【Java】InnerClass 内部类

时间:2022-06-07 15:14:34

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();
}

匿名内部类