Java InnerClass 内部类
类的成员: 属性、方法、构造器、代码块、内部类
概述
内部类是什么
将一个类A定义在另一个类B里面,里面的那个类A就称为内部类(InnerClass)
,类B则称为外部类(OuterClass)
。
为什么要声明内部类呢
具体来说,当一个事物A的内部,还有一个部分需要一个完整的结构B进行描述,而这个内部的完整的结构B又只为外部事物A提供服务,不在其他地方单独使用,那么整个内部的完整结构B最好使用内部类。
总的来说,遵循高内聚、低耦合
的面向对象开发原则。
内部类的举例(源码中)
在Thread中声明了State类,表示线程的生命周期
HashMap类中声明了Node类,表示封装的key和value
[修饰符] class 外部类{
[其他修饰符] [static] class 内部类{
}
}
内部类的分类
成员内部类、局部内部类
-
成员内部类:直接声明在外部类里面
成员内部类中,又根据是否用static修饰,分为(静态的成员内部类 \ 非静态的成员内部类)
-
局部内部类:声明在方法内、构造器内、代码块内的内部类
成员内部类中,分为(匿名的成员内部类 \ 非匿名的成员内部类 )
成员内部类
从类的角度看
- 内部类可以声明属性、方法、构造器、代码块、内部类等结构
- 此内部类可以声明父类、可以实现接口
- 可以使用final修饰
- 可以使用abstract修饰
从外部类的成员的角度来看
- 在内部可以调用外部类的结构,例如 属性、方法
- 除了使用public 缺省,还可以使用private、protected修饰(外部类只能用public和缺省)
- 可以使用static修饰
-
定义成员内部类
class Person{ //静态成员内部类 static class Dog{ } //非静态成员内部类 class Bird{ } }
-
成员内部类的实例化
public class OuterClassTest { public static void main(String[] args) { Person.Dog dog = new Person.Dog(); //创建静态成员内部类 dog.eat(); //输出 狗吃骨头 Person p1 = new Person(); //非静态成员内部类 Person.Bird bird = p1.new Bird(); bird.eat(); //鸟啄米 } } class Person{ static class Dog{ public void eat(){ System.out.println("狗吃骨头"); } } class Bird{ public void eat(){ System.out.println("鸟啄米"); } } }
-
外部类和内部类的冲突
外部类和内部类若存在同名属性、方法
直接调用属性、方法 则默认调用内部类中的属性、方法
使用
外部类.this.(方法\属性)
调用外部类的属性、方法class Person{ String name = "人"; class Bird{ String name = "鸟"; public void show(){ System.out.println("name:"+ name); //人 System.out.println("name:"+ Person.this.name); //鸟 } } } public class OuterClassTest { public static void main(String[] args) { Person p1 = new Person(); Person.Bird bird = p1.new Bird(); bird.show(); } }
细节问题:static class 类名,即静态成员内部类中 不能调用外部类的属性
局部内部类
局部内部类的使用
定义格式
public class OuterClass{
public void method(){
class A{ //局部内部类
//可以声明属性、方法等
}
}
//开发中场景(忽略)
public Comparable getInstance(){
//提供实现了Comparable接口的类
class MyComparable implements Comparable{
public int compareTo(Object o){
return 0;
}
}
return new MyComparable();
}
}
- 编译后有自己的独立的字节码文件,只不过在内部类名前面冠以外部类名、$符号、编号。
- 这里有编号是因为同一个外部类中,不同的方法中存在相同名称的局部内部类
- 和成员内部类不同的是,它前面不能有权限修饰符等
- 局部内部类如同局部变量一样,有作用域
- 局部内部类中是否能访问外部类的非静态的成员,取决于所在的方法