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之后的类就是匿名内部类要继承的父类或实现的接口;匿名内部类不能是抽象类,因为系统在创建匿名内部类的时候,会立即创建内部类的对象。因此不允许将匿名内部类定义成抽象类。

  • 相关阅读:
    ExtJs错误总结
    Java中的基本类型和引用类型(未完)
    【转】JavaScript中的全局变量与局部变量
    地理信息技术在现场项目的应用浅析
    vector的二分查找算法
    Linux命令
    封装 libmemcached
    Linux + boost + libmemcached + jsoncpp + mysql 配置
    SQL字符串处理函数大全(转)
    vector 排序方法sort的使用
  • 原文地址:https://www.cnblogs.com/zbh355376/p/14532334.html
Copyright © 2011-2022 走看看