内部类(JDK1.1)
定义在其他类内部的类成为内部类,或称嵌套类;包含内部类的类为外部类,或宿主类
内部类作为外部类成员,可直接访问外部类私有数据,但外部类不能直接访问内部类的实现细节
内部类比外部类可多使用三个修饰符:private、protectd、static
参考链接:Java的外部类,为什么只能使用public和default进行修饰_java public default一起用-CSDN博客
Java内部类包括成员内部类(非静态内部类、静态内部类)、局部内部类、匿名内部类
成员内部类:非静态内部类
不允许在非静态内部类中定义静态成员
非静态内部类对象中,保存了一个寄生的外部类对象的引用,即{外部类类名}.this
显示创建内部类实例对象来调用访问其实例成员
DiscernVariable.java
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
| public class DiscernVariable { private String prop = "外部类的实例变量"; private class InClass { private String prop = "内部类的实例变量"; public void info() { String prop = "局部变量"; System.out.println("外部类的实例变量值:" + DiscernVariable.this.prop); System.out.println("内部类的实例变量值:" + this.prop); System.out.println("局部变量的值:" + prop); } } public void test() { InClass in = new InClass(); in.info(); } public static void main(String[] args) { new DiscernVariable().test(); } }
|
外部类以外调用非静态内部类
内部类完整类名 OutClass.InnerClass
必须先创建外部类对象然后outerInstance.new InnerConstructor()
创建内部类实例
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
| class Out { class In { public In(String msg) { System.out.println(msg); } } } public class CreateInnerInstance { public static void main(String[] args) { Out.In in = new Out().new In("测试信息");
} }
|
成员内部类:static 静态内部类
属于外部类本身,只能访问外部类类成员,而不能访问外部类实例成员
静态内部类可包含静态和非静态成员,但非静态成员也无法访问外部类实例成员
静态内部类对象只持有外部类的引用,没有持有外部类对象的引用。如果允许静态内部类的实例方法访问外部类的实例成员,但找不到被寄生的外部类对象,这将引起错误。
外部类可通过静态内部类类名访问其类成员,或通过静态内部类对象访问其实例成员
CreateStaticInnerInstance.java
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
| class StaticOutS { static class StaticIn { public StaticIn() { System.out.println("静态内部类的构造器"); } } } public class CreateStaticInnerInstance { public static void main(String[] args) { StaticOut.StaticIn in = new StaticOut.StaticIn();
} }
|
局部内部类
局部内部类在方法中定义,仅在方法中有效,不能使用访问控制符
和static
修饰
LocalInnerClass.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| public class LocalInnerClass { public static void main(String[] args) { class InnerBase { int a; } class InnerSub extends InnerBase { int b; } InnerSub is = new InnerSub(); is.a = 5; is.b = 8; System.out.println("InnerSub对象的a和b实例变量是:" + is.a + "," + is.b); } }
|
生成LocalInnerClass.class,LocalInnerClass$1InnerBase.class,LocalInnerClass$1InnerSub.class
匿名内部类
匿名内部类适合创建一次性使用的类
匿名内部类创建时立即创建一个实例,类定义立即消失,不能重复使用
匿名内部类必须继承一个父类,或实现一个接口,但最多只能继承一个父类,或实现一个接口
1 2 3 4 5
| new 实现接口() | 父类构造器(实参列表) { }
|
实现例子:
AnonymousInner.java
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 53 54 55 56 57 58
| abstract class Device { private String name; public abstract double getPrice(); public Device(){} public Device(String name) { this.name = name; } public void setName(String name) { this.name = name; } public String getName() { return this.name; } } public class AnonymousInner { public void test(Device d) { System.out.println("购买了一个" + d.getName() + ",花掉了" + d.getPrice()); } public static void main(String[] args) { AnonymousInner ai = new AnonymousInner(); ai.test(new Device("电子示波器") { public double getPrice() { return 67.8; } }); Device d = new Device() { { System.out.println("匿名内部类的初始化块..."); } public double getPrice() { return 56.2; } public String getName() { return "键盘"; } }; ai.test(d); } }
|
匿名内部类访问的局部变量必须按有final修饰的来用,如示例中的age,Java8以后会自动修饰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
| interface A { void test(); } public class ATest { public static void main(String[] args) { int age = 8;
A a = new A() { public void test() { System.out.println(age); } }; a.test(); } }
|