Java - 内部类
一个类的内部 又完整地嵌套了另一个类结构,被嵌套的内为 内部类
内部类 - 外部类 - 外部其他类
类的五大成员:属性;方法;构造器;代码块;内部类
class Outer{
class Inner{
}
}
定义在外部类 局部位置 上(通常在 方法 /代码块 中)
局部内部类(有类名)
- 本质还是一个类,作用域在 定义它的方法或代码块中
- 可以直接访问外部类的所有成员,包括私有的
- 不能添加访问修饰符,可以使用 final 修饰
class Outer{
private int n = 1;
private void m2(){}
public void m1(){
// 不能添加访问修饰符,可以使用 final 修饰
class Inner01{ // 本质还是一个类,作用域在 定义它的方法或代码块中
// 可以直接访问外部类的所有成员,包括私有的
public void f1(){
System.out.println("n1="+n1);
m2();
}
}
class Inner02 extends Inner01{}
// 外部类在方法中可以创建Inner对象,然后调用方法即可
Inner01 in = new Inner01();
in.f1();
}
}
匿名内部类(没有类名)
new 类或接口(参数列表){
}
- 本质是类,作用域在 定义它的方法或代码块中
- 该类没有名字(但系统会分配一个我们看不到的名字)
- 匿名内部类 使用一次就不能再使用了
- 可以直接访问外部类的所有成员,包括私有的
- 同时 还是一个对象
- 是 局部变量,不能使用访问修饰符
- 外部类与匿名内部类的成员重名时,匿名内部类的访问遵循就近原则,使用
外部类.this.成员
访问外部成员
class A{
private n1 = 1;
public A(){}
public void me(){
// ia编译类型:IA,运行类型:匿名内部类
// jdk底层创建匿名内部类后立马创建了对象
IA ia = new IA(){
@override
public void cry(){
System.out.println("...");
}
};
ia.cry();
ia.getClass(); // A$1
// 参数列表会传给 Father 的构造器
Father f = new Father("Hu"){
private n1 = 88;
@override
public void test(){
System.out.println("匿名内部类重写了test()");
// 访问外部 n1
System.out.println(A.this.n1); // 1
}
};
f.getClass(); // A$2
}
}
interface IA{
void cry();
}
class Father{
public Father(String name){}
public void test(){}
}
最佳实践
当作实参直接传递
class Main{
public static void main(String[] args){
f1(new IL(){
@Override
public void show(){
System.out.println("show");
}
});
}
public static f1(IL il){
il.show();
}
}
interface IL{
void show();
}
定义在外部类 成员位置 上
成员内部类(没用static修饰)
class Main{
public static void main(String[] args){
// 外部其它类访问成员内部类1
Outer ot = new Outer();
Outer.Inner inner1 = ot.new Inner();
// 外部其它类访问成员内部类2
Outer.Inner inner2 = ot.getInnerInstance();
}
}
class Outer{
private int n1 = 1;
public class Inner{
private double sal = 99.8;
public void say(){
System.out.println(n1); // 直接访问外部类成员
}
}
public void t1(){
// 创建对象再访问
Inner inner = new Inner();
inner.say();
System.out.println(sal); // 99.8
}
// 返回成员内部类对象的方法
public Inner getInnerInstance(){
return new Inner();
}
}
-
作用域为整个类
-
成员内部类 可以直接访问外部类的所有成员,包括私有的
-
外部类 访问 成员内部类 需要创建对象再访问
-
外部其它类访问成员内部类 有两种方法
-
可以添加任意访问修饰符,因为 它的地位是成员
- 成员内部类是外部类的一部分,这种嵌套关系使得外部类能够访问内部类的所有成员,包括私有成员
-
外部类与成员内部类的成员重名时,匿名内部类的访问遵循就近原则,使用
外部类.this.成员
访问外部成员
静态内部类(使用static修饰)
class Main{
public static void main(String[] args){
// 外部其它类访问静态内部类1
Outer.Inner inner1 = new Outer.Inner();
// 外部其它类访问静态内部类2
Outer.Inner inner2 = new Outer.getInner();
Outer.Inner inner3 = Outer.get_Inner();
}
}
class Outer{
private int n = 10;
private static String name = "hello";
static class Inner{
public void say(){
System.out.println(name);
}
public Inner getInner(){
return new Inner();
}
public static Inner get_Inner(){
return new Inner();
}
}
}
- 作用域为整个类
- 静态内部类 可以直接访问外部类的所有静态成员,包括私有的,但不能访问非静态成员
- 外部类 访问 静态内部类 需要创建对象再访问
- 外部其它类访问静态内部类 有两种方法
- 可以添加任意访问修饰符,因为 它的地位是成员
- 外部类与静态内部类的成员重名时,静态内部类的访问遵循就近原则,使用
外部类.成员
访问外部静态成员