- 内部类
- 什么是内部类
- 为什么有内部类
- 内部类的分类
- 成员内部类
- 编写成员内部类的注意事项
- 如何创建成员内部类的对象
- 成员内部类如何获取外部类的成员变量
- 静态内部类
- 创建静态内部类的对象的格式
- 调用静态内部类中非静态方法的格式
- 调用静态内部类中静态方法的格式
- 示例2
- 局部内部类
- 示例
- 匿名内部类
- 作用
- 使用场景
- 定义格式
- 示例
配套完整代码:GitHub仓库 https://github.com/LIN-commit/java-learning 代码所在目录:java-learning/innerclass/
内部类
什么是内部类
在一个类里面,再定义一个类
public class Outer{//外部类
public class Inner{//内部类
}
}
为什么有内部类
- 需求:写一个Javabean类描述汽车
- 属性:汽车的品牌,车龄,颜色,发动机的品牌,发动机的使用年限
public class Car{//外部类:汽车
String carName;
int carAge;
int carColor;
class Engine{//内部类:发动机
String engineName;
int engineAge;
}
}
注意
- 内部类表示的事物是外部类的一部分
- 内部类单独出现没有任何意义
内部类的分类
- 成员内部类
- 静态内部类
- 局部内部类
- 匿名内部类
成员内部类
写在成员位置的,属于外部类的成员(刚才代码中的class Engine就是成员内部类)
编写成员内部类的注意事项
- 成员内部类可以被一些修饰符所修饰,比如:private(只在本类中使用),默认(只在本包中使用),protected(在本包和其他包的子类中使用),public(所有包都可以使用)等
- 在成员内部类里面,JDK16之前不能定义静态变量,JDK16开始才可以定义静态变量
如何创建成员内部类的对象
- 方式一:直接创建 格式:
外部类名.内部类名 对象名 = new 外部类名().new 内部类名();
示例:
Outer.Inner oi = new Outer().new Inner();
- 方式二:外部类编写方法,对外提供内部类对象 例如:如果内部类用private修饰,那就无法直接创建。 对应package:Test1 对应代码:
- Outer.java
- Test.java
package Test1;
public class Outer {
String name;
private class Inner{
}
public Inner getInstance(){
return new Inner();
}
}
package Test1;
public class Test {
public static void main(String[] args) {
Outer o = new Outer();
System.out.println(o.getInstance());
}
}
[运行结果]
Test1.Outer$Inner@4e50df2e
打印的是对象的地址值,且
符前是外部类名,
符前是外部类名,
符前是外部类名,符后是内部类名
成员内部类如何获取外部类的成员变量
示例 对应package:Test2 对应代码:
- Outer.java
- Test.java
package Test2;
public class Outer {
private int a = 10;
class Inner{
private int a = 20;
public void show(){
int a = 30;
System.out.println(a);//30
System.out.println(this.a);//20
System.out.println(Outer.this.a);//10
}
}
}
package Test2;
public class Test {
public static void main(String[] args) {
Outer.Inner oi = new Outer().new Inner();
oi.show();
}
}
[运行结果]
30
20
10
Outer.this表示获取了外部类对象的地址值
静态内部类
- 静态内部类实际上是成员内部类的一种,只是要用static修饰
- 静态内部类只能访问外部类中的静态变量和静态方法
示例:
public class Car{//外部类
String carName;
int carAge;
int carColor;
static class Engine{//静态内部类
public void show(){
sout(carName);//这样会报错,静态内部类无法直接访问外部类中非静态的内容
}
}
}
- 如果在静态内部类中,需要访问外部类找那个非静态的内容,需要创建外部类的对象
这个知识点和之前学过的静态方法比较类似,静态只能访问静态 示例:
public class Car{
String carName;
int carAge;
int carColor;
public static void show(){//静态方法
sout("只能访问静态变量");
}
}
示例: 对应package:Test3 对应代码:
- Outer1.java
package Test3;
public class Outer1 {
int a = 10;
static int b = 20;
//静态内部类
static class Inner{
//非静态的方法
public void show1(){
//System.out.println(a);//报错
Outer1 o = new Outer1();
System.out.println(o.a);
System.out.println(b);
}
//静态方法
public static void show2(){
//System.out.println(a);//报错
Outer1 o = new Outer1();
System.out.println(o.a);
System.out.println(b);
}
}
}
创建静态内部类的对象的格式
外部类名.内部类名 对象名 = new 外部类名.内部类名();
调用静态内部类中非静态方法的格式
先创建对象,用对象调用
调用静态内部类中静态方法的格式
外部类名.内部类名.方法名();
示例2
对应package:Test3 对应代码:
- Outer.java
- Test.java
package Test3;
public class Outer {
static class Inner{
//非静态的方法
public void show1(){
System.out.println("非静态的方法被调用了");
}
public static void show2(){
System.out.println("静态方法被调用了");
}
}
}
package Test3;
public class Test {
public static void main(String[] args) {
Outer.Inner oi = new Outer.Inner();
//调用非静态的方法
oi.show1();
//调用静态方法
Outer.Inner.show2();
}
}
[运行结果]
非静态的方法被调用了
静态方法被调用了
局部内部类
- 将内部类定义在方法里面就叫作局部内部类,类似于方法里面的局部变量
- 外界是无法直接使用,需要在方法内部创建对象并使用
- 该类可以直接访问外部类的成员,也可以访问方法内的局部变量
示例
对应package:Test4 对应代码:
- Outer.java
- Test.java
package Test4;
public class Outer {
int a = 20;
public void show(){
int b = 10;
class Inner{
String name;
int age;
public void method1(){
System.out.println(a);
System.out.println(b);
System.out.println("调用局部内部类的method1方法");
}
public static void method2(){
System.out.println("调用局部内部类的静态方法method2");
}
}
Inner i = new Inner();
System.out.println(i.name);
System.out.println(i.age);
i.method1();
Inner.method2();
}
}
package Test4;
public class Test {
public static void main(String[] args) {
Outer o= new Outer();
o.show();
}
}
[运行结果]
null
0
20
10
调用局部内部类的method1方法
调用局部内部类的静态方法method2
匿名内部类
就是一个没有名字的内部类
作用
在继承一个类或者实现一个接口的时候少写一个文件,也是lambda的前置知识点
使用场景
如果实现类只要使用一次,就可以用匿名内部类简化代码
定义格式
new 类名或者接口名(){
重写方法;
};
示例
new Inter(){
public void show(){
...
}
};
示例
对应package:Test5 对应代码:
- Swim.java
- Test.java
package Test5;
public interface Swim {
public abstract void swim();
}
package Test5;
public class Test {
public static void main(String[] args) {
Swim s= new Swim(){
@Override
public void swim() {
System.out.println("学生去游泳");
}
};
goSwimming(s);
s.swim();
}
public static void goSwimming(Swim s ){
s.swim();
}
//用静态方法goSwimming来调用,是为了演示面向接口编程、多态和代码复用的思想
}
[运行结果]
学生去游泳
学生去游泳
) { Swim s= new Swim(){ @Override public void swim() { System.out.println(“学生去游泳”); } }; goSwimming(s); s.swim(); } public static void goSwimming(Swim s ){ s.swim(); } //用静态方法goSwimming来调用,是为了演示面向接口编程、多态和代码复用的思想 }
[运行结果]
```text
学生去游泳
学生去游泳
以上就是java内部类的内容了。下一篇我们将学习创建API,欢迎继续关注蓝猫学姐的java学习笔记~






