【Java】InnerClass 内部类
Java 允许一个类的定义位于另一个类的内部,前者为内部类,后者称为外部类
InnerClass一般定义它的类或语句块之中外部类引用时必须给出完整的名称
成员内部类 & 局部内部类
- 静态成员 内部类
- 非静态成员 内部类
- 匿名内部类
静态内部类 成员内部类 局部内部类
// 相对于内部类而言,这是一个外部类 public class OuterClass { public int a; int b; protected int c; private int d; static int e; public void memberMethod(){ System.out.println("外部类的成员方法!"); // 成员内部类可以创建实例 InnerClass innerClass = new InnerClass(); // 静态内部类可以创建实例 StaticInnerClass staticInnerClass = new StaticInnerClass(); } public static void staticMethod(){ System.out.println("外部类的静态方法!"); } // 成员内部类和静态内部类 都可以abstract抽象 或者final,都可以被4种权限访问修饰 // 成员内部类 不允许任何静态存在 class InnerClass{ // 成员内部类可以修饰所有访问权限 public int a; int b; protected int c; private int d; // 成员内部类不能写静态方法 // static void staticMethod(){} // 成员内部类可以声明成员方法 void memberMethod(){ // 成员内部类可以调用外部类的成员方法 OuterClass.this.memberMethod(); // 成员内部类外部类的静态方法也能被调用 OuterClass.staticMethod(); } // 成员内部类可以构造器 InnerClass(){} // 各个字段的访问 public void checkField(int a){ // 形参的a a = 50; // 本成员内部类的字段a this.a = 100; // 外部类的字段a OuterClass.this.a = 150; } } // 静态内部类 static class StaticInnerClass{ // 静态内部类可以修饰所有访问权限 public int a; int b; protected int c; private int d; // 静态内部类可以声明成员方法 void memberMethod(){ // 可以调用外部类的静态方法 OuterClass.staticMethod(); // 外部类的成员方法不行 // OuterClass.this.memberMethod(); } // 静态内部类可以声明静态方法 static void staticMethod(){ // 可以调用外部类的静态方法 OuterClass.staticMethod(); // 外部类的成员方法不行 // OuterClass.this.memberMethod(); } public void fieldCheck(int a){ // 形参字段 a = 100; // 静态内部类的字段 this.a = 150; // 外部类字段 只能访问静态方法和静态字段 OuterClass.e = 300; } // 静态内部类也可以构造器 StaticInnerClass(){} } public void classMethod(){ // 局部内部类 没有权限访问修饰,只做用在这个方法之内 ,可以设置final修饰局部内部类 // 被内部类所访问的局部变量必须是Final的 // x的作用域之存活于这个方法中 // 当方法调用结束,方法出栈,x变量即被销毁掉 final int x = 123; // 局部内部类 class LocalInnerClass{ // 但是局部内部类的实例依然才在,依然保持这个x变量的引用指向 // 如果在局部方法被销毁后调用这个方法,就无法再访问这个x变量,这就是BUG问题 // 但是在JDK8已经默认隐式的表示这个x变量是final修饰的,x必须是一个常量的存在 // 即表示如果x被销毁,但其值不发生变化,依然是可以被访问赋予的 // 这个原因在于 局部内部类的实例的作用域大于了这个变量的作用域 public int returnX(){ // x += 100; x变量不能被修改 return x; } } } // 局部内部类的用法,可以用于返回一个实现某接口的实例出来 public Comparable getComparable(){ class LocalInnerClass implements Comparable{ // 局部内部类重写接口方法 @Override public int compareTo(Object o) { return 0; } } // 返回给外部调用 return new LocalInnerClass(); } }
静态内部类 和 成员内部类在外部的实例创建与访问
public class ClassTest { public static void main(String[] args) { // 实例化静态内部类 OuterClass.StaticInnerClass staticInnerClass = new OuterClass.StaticInnerClass(); // 静态内部类的成员方法 staticInnerClass.memberMethod(); // 静态内部类的静态方法 OuterClass.StaticInnerClass.staticMethod(); // 实例化成员内部类,必须要有外部类的实例才可以 OuterClass outerClass = new OuterClass(); //先创建外部实例 OuterClass.InnerClass innerClass = outerClass.new InnerClass(); //再通过外部实例调用内部初始化 // 也可以直接匿名外部类对象,调用内部类初始化 OuterClass.InnerClass innerClass2 = new OuterClass().new InnerClass(); // 成员内部类调用成员方法 innerClass.memberMethod(); } }
匿名内部类
public class ClassTest { public static void main(String[] args) { AnonymousInnerClass anonymousInnerClass = new AnonymousInnerClass() { // 这就是匿名内部类的类体,匿名,顾名思义,没有类的名字 // 重写接口的方法 @Override public void aicMethod() { System.out.println("这就是匿名内部类"); } // 匿名内部类只能声明这一次,不能像显示的类一样保存下来 // 用于创建去实现一个接口或者继承一个抽象类,或者继承普通类也可以 // 适用于实现只有一个方法的接口,例如多线程的Runnable // 注意线程还有一个Callable可以使用 }; } } // 声明一个接口和一个抽象方法 interface AnonymousInnerClass{ void aicMethod(); }