一、匿名内部类特点:
1.匿名内部类是没有名称的内部类,没办法引用它们。必须在创建时,作为new语句的一部分来声明并创建它们的实例。
2.匿名内部类必须继承一个类(抽象的、非抽象的都可以)或者实现一个接口。如果父类(或者接口)是抽象类,则匿名内部类必须实现其所有抽象方法。
3.匿名内部类中可以定义代码块,用于实例的初始化({},对对象的属性做初始化,也可用构造方法来做,但代码块优先于构造方法先执行),但是不能定义静态代码块(会报错)。
4.匿名内部类的语法:
new interface/super class() {// 类体} 这种形式的new语句声明一个新的匿名类,它对一个给定的类进行扩展,或者实现一个给定的接口,并同时创建该匿名类的一个新实例。(这里new出来的是接口的实现类也就是说new出来了一个类它继承了这个接口或者是父类的子类,所以new接口/父类new出来的不是对接口实例化而是new出来的是接口的实现类对象或者是父类的子类对象)
public class AnonymousInnerClass {
public static void main(String[] args) {
Person person = new Person();
// 这是传统的实现方法
Animal dog = new Dog();
person.feed(dog);
}
}
abstract class Animal {
public abstract void eat();
}
class Dog extends Animal {
@Override
public void eat() {
System.out.println("啃骨头");
}
}
class Person {
public void feed(Animal animal) {
// 同一个方法接收不同的实例对象(接收不同的动物),实现不同的功能。
animal.eat();
}
}
(1)通过匿名类来实现这个功能
public class AnonymousInnerClass {
public static void main(String[] args) {
Person person = new Person();
//+++++======这里喂的是不同的狗=======+++++//
person.feed(new Animal() {
@Override
public void eat() {
System.out.println("啃骨头");
}
});
person.feed(new Animal() {
@Override
public void eat() {
System.out.println("啃骨头");
}
});
//-------------------喂同一条狗可以这么做-----------------//
Animal dog =new Animal() {
@Override
public void eat() {
System.out.println("啃骨头");
}
};
// 将匿名内部类构造出来的对象也可以赋值给一个引用变量,所以这个dog是同一个对象。
person.feed(dog);
person.feed(dog);
//-------------匿名内部类中可以有自己的属性和方法--------------//
Animal cat = new Animal() {
private String name = "aa";
@Override
public void eat() {
System.out.println("吃鱼肉");
}
public void show() {
System.out.println(name);
}
};
cat.eat();
//cat.show();
------>怎么调用自己的方法呢?
这里不能通过这种方式来调用,因为这里new出来的是子类的对象,子类赋值给父类,父类的引用变量引用其子类的对象,它只能调用父类中有的方法,而这个show方法是子类特有的,所以父类的引用变量是不能调用的。也不能将父类的引用变量强制类型转换为猫,因为这里没有猫这个类型,因此不能强制类型转换。所以可以这么做,因为这个类是匿名的,所以就不要赋值,即:
new Animal() {
private String name = "加菲猫";
@Override
public void eat() {
System.out.println("吃鱼肉");
}
public void show() {
System.out.println(name);
}
}.show();
因为new出来的是它的一个子类的对象,那么对象名.方法名就可以调用自己内部的方法。所以要想调用匿名内部类中特有的方法,只能通过这种方式,不能赋值给父类的引用变量,因为它只能调用父类中有的方法,不能调用子类中特有的方法。
//----------匿名内部类中可以定义代码块----------------//
new Animal() {
private String name;
// 代码块,比构造方法先执行,一般用来对属性进行初始化,但是这里不能使用静态代码块。
{
name = "TEST";
}
@Override
public void eat() {
System.out.println(name);
}
};
}
}
abstract class Animal {
public abstract void eat();
}
class Person {
public void feed(Animal animal) {
// 同一个方法接收不同的实例对象(接收不同的动物),实现不同的功能。
animal.eat();
}
}
public class AnonymousInnerClass {
public static void main(String[] args) {
Person person = new Person();
//-------------new一个接口的实现类对象--------------------//
new IAnimal() {
private String name = "aa";
@Override
public void eat() {
System.out.println("啃骨头");
}
public void show() {
System.out.println(name);
}
}.show();
person.feed(new IAnimal() {
@Override
public void eat() {
System.out.println("吃鱼肉");
}
});
}
}
interface IAnimal {
// 接口里只能放方法的声明,不能放有方法体的方法;
public abstract void eat();
}
class Person {
public void feed(IAnimal animal) {
animal.eat();
}
}