Java SE内部类(Inner classes)
CAMELLIA!!! note 目录
内部类
一、实例内部类/成员内部类(Member Inner Class):
- 成员内部类是定义在外部类的成员位置的类,可以直接访问外部类的所有成员变量和方法,包括私有成员。
- 成员内部类可以使用访问控制修饰符(如public、private、protected、default)。
- 外部类可以访问成员内部类的所有成员,但需要先创建内部类的对象
当一个成员内部类(非静态内部类)被定义在外部类中时,外部类可以访问内部类的所有成员,但是需要先创建内部类的对象。下面是一个示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| public class OuterClass { private int outerMember = 10;
public void outerMethod() { System.out.println("Outer Method"); }
class InnerClass { private int innerMember = 20;
public void innerMethod() { System.out.println("Inner Method"); } } public static void main(String[] args) { OuterClass outer = new OuterClass(); OuterClass.InnerClass inner = outer.new InnerClass(); System.out.println(inner.innerMember); inner.innerMethod(); } }
|
在这个示例中,InnerClass
是一个成员内部类,它被定义在OuterClass
中。在main()
方法中,首先创建了外部类的实例outer
,然后通过该实例创建了内部类的实例inner
。接着,外部类可以通过内部类的实例inner
访问内部类的所有成员,包括innerMember
成员和innerMethod()
方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| public class OuterClass { public int i = 100; public void m1(){ System.out.println("外部类的实例方法m1执行了"); }
private static int j = 200; public static void m2(){ System.out.println("外部类的静态方法m2执行了"); }
public class InnerClass { public void x(){ System.out.println(i); System.out.println(j); m1(); m2(); } }
}
|
1 2 3 4 5 6 7 8
| public class OuterClassTest { public static void main(String[] args) { OuterClass outerClass = new OuterClass(); System.out.println(outerClass.i); OuterClass.InnerClass innerClass = outerClass.new InnerClass(); innerClass.x(); } }
|
二、静态内部类(Static Inner Class)
- 静态内部类使用 static 关键字修饰,与外部类的实例无关,可以直接访问外部类的静态成员。
- 静态内部类不能直接访问外部类的非静态成员,但可以通过创建外部类的实例来访问。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| public class OuterClass {
private static int i = 100;
private int j = 200;
public static void m1(){ System.out.println("外部类的m1静态方法执行了"); }
public void m2(){ System.out.println("外部类的m2实例方法执行了"); }
private static class InnerClass { public void m3(){ System.out.println(i); m1(); } public static void m4(){ System.out.println(i); m1(); } }
public static void main(String[] args) { InnerClass innerClass2 = new InnerClass(); innerClass2.m3(); InnerClass.m4(); } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13
| public class OuterClassTest { public static void main(String[] args) { OuterClass.InnerClass innerClass = new OuterClass.InnerClass(); innerClass.m3();
OuterClass.InnerClass.m4(); } }
|
在Java中,静态内部类不能直接访问外部类的非静态成员,但可以通过创建外部类的实例来访问。下面是一个简单的示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| public class OuterClass { private int outerMember = 10;
public void outerMethod() { System.out.println("Outer Method"); }
static class StaticInnerClass { public void innerMethod() { } } public static void main(String[] args) { OuterClass outer = new OuterClass(); System.out.println(outer.outerMember); } }
|
在这个示例中,StaticInnerClass
是一个静态内部类,它不能直接访问外部类OuterClass
的非静态成员outerMember
,因此在innerMethod()
方法中,如果尝试直接访问outerMember
,会导致编译错误。但是,通过创建OuterClass
的实例,我们可以访问外部类的非静态成员,比如在main()
方法中,我们创建了一个OuterClass
的实例outer
,并且通过该实例访问了outerMember
成员。
三、局部内部类(Local Inner Class):
- 局部内部类定义在方法或作用域内部,只能在所在的方法或作用域内使用。
- 结论:局部内部类能不能访问外部类的数据,取决于局部内部类所在的方法。
- 如果这个方法是静态的:只能访问外部类中静态的。
- 如果这个方法是实例的:可以都访问。
- 局部内部类可以访问外部类的成员变量和方法,但只能访问 final 或 effectively final 的局部变量(只不过从JDK8开始。这个final关键字不需要提供了。系统自动提供。)。
- 局部内部类不能使用访问权限修饰符修饰。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| public class OuterClass {
private static int k = 1; private int f = 2;
public void m1(){ int i = 100; class InnerClass { public void x(){ System.out.println(k); System.out.println(f); System.out.println(i); } } InnerClass innerClass = new InnerClass(); innerClass.x(); }
public static void m2(){ int i = 100; class InnerClass { public void x(){ System.out.println(k); } } } }
|
1 2 3 4 5 6 7
| public class OuterClassTest { public static void main(String[] args) { OuterClass outerClass = new OuterClass(); outerClass.m1(); } }
|
四、*匿名内部类(Anonymous Inner Class):
- 匿名内部类是没有显式名称的内部类,通常用于实现接口或继承父类,并在创建对象时进行定义。
- 匿名内部类不能定义构造方法,但可以初始化块和成员变量。
- 匿名内部类可以访问外部类的成员变量和方法,以及方法内的 final 局部变量。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public class Outer { public void methodWithInterface() { MyInterface myInterface = new MyInterface() { @Override public void interfaceMethod() { System.out.println("Implementation of interface method"); } }; myInterface.interfaceMethod(); } }
interface MyInterface { void interfaceMethod(); }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
| public class Test { public static void main(String[] args) { Computer computer = new Computer();
computer.conn(new Usb(){ @Override public void read() { System.out.println("read....."); }
@Override public void write() { System.out.println("write....."); } }); } }
class Computer { public void conn(Usb usb){ usb.read(); usb.write(); } }
interface Usb { void read(); void write(); }
|