匿名内部类(对象)
我们已经使用过匿名对象了,匿名对象的含义是这个对象是没有名字,没有引用指向它
那么如果一个类没有名字,那么这个类就是匿名类(Anonymous Class)
显然一个正常的类是不可能没有名字的,我们今天就来介绍匿名内部类
案例
回顾一下,以往当需要一个子类对象的时候,我们需要分两步走
- 定义子类继承(实现)父类(接口)
- 创建子类对象
- 那么有没有一步直达的方式呢?
- 我们可以通过局部内部类得到一个实现子类
- 如果把局部内部类更进一步,变成匿名(局部)内部类呢?
匿名内部类的创建
-
首先明确两点使用匿名内部类的前提
- 匿名内部类是特殊的局部内部类,所以匿名内部类必须定义在局部位置
- 匿名内部类是局部内部类的更进一步
- 匿名内部类的成员特征、访问特征和局部内部类没有区别
- 存在一个已定义类或者接口,这里的类可以是具体类也可以是抽象类
- 匿名内部类是特殊的局部内部类,所以匿名内部类必须定义在局部位置
-
语法:
-
class outerClass { // 定义一个匿名类 object1 = new Type(parameterList) { // 匿名类代码 }; }
-
注意右大括号的结尾分号,不可省略
-
匿名内部类的本质是继承了一个(抽象)类或者实现了接口
匿名内部类对象的使用
- 直接使用对象去调方法即可
- 也可以用父类接收,但是父类接收无法调用子类独有方法
- 当我们只使用一次某类或者某接口的,子类对象,此时用匿名内部类对象,会稍微方便一点
- 但是,如果要多次访问,匿名内部类对象中的成员,就比较麻烦了
- 因为每一次访问都得创建一次匿名内部类对象
- 通常,在只使用一次类、接口的子类对象的情况下,比较适合使用匿名内部类对象来完成
- 本质:是一个继承了类或者实现了接口的子类匿名对象
小试牛刀
按照要求,补齐代码
要求在控制台输出”HelloWorld”
public class Test{
public static void main(String[] args) {
Outer.method().show();
}
}
interface Inter {
void show();
}
class Outer {
}
public class Test5{
public static void main(String[] args) {
Outer.method().show();
}
}
interface Inter {
void show();
}
class Outer {
// -------------改动内容--------------
public static Inter method() {
return new Inter() {
@Override
public void show() {
System.out.println("hello world !");
}
};
}
// -------------改动内容--------------
}
/**
* 运行结果:
* hello world !
*/
-
开发中的匿名内部类:
-
方法的实际参数
-
学习多态的时候我们曾经讲过,可以将父类作为形式参数,而将子类作为实际参数在方法调用的时候传入
向上转型
-
匿名内部类的匿名对象就是一个子类匿名对象,所以,可以使用匿名内部类改进以前的做法
改进前
package com.wd.day11.tset6.Demo2; /** * @author wangdezhao * @date 2021/3/11 * @description */ public class Demo2 { public static void main(String[] args) { Father f = new Son(); // 打印 "哈哈哈哈" f.print(); } } class Father { public void print() { System.out.println("我是一个父类"); } } class Son extends Father { @Override public void print() { System.out.println("哈哈哈哈"); } }
改进后
package com.wd.day11.tset6.Demo1; /** * @author wangdezhao * @date 2021/3/11 * @description * 不需要定义子类,直接可以重写,确实简便了 */ public class Test6 { public static void main(String[] args ) { // 匿名内部类继承普通类 Father f = new Father(){ @Override public void print(){ System.out.println("哈哈哈哈"); } }; f.print(); // 打印 "哈哈哈哈" // 匿名内部类继承抽象类 AbstractFather af = new AbstractFather() { @Override public void print() { System.out.println("哈哈哈哈"); } }; af.print(); // 打印 "哈哈哈哈" // 匿名内部类继承接口 IFather ifather = new IFather() { @Override public void print() { System.out.println("哈哈哈哈"); } }; ifather.print(); // 打印 "哈哈哈哈" } } //普通类 class Father{ public void print(){ System.out.println("我是父类"); } } // 抽象类 abstract class AbstractFather{ public abstract void print(); } // 接口 interface IFather{ void print(); }
-
-
方法体中,return 返回值只会执行一次,如果方法返回一个接口类型的对象,我们也可以使用匿名内部类
package com.wd.day11.tset6.Demo3; /** * @author wangdezhao * @date 2021/3/11 * @description */ public class Test3 { // 一个返回值是IA接口的方法,通过主类Test3的实例化对象去调用 public IA getIA(){ return new IA(){ @Override public void print() { System.out.println("哈哈哈哈"); } }; } // 主方法 public static void main(String[] args) { Test3 t = new Test3(); t.getIA().print(); // 直接打印 重写后的 "哈哈哈哈" } } interface IA{ void print(); }
-
通过定义匿名内部类对象,我们可以将上面的两步变为一步。
匿名内部类的前提:
存在一个类或者接口,这里的类可以是具体类也可以是抽象类。
匿名内部类的语法:
new 类名或者接口名() {重写方法;}
本质:是一个继承了类或者实现了接口的子类匿名对象
匿名内部类的使用优缺点:
1,当我们只使用一次某类或者某接口的子类对象时,使用匿名内部类,会稍微方便一点
2,如果需要多次访问子类对象的成员,匿名内部类很麻烦。
3,如果访问匿名子类中的独有方法,必须用匿名对象去访问