一 . 匿名内部类的基本语法:
new 类 / 接口(参数){
类体
} ;
匿名内部类本质是一个类 , 通常写在方法中 , 没有名字(名字是由系统给出的) , 同时也是一个对象 ;
二 . 基于接口的匿名内部类 :
1. 对于接口来说什么时候最好使用匿名内部类 :
interface A //接口
{
public void cry();
}
class Tiger implements A
{
@Override
public void cry()
{
System.out.println("老虎..");
}
}
class TestMain
{
public static void main(String[] args) {
//向上转型
A tiger=new Tiger();
//只使用一次,还得再新创建一个Tiger类去实现接口A, 很麻烦
tiger.cry();
}
}
2. 为了避免这种只使用一次这个Tiger类 , 并且还要再创建这个类来实现接口的这种情况, 我们可以采用匿名内部类 来简化开发 , 就不需要再新创建一个Tiger类了 :
public class Outer { //外部类
private int n1=100;
//在方法内写匿名内部类
public void method()
{
//tiger 的编译类型:接口A;
//tiger 的运行类型:不是接口A,因为接口是抽象类创建不了对象的,tiger的运行类型就是匿名内部类;
A tiger=new A() {
@Override
public void cry() {
System.out.println("老虎..");
}
};
tiger.cry();
}
}
interface A //接口
{
public void cry();
}
class TestMain
{
public static void main(String[] args) {
//使用外部类来创建对象
Outer tiger=new Outer();
//调用方法
tiger.method();
}
}
3. 在底层创建了匿名内部类 Outer$1 , 立即就new创建了实例对象 (这也就是为什么说匿名内部类还是一个对象) , 并把地址返回给tiger ,所以tiger此时引用的是Outer$1的对象:
解释匿名内部类为什么也是对象 : 因为匿名内部类实现接口 / 继承父类后 ,由于匿名内部类的格式是new 接口/父类 ,所以会直接创建对象 , 所以在使用匿名内部类的时候它本质就是一个对象 .
public class Outer { //外部类
private int n1=100;
//在方法内写匿名内部类
public void method()
{
/*
底层是通过系统用一个匿名的类来实现这个接口的实现:
这个类名 XXXX 由系统给出,可以通过getClass方法来获取tiger的运行类型: 就是外部类名$1(Outer$1)
class XXXX implements A {
@Override
public void cry()
{
System.out.println("老虎..");
}
}
*/
//直接用匿名内部类创建一个对象,让tiger引用这个对象,就可以实现接口并调用重写后的方法了:
A tiger = new A() {
@Override
public void cry() {
System.out.println("老虎..");
}
};
System.out.println("tiger的运行类型: "+tiger.getClass());
tiger.cry();
}
}
interface A //接口
{
public void cry();
}
class TestMain
{
public static void main(String[] args) {
//使用外部类来创建对象
Outer tiger=new Outer();
//调用方法
tiger.method();
}
}
三 .基于类的匿名内部类 :
和基于接口是相似的 , 只不过匿名内部类是实现接口 , 对于类来说匿名内部类是继承此类 .
public class Outer { //外部类
private int n1=100;
//在方法内写匿名内部类
public void method()
{
/*
底层是通过系统用一个匿名内部类来继承这个Father类:
这个类名 XXXX 由系统给出,可以通过getClass方法来获取father的运行类型: 就是外部类名$1(Outer$1)
class XXXX extends Father{
@Override
public void test()
{
}
}
如果这样写则不会产生匿名内部类,因为这只是用Father来创建了一个对象,所以要想使用匿名内部类必须要有{};
Father father=new Father("jack");
*/
//基于类的匿名内部类:
//father的编译类型: Father
//father的运行类型: Outer$1
//Father("jack")会调用Father中的构造方法;
Father father=new Father("jack"){
//匿名内部类继承了Father类 ,这里面可以重写Father类中的方法也可以不重写,因为这不是接口;
};
System.out.println("father的运行类型: "+father.getClass());
}
}
class Father
{
//构造方法:
public Father(String name)
{
System.out.println("接收的name是:"+name);
}
//普通方法:
public void test()
{
}
}
class TestMain
{
public static void main(String[] args) {
//使用外部类来创建对象
Outer father=new Outer();
//调用方法method
father.method();
}
}
四 . 把匿名内部类作为实参传递 , 简洁高效 :
public class test {
public static void main(String[] args) {
//如果只使用一次最好使用匿名内部类作为实参传递
//由匿名内部类来实现接口A1,因为匿名内部类也是一个对象,所以匿名内部类作为实参直接传递,简洁高效
f1(new A1() {
@Override
public void show()
{
System.out.println("这是匿名内部类作为实参");
}
});
//如果传入多次new B(),最好使用传统方法;
//传统方法:写一个B类来实现接口A1,再创建B类的对象作为实参传入f1中:
f1(new B());
}
//静态方法,形参是接口类型
public static void f1(A1 a1)
{
a1.show();
}
}
interface A1
{
void show();
}
class B implements A1
{
@Override
public void show()
{
System.out.println("这是B类对象作为实参");
}
}