Nested Classes

嵌套类(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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值