内部类
成员内部类
-
一个类可以定义在另外一个类的内部,定义在类内部的类称之为Inner,其所在的类称之为Outer;
-
Inner定义在Outer的内部,通常只服务于Outer,对外部不具备可见性,Inner可以直接调用Outer的成员及方法(包括私有的)。
-
一般情况下,Inner对象会在Outer对象中创建(构造方法或其他方法);Inner对象中会有一个隐式的引用指向创建它的Outer类对象。
内部类结构
- 可以定义非静态属性和方法,不可以定义static修饰的属性和方法,可以定义static final修饰的编译期变量【不用加载类的字节码】
- 首先内部类是外部类的一个成员,只有当外部类初始化的时候,内部类才能初始化,静态变量属于类级别,在类加载的时候就初始化,所有两者本身在语法上就有矛盾。
- 首先要先知道static final修饰的变量叫做常量,常量分为编译期常量和非编译期常量
- 编译期常量:在程序编译阶段【不需要加载类的字节码】,就可以确定常量的值
- 非编译期常量:在程序运行阶段【需要加载类的字节码】,可以确定常量的值
public class Outer {
//成员变量
int num = 1;
//成员方法
public void OuterMethod(){
int b = 2;
System.out.println("这是外部类方法");
class Inner{
/*
int aaa = 1;
static int a =1;//静态变量 报错
static final int b = 0;//编译期常量,不需要类加载
static final InterfaceAImpl = new InterfaceAImpl();//非编译期常量,需要类加载 报错
*/
int c = 0;
public void innerMethod(){
System.out.println("这是内部类方法");
System.out.println(num);
System.out.println(c);
System.out.println(b);
}
}
Inner inner = new Inner();
inner.innerMethod();
}
}
内部类访问外部类
- 访问方法有两种:直接写属性名或者外部类加.this.属性
- 直接写属性名可能会产生外部类和内部类属性命名相同导致发生隐藏现象,取得的是内部类的值,若要访问外部类则需要外部类.this.属性。
外部类访问内部类
-
创建内部类对象
Outter.Inner in = new Outter().new Inner();
-
创建静态内部类对象
Outer.InnerStatic innerStatic = new Outer.InnerStatic();
匿名内部类
- 如果在一段程序中需要创建一个类的对象(通常这个类需要实现某个接口或者继承某个类),而且这个对象创建后,这个类的价值也就不存在了,这个类可以不必命名,称之为匿名内部类。
- 匿名内部类与局部类对作用域内的变量拥有相同的的访问权限。
- 匿名内部类可以访问外部内的所有成员;
- 匿名内部类不能访问外部类未加final修饰的变量(注意:JDK1.8即使没有用final修饰也可以访问);
- 属性屏蔽,与内嵌类相同,匿名内部类定义的类型(如变量)会屏蔽其作用域范围内的其他同名类型(变量):
public class Outer {
public void outerM1() {
//创建接口的实现类对象
/* InterfaceAImpl interfaceA = new InterfaceAImpl();
interfaceA.MethodAbs1();
interfaceA.MethodAbs2();*/
//只想使用一次
//匿名内部类
//需求:使用接口 -> 接口不能new - > new 接口的实现类
//new: 创建InterfaceA的实现类 - > InnerAImpl 实现类
//InterfaceA: 要实现的接口
//{}:真正的实现类
InterfaceA in = new InterfaceA() {
@Override
public void MethodAbs1() {
}
@Override
public void MethodAbs2() {
}
};
in.MethodAbs1();
in.MethodAbs2();
//匿名对象(一般不用)
new InterfaceA() {
@Override
public void MethodAbs1() {
}
@Override
public void MethodAbs2() {
}
}.MethodAbs2();
new InterfaceA() {
@Override
public void MethodAbs1() {
}
@Override
public void MethodAbs2() {
}
}.MethodAbs1();
}
}