zoukankan      html  css  js  c++  java
  • Java内部类

    一、内部类是什么

    将一个类的定义放在另一个类的内部,这就是内部类。

    /**
     * 外部类
     */
    public class Outer {
        /**
         * 内部类
         */
        class inner{
    
        }
    }
    

    二、为什么要使用内部类

      使用内部类最吸引人的原因是:每个类都能够独立的继承一个(接口的)实现,所以无论外围类是否已经继承了某个(接口的)实现,对内部类都没有影响。

      内部类拥有类的基本特征(可以继承父类,实现接口),在实际问题中我们会遇到一些接口无法解决或难以解决的问题,此时我们可以使用内部类继承某个具体的或抽象的类,间接解决类无法多继承引起的一系列问题。

    注:内部类可以嵌套内部类,但是这极大的破坏了代码的结构,这里不推荐使用。

    除了上面的优点之外还有如下几点:

    • 内部类可以用多个实例,每个实例都有自己的状态信息,并且于其他外围对象的信息相互独立。

    • 内部类并没有令人迷惑的"is-a"关系,他就是一个独立的个体。

    • 内部类提供了更好的封装,除了外围类,其他类都不能访问。

    • 创建内部类对象的时刻并不依赖与外围类对象的创建。

      具体来说,内部类信息(属性、方法)可以和外部类重名;内部类是具有类的基本特征的独立实体;可以利用访问修饰符隐藏内部类的实施细节,提供了更好的封装;静态内部类使用时可以直接使用,不需先创造外部类。

    三、内部类的共性

    1. 内部类仍然是一个独立的类,在编译之后内部类会被编译成独立的.class文件,但是前面冠以外部类的类名和$符号。

    1. 内部类不能用普通的方式访问,内部类是外部类的一个成员,因此内部类可以自由访问外部类的成员变量,无论是否是private的。

    2. 内部类声明成静态的,就不能随便的访问外部类的成员变量了,此时内部类只能访问外部类的静态成员变量。

    四、使用内部类

    (一)、成员内部类

    public class Outer {
        int id = 1;
        /**
         * 成员内部类
         */
        class Inner{
            private int id = 2;
            public void say(){
                // 访问的是内部类的变量
                System.out.println(id); // 2
                // 访问外部类的变量
                System.out.println(Outer.this.id); // 1
                System.out.println("Inner.say");
            }
        }
    
        public void show() {
            // 外部类访问内部类的成员需要先创建一个成员内部类的对象
            Inner inner = new Inner();
            System.out.println(inner.id);
        }
    
        public static void main(String[] args) {
            Outer outer = new Outer();
            // 访问类的成员
            System.out.println(outer.id);
            // 创建内部类的实例,需要外部类的实例
            Outer.Inner1 inner1 = new Outer().new Inner();
            inner1.say();
        }
    }
    

      当成员内部类拥有和外部类同名的成员变量或者方法时,会发生隐藏现象,即默认情况下访问的是成员内部类的成员,如果要访问外部类的同名成员,需要以下形式进行访问:

    外部类.this.成员变量
    外部类.this.成员方法
    

      虽然成员内部类可以无条件的访问外部类的成员,但是外部类想要访问成员内部类,就不可以直接访问了,需要先创建一个成员内部类的对象,在通过指向这个对象的引用来访问。

      在其他类使用成员内部类有两种方式:

    方式一:
    Outer.Inner inner = new Outer().new Inner();
    
    方式二:
    Outer outer = new Outer();
    Outer.Inner inner = outer.new Inner();
    

    (二)、静态内部类(静态嵌套类)

    public class Outer {
        int id = 1;
        static int id2 = 2;
    
        /**
         * 静态成员内部类
         */
        static class Inner{
            public void say(){
                System.out.println("Inner.say");
                // 只能访问外部类的静态信息(成员变量和方法)
                System.out.println("Outer.id2=" + id2);
            }
            public static void show() {
                System.out.println("Inner.show");
            }
        }
        
        public static void main(String[] args) {
            // 创建静态内部类实例
            Outer.Inner inner = new Outer.Inner();
            inner.say();
            // 访问静态内部类的静态方法,Inner类被加载,此时外部类未被加载,独立存在,通过类名.方法即可访问。
            Outer.Inner.show();
        }
    }
    

      静态内部类也是定义在类里面的类,在类前面多了一个static关键字,内部类可以独立存在,不依赖与其他外围类,它不能使用外部类的非静态成员变量或方法。

    (三)、方法内部类

    public class Outer {
        int id = 1;
    
        public void work(){
            final int id1=1;
            int id2 = 2;
            /**
             * 方法内部类,只能在方法内部使用
             */
            class Inner{
                public Inner(){
                    System.out.println(id1);
                    // 报错,Variable 'id2' is accessed from within inner class, needs to be declared final
                    // 变量'id2'是从内部类中访问的,需要声明为final
    //                System.out.println(id2);
                    System.out.println("method work Inner created");
                }
                void work(){
                    System.out.println("method Inner.work");
                }
            }
            // 方法内部类只能在方法中使用,在方法中创建实例并调用内部类的方法
            Inner inner = new Inner();
            inner.work();
        }
        public static void main(String[] args) {
            Outer outer = new Outer();
            outer.work();
        }
    }
    

    方法内部类的限制:

    • 类前不能有访问修饰符。

    • 仅在此方法中使用。

    • 无法创造静态信息。

    • 只能访问final变量和形参

    (四)、匿名内部类

    public class Outer {
        int id = 1;
    
        /**
         * 匿名内部类,一个没有名称的实现了IAnimal接口的类
         */
        IAnimal animal = new IAnimal() {
            @Override
            public void say() {
                System.out.println("匿名内部类的say方法");
            }
        };
    
        public static void main(String[] args) {
            Outer outer = new Outer();
            
            // animal是Outer类的一个成员,这个成员是匿名内部的实例
            outer.animal.say();
        }
    }
    

      在使用匿名内部类时,这个new之后的类首先是要存在的,其次我们要重写new后的类的某个或某些方法。匿名内部类没有构造方法。

      使用匿名内部类有一个前提条件:必须继承一个父类或实现一个接口,但最多只能继承一个父类或实现一个接口,new之后的类就是匿名内部类要继承的父类或实现的接口;匿名内部类不能是抽象类,因为系统在创建匿名内部类的时候,会立即创建内部类的对象。因此不允许将匿名内部类定义成抽象类。

  • 相关阅读:
    bzoj1415 NOI2005聪聪和可可
    Tyvj1952 Easy
    poj2096 Collecting Bugs
    COGS 1489玩纸牌
    COGS1487 麻球繁衍
    cf 261B.Maxim and Restaurant
    cf 223B.Two Strings
    cf 609E.Minimum spanning tree for each edge
    cf 187B.AlgoRace
    cf 760B.Frodo and pillows
  • 原文地址:https://www.cnblogs.com/zbh355376/p/14532334.html
Copyright © 2011-2022 走看看