内部类和匿名内部类

内部类(宿主类对内部类成员的访问、内部类对象的创建)

首先写个简单例子

public class Outer {//    宿主类
    String out_string = "string in outer";
    public void show(){
        System.out.println(out_string);
    //    Inner1.showInner1();//对于普通内部类,不能直接调用其内部的成员属性和方法
    //    System.out.println(Inner1.in_string1);
        Inner2.showInner2();//对面静态内部类里的静态属性和静态方法,我们可以通过(类名.属性名/方法名)来调用相对应的成员。

//因为Java虚拟机在程序可以运行前加载了静态类、静态变量、静态方法,放在虚拟机里面,可以直接调用
        System.out.println(Inner2.in_string2);

           //System.out.println(Inner2.in_string3);//如果是非静态成员,这需要通过实例化对象来调用
        
        Inner1 inner1 = new Inner1();//如果想要使用普通内部类里的属性和方法,需要先进行实例化,创建一个该类的对象。
        inner1.showInner1();//然后通过该对象来调用其成员属性和方法。
        System.out.println(inner1.in_string1);
    } 
    
    class Inner1{//普通内部类1
        String in_string1 = "string in inner1";
        public Inner1(){
            System.out.println("这是内部类1的构造方法。");
        }
        public void showInner1(){
            System.out.println("这是内部类的普通方法。");
        }
    }
    
    static class Inner2{//静态内部类2
        static String in_string2 = "string in Inner2";
        public Inner2(){
            System.out.println("这是静态内部类2的构造方法");
        }
        public static void showInner2(){
            System.out.println("这是静态内部类2的普通方法。");
        }
    }
}

然后我们看一下show()方法的运行结果

public class Test {
    public static void main(String[] args) {
        Outer outer = new Outer();//创建一个Outer类的对象,来调用show(方法)
        outer.show();
    }
}

如果我们想调用内部类呢

public class Test {
    public static void main(String[] args) {
        //Inner1 inner1 = new Inner1();//不能直接调用,找不到该类所在位置
        Outer.Inner1 inner1 = new Outer().new Inner1();
        //我们首先找到Inner1所在位置:Outer类里面。
        //然后先实例化一个Outer对象,再在用Outer对象里面实例化Inner1对象
        inner1.showInner1();
        System.out.println(inner1.in_string1);
        
        System.out.println(Outer.Inner2.in_string2);
        Outer.Inner2.showInner2();//对于静态内部类里的静态成员变量和成员方法,可以根据位置来直接调用,
        //不需要实例化。当然,也可以用实例化对象里调用
        
        //而对于静态内部类,这不需要先一步进行宿主类实例化,直接根据位置实例化
        Outer.Inner2 inner2 = new Outer.Inner2();
        inner2.showInner2();
        System.out.println(inner2.in_string2);
        System.out.println(inner2.in_string3);
    }
}

扩展(内部类的内部类)

public class Outer2 {
    String out2_string = "string in outer2";
    public void show(){
        Inner1.Class_in_inner1 class1 = new Inner1().new Class_in_inner1();//同上,调用Class_in_inner1类里的成员
        //需要先对其进行实例化,然后通过实例化的对象来调用里面的成员变量和方法
        System.out.println(class1.in_class_in_inner1);
        
        //而静态内部类的静态内部类里的静态成员变量的静态方法调用,可直接根据位置来调用
        System.out.println(Inner2.StaticClass_in_inner2.in_staticClass_in_inner2);
        
    } 
    
    class Inner1{
        String in_string1 = "string in inner1";
        public Inner1(){
            System.out.println("这是内部类1的构造方法。");
        }
        class Class_in_inner1{
            String in_class_in_inner1 = "string in class_in_inner1";
            public Class_in_inner1(){
                System.out.println("这是内部类的内部类的构造方法");
            }
        }
    }
    
    static class Inner2{
        static String in_string2 = "string in Inner2";
        public Inner2(){
            System.out.println("这是静态内部类2的构造方法");
        }
        static class StaticClass_in_inner2 {
            static String in_staticClass_in_inner2 = "string in staticClass_in_inner2";
            public StaticClass_in_inner2(){
                System.out.println("这是静态内部类的静态内部类的构造方法");
            }
        }
    }
}

Test测试类

public class Test2 {
    public static void main(String[] args) {
        Outer2 outer2 = new Outer2();
        outer2.show();
        System.out.println("*********************************************");
        //对面普通内部类的内部类的实例化,得到Class_in_inner1对象,步骤同上
        //依次创建其宿主类的对象,然后通过宿主类对象来实例化内部类对象
        Outer2.Inner1.Class_in_inner1 class1 = new Outer2().new Inner1().new Class_in_inner1();
        System.out.println(class1.in_class_in_inner1);
        
        //而静态内部类的静态内部类里的静态成员变量和静态方法,可以根据位置直接调用
        System.out.println(Outer2.Inner2.StaticClass_in_inner2.in_staticClass_in_inner2);
        
        //而而静态内部类的静态内部类的实例化也同上
        Outer2.Inner2.StaticClass_in_inner2 class2 = new Outer2.Inner2.StaticClass_in_inner2();
        System.out.println(class2.in_staticClass_in_inner2);
    }

}

匿名内部类(对接口的匿名内部类、通过继承父类来创建的匿名内部类)

一般调用一个接口,实现接口里面的方法,通过下面步骤

interface IProduct{//定义一个借口,里面包含一个商品的名称和价格的获取方法
    public String getName();
    public double getPrice();
}
class ProductImpl implements IProduct{//一个IProduct接口的实现类,具体化了getName()和
    //getPrice()方法,给了商品的名称:键盘,价格200.0
    public String getName() {
        return "键盘";
    }
    public double getPrice() {
        return 200.0;
    }
    //一个商品:200.0元的键盘
}
public class AnonymousInterface {
    public void show(IProduct iProduct) {//定义一个方法来输出一个商品的名称和价格,形参为IProduct对象
        System.out.println("一个商品:"+iProduct.getName()+",价格:"+iProduct.getPrice()+"¥。");
    }
    public static void main(String[] args) {
        AnonymousInterface anonymousInterface = new AnonymousInterface();//实例化AnonymousInterface,得到对象
        anonymousInterface.show(new ProductImpl());//利用对象调用show()方法
        //这里我们先对接口IProduct创建一个实现类,可以直接调用
        //IProduct iproduct = new ProductImpl();anonymousInterface.show(iproduct);等同于上句
    }
}

但我们可以使用匿名内部类,来简化和代替接口Iproduct实现类ProductImpl类

interface IProduct{//定义一个借口,里面包含一个商品的名称和价格的获取方法
    public String getName();
    public double getPrice();
}
public class AnonymousInterface2 {
    public void show(IProduct iProduct) {//定义一个方法来输出一个商品的名称和价格,形参为IProduct对象
        System.out.println("一个商品:"+iProduct.getName()+",价格:"+iProduct.getPrice()+"¥。");
    }
    public static void main(String[] args) {
        AnonymousInterface2 anonymousInterface = new AnonymousInterface2();//实例化AnonymousInterface,得到对象
        anonymousInterface.show(new IProduct(){//直接定义一个实现接口IProduct的匿名内部类,
        //实现里面的getName()和gerPrice()方法,提供商品的名称和价格信息
            public String getName() {
                return "键盘";
            }
            public double getPrice() {
                return 200.0;
            }
            //一个商品:200.0元的键盘
        });
    }
}
这样,把接口的实现类根据需求创建匿名内部类,不影响运行结果,可以进一步优化代码。

但是这种方法只能对于只需要实现一次接口的程序使用,当你需要多次调用同样的实现类的时候,就需要写一个实现类,然后调用。

另外,我们可以通过继承父类来创建内部类,匿名内部类将拥有和父类类似的构造器(相同参数列表的构造方法),可以使用父类中的非私有成员变量和方法。

同上,我们使用一个抽象实体父类时候,需要创建一个子类实现父类里的抽象方法(普通的父类、子类情况一样)。

但是,我们可以使用匿名内部类来继承父类,实现其中的抽象方法,简化和代替子类

abstract class Product {
    private String name;

    public abstract double getPrice();// 抽象方法,获取商品的价格
    // 创建构造方法

    public Product() {
        super();
    }

    public Product(String name) {
        super();
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

public class Anonymous_parenr_class {
    public void show(Product product) {// 定义一个方法来输出一个商品的名称和价格,形参为Product对象
        System.out.println("一个商品:" + product.getName() + ",价格:" + product.getPrice() + "¥。");
    }

    public static void main(String[] args) {
        Anonymous_parenr_class anonymousInterface = new Anonymous_parenr_class();// 实例化AnonymousInterface,得到对象
        anonymousInterface.show(new Product("键盘") {//调用了构造方法public Product(String name) 对商品名称进行赋值
//            {//当然,也可以通过构造代码块进行赋值
//                super.setName("键盘");//调用父类里的setName方法进行赋值
//            //    super.name = "键盘";//这个要求父类里name修辞词不为private
//            }

//            public String getName(){
//                return "键盘";
  //          }//也可以重写getName方法,将其返回值固定为“键盘”。
            public double getPrice() {
                return 300.0;
            }
        });
    }
}

猜你喜欢

转载自blog.csdn.net/songxinyuandouxinyu/article/details/81289863
今日推荐