其他分享
首页 > 其他分享> > 故乡魂

故乡魂

作者:互联网

https://bbs.pku.edu.cn/v2/post-read.php?bid=459&threadid=17733059

package com.example.nestedclassdemo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * 嵌套类 Nested classes
 * - 静态嵌套类: Static nested classes,即类前面有static修饰符
 * - 非静态嵌套类: Non-static nested classes,又名内部类,Inner classes
 *  - 普通内部类(亦翻译为:成员内部类)
 *  - 局部内部类(Local classes)
 *  - 匿名内部类(Anonymous classes)
 *
 *  为什么需要嵌套类
 *  - 不同的访问权限要求,更细粒度的访问控制
 *  - 简洁,避免过多的类定义
 *  - 语言设计过于复杂,较难学习和使用
 *
 *  匿名内部类:Anonymous classes
 *  - 没有类名的内部类,必须继承一个父类/实现一个父接口
 *  - 在实例化以后,迅速转型为父类/父接口
 *  - 这种类型的对象,只能new一个对象,之后以对象名字操作
 *  - 可在普通语句和成员变量赋值时使用内部类
 *
 *  局部内部类:Local classes
 *  - 定义在代码块中的非静态的类,如方法,for循环,if语句等
 *  - 定义后,即可创建对象使用
 *  - 只能活在这个代码块中,代码块结束后,外界无法使用该类
 *
 *  了解匿名内部类和局部内部类
 *  - 两者几乎相似
 *  - 局部内部类可以重用,匿名内部类不能重用
 *  - 匿名内部类更简洁
 *
 *  普通内部类
 *  - 非static的类,定义在某个类的成员变量位置
 *  - 定义后,在类里面均可以使用
 *
 *  静态嵌套类
 *  - 层级和包围类(enclosing class)的成员变量/方法一样
 *  - 第三方需要通过外部包围类才可以访问到静态嵌套类
 *
 *  了解普通内部类和静态嵌套类
 *  - 两者都定义在外围类中的成员级别
 *  - 静态嵌套类不依赖于外围类对象,但是只能访问外围类的静态成员
 *  - 普通内部类必须依赖于外围类对象,不能单独存在,但是可以访问外围类的所有成员
 *
 *  四种类对比(1)
 *  Oracle官方文档比较
 *  - 匿名内部类:应用它,如果需要定义额外的变量和方法
 *  - 局部内部类:在一个方法内,需要创建一个新的类型,并重复使用
 *  - 普通内部类:和局部内部类相似,在一个类中定义,可重复使用,可以访问外部类成员,但不需要访问外部类方法的形参和内部变量
 *  - 静态嵌套类:在一个类中定义,可重复使用,并需要访问外部类的静态成员
 *
 *  外部访问规则
 *  外部访问和修饰符关系
 *  - 普通内部类和静态嵌套类可以被外部访问
 *  - 外部访问普通内部类和静态嵌套类,和普通类之间访问规则一样
 *
 *  变量遮蔽 Shadowing
 *  - 嵌套类变量和外部包围类的变量重名
 *   - 以离得近作为优先原则
 *   - 优先级高的变量会遮蔽优先级低的变量
 *   - 外部包围类.this.变量名,可以访问到外部包围类的成员变量
 *   - 静态嵌套类不能访问非静态变量
 *   - Java7及以前,匿名内部类和局部内部类只能访问外部包围类的final成员变量
 *   - Java8及以后,匿名内部类和局部内部类可访问外部包围类的final成员变量和事实意义上的final变量
 *
 *   
 *
 *
 *
 *
 *
 *
 */
@SpringBootApplication
public class NestedclassDemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(NestedclassDemoApplication.class, args);
    }

}

package com.example.nestedclassdemo;

/**
 * 匿名内部类
 * - 没有正式类名的内部类
 *  - 编译器产生内部名字: 类名+$+数字编号
 * - 没有类名,没有构造函数,能用父类/父接口的构造函数(可带参数)
 * - 可以继承,改写,补充父类/父接口的方法
 * - 内部不可以新定义静态成员(变量+方法),常量除外
 *  - final static int a = 5;
 * - 可以访问外部包围类的成员变量和方法(包括private)
 * - 如果定义在静态方法中,也只能访问外部包围类的静态成员
 * - 没有类名,外部包围类和其他类也无法访问到匿名内部类
 */
public class Outer1 {
    private String name = "abc";

    public void f1(){
        String name = "def";

        Runnable r = new Runnable() {
            //匿名内部类不能定义静态变量,除非是常量
            public final static int a = 5;
            //public static int b = 3;
            String name = "ghi";
            @Override
            public void run() {
                System.out.println("hello "+name);
            }
            //静态方法不能在匿名内部类定义
            //public static void f2(){}
        };
        new Thread(r).start();
        System.out.println(r.getClass().getName());

        //编译后会产生第二个class匿名内部类
        Runnable r2 = new Runnable() {
            @Override
            public void run() {
                System.out.println("hello "+Outer1.this.name);
            }
        };
        new Thread(r2).start();
        System.out.println(r2.getClass().getName());
    }
}

package com.example.nestedclassdemo;

import java.io.Serializable;

/**
 * 局部内部类: Local classes
 * - 编译后名称: 外部类名+$+序号+内部类名
 * - 可以继承其他类,或者实现其他接口
 * - 非静态的类,不能包含静态成员(变量和方法),除了常量
 * - 可以访问外部包围类的成员
 * - 如果定义在静态方法中,只能访问包围类的静态成员
 * - 局部内部类不能是一个接口,即接口不能定义在代码块中
 */
public class Outer2 {
    String name = "abc";

    //局部内部类
    public void f1(){
        String name = "def";

        class Inner2 extends Outer1 implements Runnable, Serializable {
            final static int a = 1;
            //不允许定义静态普通类成员
            //static int b = 2;
            String name = "ghi";

            public void f2(){
                System.out.println(name);
                System.out.println(Outer2.this.name);
            }

            @Override
            public void run() {
                System.out.println(name);
            }
        }

        Inner2 obj1 = new Inner2();
        obj1.f2();
        System.out.println(obj1.getClass().getName());
    }

    //局部内部类
    public static void f2(){
        final String name = "def";

        class Inner2{
            public String f2(){
                return "this is f2()";
            }
        }

        Inner2 inner2 = new Inner2();
        String s = inner2.f2();
        System.out.println(s);
        System.out.println(inner2.getClass().getName());
    }
}

package com.example.nestedclassdemo.shadow;

public class ShadowTest {

    public int x = 0;

    class FirstLevel{
        public int x  = 1;

        void methodInFirstLevel(int x){
            System.out.println("x = "+x); //line 10 x
            System.out.println("this.x = "+this.x); //line 8 x
            System.out.println("ShadowTest.this.x = "+ShadowTest.this.x); //line 5 x
        }
    }

    public static void main(String... args){
        ShadowTest st = new ShadowTest();
        ShadowTest.FirstLevel f1 = st.new FirstLevel();
        f1.methodInFirstLevel(20);
    }
}

package com.example.nestedclassdemo.shadow;

public class ShadowTest2 {

    public int x = 0;

    public void f1(){
        //局部内部类无法访问得到!
        int x = 20;

        class FirstLevel{
            public int x = 1;

            void methodInFirstLevel(int x){
                System.out.println("x = "+x); //line 14 x
                System.out.println("this.x = "+this.x); //line 12 x
                System.out.println("ShadowTest.this.x = "+ShadowTest2.this.x); //line 5 x
            }
        }

        FirstLevel obj = new FirstLevel();
        obj.methodInFirstLevel(10);
    }

    public static void main(String... args) {
        ShadowTest2 st = new ShadowTest2();
        st.f1();
    }
}

package com.example.nestedclassdemo.shadow;

public class ShadowTest3 {

    public int x = 0;

    public void f1(){
        //可以访问得到,没有被遮蔽!
        int x = 20;

        class FirstLevel{
            void methodInFirstLevel(){
                System.out.println("x = "+x);//line 9 x
                System.out.println("ShadowTest3.this.x = "+ShadowTest3.this.x); //line 5 x
            }
        }

        //x=30;
        FirstLevel obj = new FirstLevel();
        obj.methodInFirstLevel();
    }

    public static void main(String... args) {
        ShadowTest3 st = new ShadowTest3();
        st.f1();
    }
}

package com.example.nestedclassdemo.outer3;

public class Animal {

    String name;

}

package com.example.nestedclassdemo.outer3;

public interface Flyable {

    void fly();

}

package com.example.nestedclassdemo.outer3;

/**
 * 普通内部类
 * - 编译后名称: 外部类名+$+内部类名
 * - 可以继承其他类,或者实现其他接口
 * - 可以用private/package private(不写)/protected/public控制外界访问
 * - 非静态的类,不能包含静态变量/方法,除了常量
 * - 和外部包围类的实例相关,一个普通内部类实例肯定是在一个外部包围类的实例中,
 * 且可以访问外部包围类的所有成员
 * - 在第三方类中,需要先创建外部包围类实例,才能创建普通内部类的实例,
 * 不允许单独的普通内部类对象存在!!!
 */
public class Outer3 {
    String name = "aaaaaa";

    public class Bird extends Animal implements Flyable{
        //常量OK
        public static final int a = 3;
        //不能定义非常量的static变量
        //public static int b = 4;

        @Override
        public void fly() {
            System.out.println(Outer3.this.name+" can fly");
        }
    }

    public Bird b1 = new Bird();

    public void f1(){
        b1.fly();
        System.out.println(b1.getClass().getName());
        this.name = "bbbbbb";
        b1.fly();
    }

    public Bird getBird(){
        return this.b1;
    }
}

package com.example.nestedclassdemo.outer3;

public class Outer3Test {

    public static void main(String[] args) {
        Outer3 foo1 = new Outer3();
        foo1.f1();

        Outer3.Bird foo2 = foo1.new Bird();
        foo2.fly();
        System.out.println(foo2 == foo1.getBird());

        //foo1对象下,有2个内部类对象和它关联

        //不允许没有关联的单独的普通内部类对象
        //Outer3.Bird foo3 = new Outer3().Bird();
    }
}

package com.example.nestedclassdemo.outer4;

/**
 * 静态嵌套类的语法总结
 * - 需要加修饰符static
 * - 可以定义静态成员和非静态成员
 * - 不能直接访问包围类的非静态成员,可直接访问包围类的静态成员
 *  = 可通过包围类的对象进行访问非静态成员
 * - 外界可以通过静态嵌套类名访问其静态成员,通过对象访问其非静态成员
 * - 外界需要通过包围类才可以访问到静态嵌套类,并创建其对象,不需要外部包围类的实例
 */
public class Outer4 {
    private String outField1 = "outer 111";
    private static String outStaticField2 = "outer static 222";

    /**
     * 静态嵌套类
     */
    public static class Inner4{
        //静态嵌套类可以定义静态和非静态成员
        private String innField1 = "inner 333";
        static String innStaticField2 = "inner static 444";

        public void innFun1(){
            //静态嵌套类可以直接访问包围类的静态成员
            System.out.println(innField1);
            //System.out.println(Outer4.outField1);
            System.out.println(Outer4.outStaticField2);
            System.out.println(outStaticField2);

            //静态嵌套类可以通过对象访问包围类的非静态成员
            Outer4 outObj = new Outer4();
            System.out.println(outObj.getOutField1());
        }
        public String getInnField1(){
            return this.innField1;
        }
        public static String getInnStaticField2(){
            hello();
            return innStaticField2;
        }
        public static void hello(){
            System.out.println("inner hello");
        }
    }
    public String getOutField1(){
        return this.outField1;
    }
    public static void outFun2(){
        Inner4 obj1 = new Inner4();
        Inner4 obj2 = new Inner4();
        System.out.println(obj1==obj2);//false
        System.out.println(obj1.getInnField1());
        System.out.println(Inner4.getInnStaticField2());
    }
    public static void hello(){
        System.out.println("outer hello");
    }

}

package com.example.nestedclassdemo.outer4;

public class Outer4Test {

    public static void main(String[] args) {
        //第三方类访问静态嵌套类
        Outer4.Inner4 obj1 = new Outer4.Inner4();
        String innField1 = obj1.getInnField1();
        System.out.println("innField1:"+innField1);

        Outer4.Inner4 obj2 = new Outer4.Inner4();
        System.out.println(obj1==obj2);

        System.out.println("====================");
        Outer4 obj3 = new Outer4();
        Outer4.outFun2();
    }
}

   

标签:静态,故乡,System,static,println,public,out
来源: https://blog.51cto.com/u_11956468/3005119