1、概述
匿名内部类即没有名字的内部类 。
由于没有名字,所以匿名内部类只能使用一次 ,它通常用来简化代码的编写 。
使用匿名内部类还有个前提条件:必须继承一个父类或实现一个接口 。
匿名内部类的创建方式:
new 父类构造器(参数列表)|实现接口(){
}
2、匿名内部类的初始化
我们一般都是利用构造器来完成某个实例的初始化工作,但是匿名内部类是没有构造器的,那该如何初始化匿名内部类呢?对,没错,使用构造代码块!利用构造代码块能够达到为匿名内部类创建一个构造器的效果。
1.新建一个名为AnonymousInnerClass
的Java项目,在其中新建两个包,分别为com.cxs.model
及com.cxs.test
。在model
包下新建一个名为Destination
的接口。
public interface Destination {
String readLable();
}
2.在test
包下新建一个名为InnerClassInitTest
测试类,并勾选主方法。
public class InnerClassInitTest {
public Destination destination (final String dest, final float price) {
return new Destination() {
private int cost;
private String label = dest;
{
cost = Math.round(price);
if (cost > 100 )
System.out.println("Over budget!" );
}
@Override
public String readLable () {
return label;
}
};
}
public static void main (String[] args) {
InnerClassInitTest test = new InnerClassInitTest();
test.destination("chaixingsi" , 102.34 f);
}
}
3.运行代码结果如下。
4.分析:
如果匿名内部类希望使用一个在其外部定义的对象(调用父类构造器时,传入的参数除外),那么编译器要求其参数引用是final
的(具体原因参考这里 );
构造器是与类名同名的函数,而匿名类因为没有名字,所以也就没有构造器,为了达到与构造器实例化对象的效果,可以使用代码块来进行实例初始化操作。
匿名内部类与正规的继承相比有些受限,因为匿名内部类既可以扩展类,也可以实现接口,但是不能两者兼备,并且实现接口也仅能实现一个接口。
3.匿名内部类的不同表现形式
3.1、继承式的匿名内部类
1.在model包下新建一个名为Car的类,代码如下:
public abstract class Car {
public abstract void drive ();
}
2.在test包下新建一个测试类CarTest,代码如下:
public class CarTest {
public static void main (String[] args) {
Car car = new Car() {
@Override
public void drive () {
System.out.println("Driving another car!" );
}
};
car.drive();
}
}
3.运行代码结果如下。
4.分析:建立匿名内部类的关键点是重写父类的一个或多个方法 。这里要强调的是重写父类的方法,而不是创建新的方法。因为用父类的引用不可能调用父类本身没有的方法,创建新的方法是多余的。
3.2、接口式的匿名内部类
5.修改Car的代码,将Car改为接口,代码如下;
public interface Car {
void drive();
}
6.测试类CarTest代码不变,运行代码,结果同上,图略。
7.分析:上面的代码很怪,好像是在实例化一个接口。事实却并非如此,接口式的匿名内部类是实现了一个接口的匿名类。并且只能实现一个接口。
3.3、参数式的匿名内部类(有疑问? )
public interface IWalk {
void walk();
}
public abstract class Person {
public abstract void doWalk (IWalk iWalk);
}
3.新建一个名为Children的类并继承自父类Person。
public class Children extends Person {
@Override
public void doWalk (IWalk iWalk) {
System.out.println("小孩儿会直立行走" );
}
}
public class Test {
public static void main (String[] args) {
Person person=new Children();
person.doWalk(new IWalk() {
@Override
public void walk () {
System.out.println("行走的能力" );
}
});
}
}
5.运行代码,结果如下。
4、借助匿名内部类实现多线程
从上面的三个例子可以看出,只要一个类是抽象的或是一个接口,那么在其子列中的方法都可以使用匿名内部类来实现。最常用的情况就是在多线程的实现上,因为要实现多线程,必须继承Thread类或实现Runnable接口。
4.1、Thread类的匿名内部类实现
public class Test {
public static void main (String[] args) {
Thread thread = new Thread() {
@Override
public void run () {
}
};
thread.start();
}
}
4.2、Runnable接口的匿名内部类实现
public class Test {
public static void main (String[] args) {
Runnable runnable = new Runnable() {
@Override
public void run () {
}
};
Thread thread = new Thread(runnable);
thread.start();
}
}