10-14,匿名内部类-概述
匿名内部类就是内部类的简写格式。
必须有的前提是:
内部类必须继承或实现一个外部类或接口。
匿名内部类:
其实就是一个匿名子类对象。
格式:
new父类 or 接口() { 子类内容 }
例如:
abstract class Demo {
abstract void show();
}
class Outer {
int num = 4;
/* 非匿名方法
class Inner extends Demo {
void show() {
System.out.println("show ... " + num);
}
}
*/
public void method() {
//new Inner().show(); //对应上面非匿名方法,
new Demo { //匿名内部类,继承了外部类Demo
//new了一个匿名子类对象并调用show方法,子类中重写Demo的抽象方法
void show() {
System.out.println("show ..." + num);
}
}.show();
}
}
class InnerClassDemo {
public static void main(String[] args) {
new Outer().method();//new 一个Outer对象并调用其method方法。
}
}
10-15,匿名内部类-应用
使用场景:
当函数参数是接口类型时,而且接口中的方法不超过三个。
可以用匿名内部类作为实际参数进行传递。
class InnerClassDemo {
class Inner {}
public static void main(String[] args) {
/* 接口类型参数传递,在传递时直接实现方法
show(new Inter(){
public void show1() {
System.out.println("show1...");
}
public void show2() {
System.out.println("show2...");
}
});
*/
new Inner();
}
public void method() {
new Inner();
}
public static void show(Inter in) {//接口形参
in.show1();
in.show2();
}
}
interface Inter {
void show1();
void show2();
}
class Outer {
/* 非匿名方式
class Inner implements Inter {
public void show1() {
System.out.println("show1...");
}
public void show2() {
System.out.println("show2...");
}
}
*/
public void method() {
Inner in = new Inner();
in.show1();
in.show2();
//给匿名内部类起个名字,用该名字调用里面的show1,show2方法。
Inter in = new Inter() {
public void show1() {
System.out.println("show1...");
}
public void show2() {
System.out.println("show2...");
}
};
in.show1();
in.show2();
}
}
若匿名内部类中只有一个方法,可以这么调用:
new Inter() {
public void show() {
System.out.println("show run ... ");
}
}.show();
10-16,匿名内部类-细节
class Outer {
void method() {
//前面的Object表示父类对象,后面的Object表示子类对象。
//这里是多态,把new Object向上转型为Object型,编译时看等号左边,
//因为Object类中没有show方法,所以编译失败。
Object obj = new Object() {
public void show() {
System.out.println("show run ... ");
}
};
obj.show(); // 报错,找不到show方法。
}
}
class InnerClassDemo {
public static void main(String[] args) {
new Outer().method();
}
}
报错原因:因为匿名内部类这个子类对象被向上转型为了Object类型,这样就不能再使用子类的特有方法了。
10-17,对象的初始化过程:
代码示例:
class Fu {
int num = 9;
{ // 构造代码块
System.out.println("Fu"); //第一步:打印 Fu
}
Fu() {
super();
//显示初始化
//构造代码块初始化
show();
}
void show() {
//这个show会被子类的show覆盖
System.out.println("fu show " + num); //第二步:打印Zi类中的show:Zi show 0
}
}
class Zi extends Fu {
int num = 8;
{
System.out.println("Zi"); //第三步:打印 Zi
}
Zi() {
super();
//显示初始化
//构造代码块初始化
show();
}
void show() {
System.out.println("Zi show " + num); //第四步:打印Zi show 8
}
}
public class Demo {
public static void main(String[] args) {
new Zi();
}
}
步骤:
(1)Demo类加载进方法区,Demo的构造函数加载进方法区。
(2)main方法加载进静态方法区,main进栈。
(3)new Zi()在堆中创建子类对象,在这个内存块中开辟两块空间,分别为Zi的num = 0,Fu的num = 0。
(4)Fu类先加载进方法区,Zi类后加载进方法区。
(5)new Zi();时调用Zi的构造函数,Zi中的super调用Fu的构造函数,Fu()先执行super这里super调用的是Object,然后执行成员变量的显示初始化,然后执行本类中构造代码块的初始化,这时输出Fu,然后再执行sho