Think in java 读书笔记
pikzas
2019.05.05
第十章 内部类
知识点
什么是内部类 可以将一个类定义在另一个类的内部
内部类的分类
- 静态内部类(也承嵌套类)
- 成员内部类
- 局部内部类
- 匿名内部类
内部类的作用 解决java的没有多继承的问题
静态内部类
- 类在定义的时候加上了static 关键字
- 不能和外部类有相同的名字
- 被编译为一个完全独立的.class文件,形如OuterClass$InnerClass.class
- 只可以访问外部类的静态成员和静态方法
- 静态内部类的创建方式 OuterClass.InnerClass inner = new OuterClass.InnerClass();
package com.learnjava.innerclass;
class StaticInner
{
    private static int a = 4;
    // 静态内部类
    public static class Inner
    {
        public void test()
        {
            // 静态内部类可以访问外部类的静态成员
            // 并且它只能访问静态的
            System.out.println(a);
        }
    }
}
public class StaticInnerClassTest
{
    public static void main(String[] args)
    {
        StaticInner.Inner inner = new StaticInner.Inner();
        inner.test();
    }
}
成员内部类
- 成员内部类也是定义在一个类中,但是定义的时候不需要加上static
- 成员内部类和静态内部类分别可以看做外部类的非静态属性和静态属性
- 成员内部类的实例化需要依赖外部类的实例化
- 成员内部类可以继承一个类,实现接口
- 成员内部类前可以添加private,protected,public修饰符,作用等同于这些修饰符作用在一个属性或者方法上的效果。
- 成员内部类可以访问外部类的所有属性和方法,无论是静态还是非静态
- 外部类里面中想要创建成员内部类 this.new InnerClass()
- 外部类之外想要创建成员内部类 (new OuterClass()).new InnerClass()
- 内部类里访问外部类 OuterClass.this.fieldOrMethod
package com.learnjava.innerclass;
class MemberInner
{
    private int d = 1;
    private int a = 2;
    // 定义一个成员内部类
    public class Inner2
    {
        private int a = 8;
        public void doSomething()
        {
            // 直接访问外部类对象
            System.out.println(d);
            System.out.println(a);// 直接访问a,则访问的是内部类里的a
            // 如何访问到外部类里的a呢?
            System.out.println(MemberInner.this.a);
        }
    }
}
public class MemberInnerClassTest
{
    public static void main(String[] args)
    {
        // 创建成员内部类的对象
        // 需要先创建外部类的实例
        MemberInner.Inner2 inner = new MemberInner().new Inner2();
        inner.doSomething();
    }
}
局部内部类
- 局部内部类定义在方法的内部,作用范围比方法还小
- 类似于局部变量 局部内部类也不能有任何的修饰符 public,protected,private,static。
- 只能访问外围方法中final修饰过的属性(非final的会可能随着方法的调用,值发生变化。而此时的内部类无法感知。)
package com.learnjava.innerclass;
class LocalInner
{
    int a = 1;
    public void doSomething()
    {
        int b = 2;
        final int c = 3;
        // 定义一个局部内部类
        class Inner3
        {
            public void test()
            {
                System.out.println("Hello World");
                System.out.println(a);
                // 不可以访问非final的局部变量
                // error: Cannot refer to a non-final variable b inside an inner
                // class defined in a different method
                // System.out.println(b);
                // 可以访问final变量
                System.out.println(c);
            }
        }
        // 创建局部内部类的实例并调用方法
        new Inner3().test();
    }
}
public class LocalInnerClassTest
{
    public static void main(String[] args)
    {
        // 创建外部类对象
        LocalInner inner = new LocalInner();
        // 调用外部类的方法
        inner.doSomething();
    }
}
匿名内部类
- 匿名内部类就是没有名字的局部内部类,不使用关键字class,extends,implements,没有构造方法。
- 匿名内部类一般隐式的继承了一个父类或者实现了一个接口。
- 匿名累不累会生成OuterClass$1.class 数字代表这是外部类中第几个匿名内部类
package com.learnjava.innerclass;
import java.util.Date;
public class AnonymouseInnerClass
{
    @SuppressWarnings("deprecation")
    public String getDate(Date date)
    {
        return date.toLocaleString();
    }
    public static void main(String[] args)
    {
        AnonymouseInnerClass test = new AnonymouseInnerClass();
        // 打印日期:
        String str = test.getDate(new Date());
        System.out.println(str);
        System.out.println("----------------");
        // 使用匿名内部类
        String str2 = test.getDate(new Date()
        {
        });// 使用了花括号,但是不填入内容,执行结果和上面的完全一致
            // 生成了一个继承了Date类的子类的对象
        System.out.println(str2);
        System.out.println("----------------");
        // 使用匿名内部类,并且重写父类中的方法
        String str3 = test.getDate(new Date()
        {
            // 重写父类中的方法
            @Override
            @Deprecated
            public String toLocaleString()
            {
                return "Hello: " + super.toLocaleString();
            }
        });
        System.out.println(str3);
    }
}