概念
将一个类A定义在另一个类B里面,里面的那个类A就称为内部类,B则称为外部类。
成员内部类
定义在类中方法外的类。
定义
class 外部类 {
class 内部类{ }
}
使用
1)间接使用,在外部类的方法中使用内部类,main方法只是使用外部类方法
2)直接使用
外部类名.内部类名 对象名 = new 外部类型().new 内部类型()
重名问题
注意
1)内部类使用外部类–随意使用
2)外部类使用内部类–必须使用内部类对象
3)内部类仍然是一个独立的类,在编译之后会内部类会被编译成独立的.class文件,但是前面冠以外部类的类名 和$符号 。
局部内部类
定义
如果一个类定义在方法内部,该类即为局部内部类
修饰符 class 外部类名称{
修饰符 返回值类型 外部类方法名称(参数列表){
class 局部内部类名称{
//...
}
}
}
使用
final
局部内部类,如果希望访问所在方法的局部变量,那么这个局部变量必须是【有效final的】
备注:从Java 8+开始,只要局部变量事实不变,那么final关键字可以省略
原因:
1)new出来的对象存在堆内存中
2)局部变量跟着方法,在栈内存中
3)方法运行结束之后,立即出栈,局部变量会立即小时
4)new出的对象会在堆中持续存在,直到垃圾回收消失
匿名内部类
内部类的简化写法
本质是一个 带具体实现的 父类或者父接口的 匿名的子类对象。
前提
继承一个父类或者实现一个父接口
定义
new 父类名或者接口名(){
// 方法重写
@Override
public void method() { // 执行语句 }
1)new代表创建对象的动作
2)接口名称就是匿名内部类需要实现那个接口
3){...}
才是匿名内部类的内容
使用
以接口为例:
接口:
public abstract class FlyAble{
public abstract void fly();
}
创建匿名内部类并调用
public class InnerDemo {
public static void main(String[] args) {
/*
1.等号右边:是匿名内部类,定义并创建该接口的子类对象
2.等号左边:是多态赋值,接口类型引用指向子类对象
*/
FlyAble f = new FlyAble(){
public void fly() {
System.out.println("我飞了~~~");
}
};
//调用 fly方法,执行重写后的方法
f.fly();
}
}
注意事项
1)匿名内部类在创建对象时,只能使用唯一一次
如果希望多次创建对象,而且类的内容一样的话,必须使用单独定义的实现类
2)匿名对象,在调用方法的时候,只能调用唯一的一次
如果希望同一个对象,调用多次方法,必须借助多态给对象起一个名字
3)匿名内部类省略【实现类/子类名称】,匿名对象省略【对象名称】