Nested Classes

来源:互联网 发布:杨裕生 铅酸 知乎 编辑:程序博客网 时间:2024/06/06 12:37

嵌套类(nested classes)

在Java应用程序语言中允许在一个类中定义另外一个类,这样的类叫做嵌套类:

class OuterClass {//外部类,顶级类    ...    class NestedClass {//嵌套类        ...    }}

嵌套类的分类

特别的,嵌套类可以分为静态和非静态的。声明为静态的叫做静态嵌套类static nested classes),而非静态的可以分为inner class ,local classes anonymous class

public class OuterClass {//顶级类,外部类    interface HelloWorld {        void greet();        void greetSomeone(String someone);    }    /**     * 静态嵌套类     */    static class StaticNestedClass {    }    /**     * 内部类     * */    class InnerClass {    }    public void sayHello() {        /***         *局部类         */        class LocalClass implements HelloWorld {            String name = "world";            public void greet() {                greetSomeone("world");            }            public void greetSomeone(String someone) {                name = someone;                System.out.println("Hello " + name);            }        }        HelloWorld englishGreeting = new LocalClass();        /**         * 匿名类         * */        HelloWorld frenchGreeting = new HelloWorld() {            String name = "tout le monde";            public void greet() {                greetSomeone("tout le monde");            }            public void greetSomeone(String someone) {                name = someone;                System.out.println("Salut " + name);            }        };        englishGreeting.greet();        frenchGreeting.greetSomeone("Fred");    }    public static void main(String... args) {        OuterClass myApp =                new OuterClass();        myApp.sayHello();    }}

为什么使用嵌套类

  1. 对于那种仅在一个地方使用的类,嵌套的方式是一种很好的逻辑分组方式。假如一个类只对其他类中的一个类有用,这是非常符合逻辑的将这个类嵌套在那个使用它的类里面,使他们连在一起。嵌套就好像是一个“帮助类”一样,使他们的封装更加的简化
  2. 增加封闭性。考虑一下这样的情景,两个顶级类A和B,在类B中要用权限能够使用到A的组成成分(域/方法),那么对于A的组成成分要么暴露(public)出来(get/set也是),要么不给B这个权限(private)。(个人理解:类A中组成成分只想给类B使用)。那么,可以通过将类B嵌套在类A中,A的组成成分就可以声明为private,类B又能有权限使用到,还有,对于类B,它也可以对除了类A之外的其他类隐藏(也就是声明为private)
  3. 增加代码的可读性和可维护性。在顶级类中嵌套的类 ,嵌套类的代码更加接近它被使用的地方。(离得近)

静态嵌套类(static nested classes)

package com.company;import java.util.Random;/** *① 可以使用访问修饰符 *②对外部类方法和域的权限:对声明为static的域和方法有使用权限,即使它们申明为private *③是否可以在类中创建static的域和method 可以,也可以声明接口 */public class StaticNestedClassTest {    static int i = 0;    int a = 0;    final static Object o = new Random();    private static void method1() {    }    public static void method2() {    }    public void method3() {    }    /**     * static nested classes 可以使用访问修饰符修饰,可以访问到外部类的static 域和方法,在static nested classes内部可以创建任何东西     * 就像是另外的一个顶级类一样使用,不过static nested classes却可以访问它外部类的一些private的静态域和方法,而其他的顶级类却不能     * */    static class StaticNestedClass {        static int s = 0;        Object object = new Object();        private static void method4() {            System.out.println(i);//可以引用外部类中的静态域//            System.out.println(a);//非静态类型的a不能在一个静态环境中引用            System.out.println(o.toString());//引用外部类静态常量            method1();//外部类的静态方法,即使它申明为private            method2();//            method3();//非静态方法不能在一个静态环境中引用        }        public void method5() {            System.out.println(i);//            System.out.println(a);//非静态类型的a不能在一个静态环境中引用            method1();            method2();//            method3();//非静态方法不能在一个静态环境中引用        }        interface Test{        }        class Test1 {        }    }    /**     * 除了StaticNestedClassTest类之外的类,其他类无法访问到这个私有的StaticNestedClass1     * */    private static class StaticNestedClass1{    }    public static void main(String[] args) {        //创建一个静态嵌套类实例        StaticNestedClassTest.StaticNestedClass staticNestedClass = new StaticNestedClassTest.StaticNestedClass();    }}

non-static nested classes

inner classes

package com.company;import java.util.Random;/** *①可以使用访问修饰符 *②对外部类方法和域的权限:所有的方法和域都有使用权,即使声明为private *③是否可以在类中创建static的域和method 不可以,(可以声明全局常量,基本数据类和String 的final static String s = "sad"; final static int g = 0;) 也不可以声明接口 *      相关:A constant variable is a variable of primitive type or type String that is declared final and initialized with a compile-time constant expression. *      A compile-time constant expression is typically a string or an arithmetic expression that can be evaluated at compile time. *      涉及到编译时。不解释 ,知道就ok */public class InnerClassTest {    static int i = 0;    private int a = 0;    final static Object o = new Random();    private static void method1() {    }    public static void method2() {    }    public void method3() {    }    /**     * InnerClass 可以使用访问修饰符修饰     */    public class InnerClass {        private void method4() {            /**             * 可以使用外部类的所用域和方法,即使是private,             * */            System.out.println(i);            System.out.println(a);            System.out.println(o.toString());            method1();            method2();            method3();        }        //不可以在inner class中有静态的声明//        private static void method5(){////        }//        static int a;//        interface test{////        }//interface 在本质上市static属性的,所以也是不可以        /**         * 对于像基本类型,String 这两种情况,因为本身它们是属于常量         * 被final static 修饰的变量可以认为是全局的常量,         * 很明显,s g ob 都是一个常量,但是s g 指向的实例对象依旧还是常量,而ob指向的确不是         *         */        final static String s = "sad";        final static int g = 0;        //不可以在inner class中有静态的声明//        final static Object ob = new Random();        /**         * 为什么在innerclass中不可以有static的方法和变量和一些常量,因为在inner class中是包含有一个         * 外部类对象实例的,要不是就不能够直接的访问到外部类的域和方法了,而static nested class里面没有包含         * 它外部类的实例对象所以他只能使用到static的域和方法         * */    }    class InnerClass1 {    }}


创建实例:
package com.company;public class Main{    public static void main(String[] args) throws ClassNotFoundException {        //报错,提示InnerClass不是一个外部顶级类//        InnerClassTest.InnerClass innerClass = new InnerClassTest.InnerClass();        InnerClassTest innerClassTest = new InnerClassTest();        InnerClassTest.InnerClass innerClass = innerClassTest.new InnerClass();        //从这里可以印证:InnerClass 内部是有一个InnerClassTest的实例对象的,        //InnerClass 的对象实例 依存它外部类InnerClassTest实例,先有我外部类实例,再有InnerClass实例    }}

local classes

localclass 可以说是inner class 的继续限制版,inner class里面 不能定义static域和方法和一些常量,localclass也是不能的
看列子:
package com.company;import java.util.Random;/** *①不能使用访问修饰符 *②对外部类方法和域的权限:对于在非静态块的localClass 对外部类的所有域和方法都有使用权,(即使声明为private) *                        在静态块定义的localClass只对外部类声明为是static的域和方法有使用权(即使声明为private) *③是否可以在类中创建static的域和method 不可以,(可以声明全局常量,基本数据类和String 的final static String s = "sad"; *                                          final static int g = 0;) 也不可以声明接口 *                                         ***即使localClass在static块出定义也不可以 *④对于方法(块)中的局部变量/参数 只有当它们是final/effective final的时候才可以在LocalClass中使用,详细看代码 */public class LocalClassTest {    static int i = 0;    private int a = 0;    final static Object o = new Random();    private static void method1() {    }    public static void method2() {    }    public void method3() {    }    /**     * 既然叫局部,当然是不能使用访问修饰符啦     * */    //定义在static 块 中    static {        class LocalClass1 {            private void method8(){                System.out.println(i);//                System.out.println(a);//静态中不能引用非静态的变量                System.out.println(o.toString());            }        }    }    //定义在构造方法中    public LocalClassTest() {        class LocalClass2 {        }        for (int i = 0; i < 5; i++) {//定义在for循环块 中            class LocalClass3 {            }        }    }    //定义在普通的方法中    private void method4(int jj,Object ll) {        final int aa = 0;        int bb = 5;//        bb++;//        ll = null;        //ll 和bb 是effectively final才能被LocalClass使用 。effectively final是在JDK8才出现的,所以8之前的只有final的才能在LocalClass中使用        class LoadClass4 {            public void method6() {                /**                 * 可以使用外部类的所用域和方法,即使是private,                 * */                System.out.println(i);                System.out.println(a);                System.out.println(o.toString());                method1();                method2();                method3();                /**                 * 对于包含LocalClass的块的一些局部变量,这些变量要么是final要么是effectively final(这个变量这能赋值一次)                 * */                System.out.println(jj);                System.out.println(ll);                System.out.println(aa);                System.out.println(bb);//                jj++;//                ll = null;//                bb = 80;            }            //不可以在inner class中有静态的声明//        private static void method5(){////        }//        static int a;//        interface test{////        }//interface 在本质上市static属性的,所以也是不可以            final static String s = "sad";            final static int g = 0;            //不可以在inner class中有静态的声明//        final static Object ob = new Random();        }    }    //定义在static方法中    /**     * 这个特殊     */    private static void method5(int jj,Object ll) {        final int aa = 0;        int bb = 5;        class LocalClass5 {            private void method7() {                System.out.println(i);//                System.out.println(a);//静态中不能引用非静态的变量                System.out.println(o.toString());                method1();                method2();//                method3();//静态中不能引用非静态的变量                /**                 *                 * */                System.out.println(jj);                System.out.println(ll);                System.out.println(aa);                System.out.println(bb);//                jj++;//                ll = null;//                bb = 80;            }//       不可以在inner class中有静态的声明//        private static void method5() {//         }//        static int a;//        interface test{////        }//interface 在本质上市static属性的,所以也是不可以            final static String s = "sad";            final static int g = 0;            //不可以在inner class中有静态的声明//        final static Object ob = new Random();        }        if (true) {//定义在if块中            class LocalClass6 {            }        }    }}

anonymous classes 

package com.company;import java.util.Random;/** * Anonymous classes enable you to make your code more concise. * They enable you to declare and instantiate a class at the same time. * 同时声明和实例化 * They are like local classes except that they do not have a name. * Use them if you need to use a local class only once. * 其实本质上说,anonymousclass是表达式,如 * new HelloWorld() { * String name = "tout le monde"; * <p> * public void greet() { * greetSomeone("tout le monde"); * } * <p> * public void greetSomeone(String someone) { * name = someone; * System.out.println("Salut " + name); * } * }; *表达式包含:①new关键字 ② 要实现的接口或者继承的抽象类③在()中包含构造函数的参数,假如又需要的话 *  用的最多的就是GUI 事件当中 * * */public class AnonymousClassTest {    static int i = 0;    private int a = 0;    final static Object o = new Random();    private static void method1() {    }    public static void method2() {    }    public void method3() {    }    interface HelloWorld {        public void greet();        public void greetSomeone(String someone);    }    abstract class HelloWorldTest {        abstract void greet();        abstract void greetSomeone(String someone);    }    public void sayHello(int jj, Object ll) {        final int aa = 0;        int bb = 5;//        bb++;//        ll = null;        //ll 和bb 是effectively final才能被LocalClass使用 。effectively final是在JDK8才出现的,所以8之前的只有final的才能在LocalClass中使用        class EnglishGreeting implements HelloWorld {            String name = "world";            public void greet() {                greetSomeone("world");            }            public void greetSomeone(String someone) {                name = someone;                System.out.println("Hello " + name);            }        }        //使用LocalClass实例化englishGreeting        HelloWorld englishGreeting = new EnglishGreeting();        //使用anonymousClass实例化        HelloWorld frenchGreeting = new HelloWorld() {            String name = "tout le monde";            public void greet() {                greetSomeone("tout le monde");            }            public void greetSomeone(String someone) {                name = someone;                System.out.println("Salut " + name);            }        };        HelloWorld spanishGreeting = new HelloWorld() {            String name = "mundo";            public void greet() {                greetSomeone("mundo");            }            public void greetSomeone(String someone) {                name = someone;                System.out.println("Hola, " + name);            }        };        englishGreeting.greet();        frenchGreeting.greetSomeone("Fred");        spanishGreeting.greet();        //使用anonymousClass        HelloWorldTest helloWorldTest = new HelloWorldTest() {            private void method4() {                /**                 * 可以使用外部类的所用域和方法,即使是private,                 * */                System.out.println(i);                System.out.println(a);                System.out.println(o.toString());                method1();                method2();                method3();                /**                 * 对于包含LocalClass的块的一些局部变量,这些变量要么是final要么是effectively final(这个变量这能赋值一次)                 * */                System.out.println(jj);                System.out.println(ll);                System.out.println(aa);                System.out.println(bb);//                jj++;//                ll = null;//                bb = 80;            }            @Override            void greet() {            }            @Override            void greetSomeone(String someone) {            }            //不可以在inner class中有静态的声明//        private static void method5(){////        }//        static int a;//        interface test{////        }//interface 在本质上市static属性的,所以也是不可以            final static String s = "sad";            final static int g = 0;            //不可以在inner class中有静态的声明//        final static Object ob = new Random();        };    }    //使用anonymousClass    HelloWorldTest helloWorldTest = new HelloWorldTest() {        @Override        void greet() {        }        @Override        void greetSomeone(String someone) {        }    };}
0 0
原创粉丝点击