内部类的访问规则
- 内部类可以直接访问外部类中的成员,包括私有成员。
因为内部类中持有了一个外部类的引用,格式为:外部类名.this - 外部类要访问内部类,必须要建立内部对象。
class Outer { //外部类 private int x = 1; class Inner{ //内部类 int x = 2; void function() { int x = 3; System.out.println(x); System.out.println(this.x); System.out.println(Outer.this.x); } } void method() { Inner in = new Inner(); in.function(); } } public class InnerClassDemo { public static void main(String[] args) { Outer out = new Outer(); out.method(); Outer.Inner in = new Outer().new Inner(); in.function(); } }
运行结果:
3 2 1 3 2 1
访问
- 当内部类定义在外部类的成员位置上,而且非私有,可以在外部其他类中直接建立内部类对象。
格式: 外部类名.内部类名 变量名 = 外部类对象.内部类对象; - 当内部类在成员位置上,就可以被成员修饰符所修饰。
例如:private,将内部类在外部类中进行封装。
static:使得内部类具有static的特性。(当内部类被static修饰后,只能直接访问外部类中的static成员,出现了访问的局限。)
静态内部类
- 在外部其他类中,如何直接访问静态内部类的非静态成员
class Outer { private static int x = 1; static class Inner { void function() { System.out.println(x); } } } public class InnerDemo2 { public static void main(String[] args) { new Outer.Inner().function(); } }
- 在外部其他类中,如何直接访问静态内部类的静态成员
class Outer { private static int x = 1; static class Inner { static void function() { System.out.println(x); } } } public class InnerDemo3 { public static void main(String[] args) { Outer.Inner.function(); } }
- 当内部类中定义了静态成员,该内部类必须也是静态的
以下代码编译会导致编译错误
class Outer { private static int x = 1; class Inner { //此内部类中定义了静态成员但是此内部类不为静态 static void function() { System.out.println(x); } } } public class InnerDemo3 { public static void main(String[] args) { Outer.Inner.function(); } }
- 当外部类中的静态方法访问内部类时,内部类也必须是静态的。
内部类的定义原则
当描述一个事物时,这个事物的内部有事物,此时这个内部的事物需要使用内部类来描述。
局部内部类
- 内部类定义在局部时:
- 不可以被成员修饰符修饰。
- 可以直接访问外部类中的成员,因为还持有外部类中的引用。但是不可以访问它所在的局部变量,只能访问被final修饰的局部变量。(目前版本的jdk中,final可以省略)
class Outer { void method(final int x) { class Inner { void function() { System.out.println(x); } } new Inner().function(); } } public class InnerDemo4 { public static void main(String[] args) { Outer out = new Outer(); out.method(7); out.method(8);//因为局部变量在栈内存中,每次一调用入栈,使用结束出栈。所以虽然是被final修饰,但是仍然可以重复调用。 } }
运行结果:
7 8
匿名内部类
- 匿名内部类其实是内部类的简写格式。
- 定义匿名内部类的前提:
内部类必须是继承一个类或者实现接口。 - 匿名内部类的格式:new 父类或者接口(){定义子类的内容}
abstract class Abs { abstract void method(); } class Outer { int x = 3; /*class Inner extends Abs { @Override void mthod() { System.out.println(x); } }*/ public void function() { //new Inner().mthod(); new Abs() { @Override void method() { System.out.println(x); } }.method(); } } public class InnerDemo5 { public static void main(String[] args) { new Outer().function(); } }
运行结果
3
以上代码将注释部分,用匿名内部类的形式体现了出来。
- 匿名内部类是一个匿名子类对象。可以理解为带内容的对象。
- 匿名内部类中定义的方法最好不要超过3个。
- 如果一个类既没有实现接口也没有继承父类,可以使用Object类来创建匿名内部类。
例如:
public class InnerClassTest { public static void main(String[] args) { new Object() { //如果左边有Object类型引用(Object ob = ),将无法调用method方法 public void method() { System.out.println("method run"); } }.method(); } }
练习
interface Inter { void method(); } class Test { //补足代码,通过匿名内部类 } public class InnerClassTest { public static void main(String[] args) { Test.function().method(); } }
分析 Test.function().method(); 这行代码可以发现function()应该是Test类中一个静态方法,function()方法后面还有一个method()的调用,说明调用function()方法应是返回了一个对象而且是Inner类型的对象,从而才能继续调用method()方法。
可以得到以下代码:
interface Inter { void method(); } class Test { //补足代码,通过匿名内部类 static Inter function() { //这里返回值类型为Inner return new Inter(){ @Override public void method() { System.out.println("Hello World"); } }; } } public class InnerClassTest { public static void main(String[] args) { Test.function().method(); } }
来源:https://www.cnblogs.com/liyuxin2/p/12324375.html