一 概念:
匿名内部类,是内部类的简化写法。他是一个隐含了名字的内部类。开发中,最常用到的内部类就是匿名内部类了。
格式:
new 类名或者接口名(){
重写方法;
};
匿名内部类整体这个格式就包含了三部分:
- 继承/实现
- 方法重写
- 创建对象
二 格式剖析
下面一个匿名内部类例子:
Swim接口:
里面有一个show方法
public interface Swim {
public abstract void show();
}
Test测试类中定义一个匿名内部类
public class Test {
public static void main(String[] args) {
//匿名内部类
new Swim(){
@Override
public void show() {
System.out.println("重写了游泳的方法");
}
};
}
}
一、 在这个匿名内部类中呢
new Swim(){
@Override
public void show() {
System.out.println("重写了游泳的方法");
}
};
而在这个匿名内部类中真正没有名字的那个类是下面这个:
{
@Override
public void show() {
System.out.println("重写了游泳的方法");
}
}
这个部分,是一个没有名字的类,而它实现了Swim接口,所以要重写Swim里面的方法,并且因为要实现的是Swim这个接口,所以在前面加上Swim
在这个部分就体现了 :实现和方法的重写的关系:
Swim {
@Override
public void show() {
System.out.println("重写了游泳的方法");
}
}
后面的没有名字的类实现了Swim这个接口,这个部分其实可以叫做Swim的实现类
二、
我们在创建一个类的对象时候,格式是这样的
new 类名();
那创建Swim实现类的对象也是如此
new Swim(){
@Override
public void show() {
System.out.println("重写了游泳的方法");
}
};
这个意思就是,new关键字创建了下面这个Swim实现类的对象
Swim {
@Override
public void show() {
System.out.println("重写了游泳的方法");
}
}
所以就变成了最终这样:
new Swim(){
@Override
public void show() {
System.out.println("重写了游泳的方法");
}
};
而Swim后面的“()” 是采用的空参构造创建的对象。
三 总结
从二中的剖析可知,其实所谓的匿名内部类真正的含义是可以叫做匿名内部类的对象
整个匿名内部类其实就是代表一个对象,真正没有名字的那个类是不带new Swim()的部分
如果new 类名(){ 重写的方法 }; 这样是体现了继承关系
所以,综上可以看出匿名内部类整体这个格式就包含了:1. 继承/实现 。 2. 方法的重写。 3. 创建对象。这三个关系
四 应用场景
(一)在测试类中我们想要有一个狗对象,然后将狗的对象作为参数传递给测试类中的method方法,method方法中调用其对象的eat方法
老的做法是这样的:
- 先有一个Animal类(里面有一个eat方法):
public abstract class Animal {
...
...
//公共方法
public abstract void eat();
}
- 然后定义一个Dog类继承Animal类并重写eat方法:
public class Dog extends Animal{
@Override
public void eat() {
System.out.println("狗正在吃骨头");
}
}
- 然后在测试类中创建Dog对象,然后将狗的对象作为参数传递给method方法,然后method方法中使用对象调用eat方法
public class Test {
public static void main(String[] args) {
Dog dog = new Dog();
method(dog);
}
public static void method(Animal a){
a.eat();
}
}
注:
如果Dog类我只要用一次,这样的做法我还要单独定义一个Dog类,那如果还要使用Cat也只用一次也要定义一个Cat类,这样太麻烦了。
所以匿名内部类的用处就是为了简化代码
(二)使用匿名内部类后我们就可以这样做:
因为Dog对象只需要用一次,所以没必要单独定义一个Dog类
- 首先定义Animal类:
public abstract class Animal {
...
...
//公共方法
public abstract void eat();
}
- 测试类中,既然传递给method方法是一个对象,这个对象又继承了Animal类,而匿名内部类其实就是一个 创建了继承父类或者实现接口的类的对象,那可以直接将匿名内部类作为参数传递给method方法,这样只使用了一次也不用单独定义一个Dog类了,很方便:
public class Test {
public static void main(String[] args) {
//开始
method(
new Animal() {
@Override
public void eat() {
System.out.println("狗正在吃骨头");
}
}
);
//结束,方法中间是个匿名内部类作为参数
}
public static void method(Animal a){
a.eat();
}
}
那么在这里的
new Animal() {
@Override
public void eat() {
System.out.println("狗正在吃骨头");
}
}
这个匿名内部类就是Animal类的子类对象
(三) 既然匿名内部类是一个父类的子类的对象或者是接口的实现类的对象,那么匿名内部类就可以以下操作
比如:
Swim swim = new Swim(){
@Override
public void show() {
System.out.println("重写了游泳的方法");
}
};
可以用swim接收,类型是接口Swim类型
再比如:
new Swim(){
@Override
public void show() {
System.out.println("重写了游泳的方法");
}
}.swim()
既然匿名内部类是对象那么可以直接后见面使用 " . "调用方法