• Java基础--内部类


    普通内部类

    如果一个类只需要在另一个类内部使用,可以考虑将它写成内部类。

    内部类拥有其外部类所有成员的访问权,因为内部类中隐含了一个外部类的引用,可通过 OuterClass.this 获得。

    普通内部类中不可定义static的字段,除非它是final的。

    利用内部类可以实现类似“多继承”,因为内部类继承哪个父类或实现哪些接口都与外部类无关。

    若内部类为private,外界将完全不可见,只有外部类可见。

    若内部类为public,可通过外部类对象.new关键字获得。

    ----------

    interface ForInner1 {
        void printSomething();
    }
    
    class OutClass {
        private int id;
        private String name;
    
        public OutClass() {
        }
    
        public OutClass(int id, String name) {
            this.id = id;
            this.name = name;
        }
    
        private class Inner1 implements ForInner1 {
            private String info; // 自己的成员
    
            @Override
            public void printSomething() {
                info = "hello";
                System.out.println(id + "-" + name + "-" + info);
                // 通过Outer.this返回其外部类引用
                System.out.println(OutClass.this);
            }
        }
    
        public class Inner2 {
            public void printMe() {
                System.out.println(this);
            }
        }
    
        public Inner1 getInner1() {
            return new Inner1();
        }
    }
    
    public class NormalNestedClassTest {
        public static void main(String[] args) {
            OutClass outClass = new OutClass(10, "boy");
            // 错误 Inner1不可见
            // OutClass.Inner1 in1 = outClass.getInner1();
            // 错误 Inner1不可见
            // outClass.getInner1().printSomething();
            // 可通过接口访问
            ForInner1 inner1 = outClass.getInner1();
            inner1.printSomething();
    
            OutClass.Inner2 inner2 = outClass.new Inner2();
            inner2.printMe();
        }
    }

    ----------

    输出:

    10-boy-hello
    demos.innerClass.OutClass@7852e922
    demos.innerClass.OutClass$Inner2@4e25154f

    静态内部类

    如果不需要内部类与外部类的对象有关联,可以使用静态内部类

    静态内部类与普通内部类非常不同,若为public的,则与普通的静态类无异。

    静态内部类不能访问外部类的非静态成员,不隐含外部类对象的引用。

    ----------静态内部类-----

    class OuterClass {
        private static String name="OuterClass";
        //在外部类中使用静态内部类
        private Nest1 nest1 = new Nest1();
        
        public void printNest1(){
            nest1.print();
        }
        private static class Nest1 {
            public void print() {
                // 只能访问外部类的静态成员
                System.out.println(this +" name:"+ name);
            }
        }
        public static class Nest2 {
            Nest2(){
                System.out.println(this);
            }
        }
    }
    
    public class StaticNestedClassTest {
        public static void main(String[] args) {
            OuterClass out1 = new OuterClass();
            OuterClass out2 = new OuterClass();
            out1.printNest1();
            out2.printNest1();
            // public静态内部类 无需外部类即可创建
            OuterClass.Nest2 nest2 = new OuterClass.Nest2();
        }
    }

    --------------------------

    匿名内部类

    这种方式将类的声明和实现放在了一起,并且省略了类名。

    但是需要一个接口或父类来描述。

    -----------匿名内部类----

    //内部类 接口
    interface Iinner {
        void printSomething();
    }
    
    // 匿名内部类 父类
    class Finner {
        String name;
        Finner() {
        }
        Finner(String name) {
            this.name = name;
        }
        public void printSomething() {
            System.out.println(this + " name:" + name);
        }
    }
    
    class Outer {
    
        // 匿名内部类1 实现接口,然后返回
        public Iinner getInner1() {
            return new Iinner() {
                @Override
                public void printSomething() {
                    System.out.println("同一接口的第一种实现");
                }
            };
        }
        
        //或者 实现接口而后调用  
        //等同于父类不实现,交由匿名内部类实现,这样可限制父类的类型
        //另一个意义 可实现同一个接口的不同实现
        public void printThing(){
            new Iinner(){
                @Override
                public void printSomething() {
                    System.out.println("同一接口的第二种实现");
                }
            }.printSomething();
        }
    
        // 匿名内部类2  继承一个父类
        // 可通过父类构造函数传递参数到匿名内部类内部
        public Finner getInner2(String name) {
            Finner a= new Finner(name) {
                //隐秘的复写了父类的方法
                @Override
                public void printSomething() {
                    System.out.println("I am "+name);
                }
                public void say(){
                    //无法被调用
                }
            };
            return a;
        }
    
        // 匿名内部类3 直接传参到匿名内部类内部 参数为final
        public Finner getInner3(String str) {
            return new Finner() {
                private String s = str;
                public void printSomething() {
                    System.out.println(s);
                }
            };
        }
    }
    
    public class InnerTest {
        public static void main(String[] args) {
            Outer out = new Outer();
            out.getInner1().printSomething();
            out.printThing();
            
            out.getInner2("tom").printSomething();
            out.getInner3("hehe").printSomething();
        }
    }

    --------------------------

    输出:

    同一接口的第一种实现

    同一接口的第二种实现

    I am tom

    hehe 

    多继承

    -----------

    class Pen {
        protected String name = "pen";
        {System.out.println("I have a pen");}
    }
    
    class Apple {
        protected String name = "apple";
        {System.out.println("I have an apple");}
    }
    
    public class ApplePen {
    
        private class C1 extends Pen {}
        private class C2 extends Apple {}
    
        public void haha() {
            C1 c1 = new C1();
            C2 c2 = new C2();
            System.out.println("en " + c2.name +"-"+ c1.name);
        }
    
        public static void main(String[] args) {
            ApplePen ap = new ApplePen();
            ap.haha();
        }
    }

    -----------

    内部类产生 Outer$Inner.class

    匿名内部类产生  Outer$1.class

    end

  • 相关阅读:
    Spring Boot 2 快速教程:WebFlux Restful CRUD 实践(三)
    Spring Boot 2 快速教程:WebFlux 快速入门(二)
    ES 集群上,业务单点如何优化升级?
    Spring Boot 2.x 系列教程:WebFlux 系列教程大纲(一)
    泥瓦匠想做一个与众不同的技术"匠"
    java编程行业微信群,无论新手老手欢迎加入,会一直更新
    Spring Boot 2.x 系列教程:WebFlux REST API 全局异常处理 Error Handling
    解决方案:如何防止数据重复插入?
    阿里 Java 手册系列教程:为啥强制子类、父类变量名不同?
    品阿里 Java 开发手册有感
  • 原文地址:https://www.cnblogs.com/luangeng/p/6057668.html
Copyright © 2020-2023  润新知