高级特性(匿名内部类及应用)

一、匿名内部类特点:

    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();
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_42051619/article/details/81270861