嵌套类小结

定义:一个类定义在别的类的内部;

分类:

  • 静态嵌套类
  • 非静态嵌套类(内部类):1.普通内部类(成员内部类)2.局部内部类 3.匿名内部类

匿名内部类:

  • 没有类名的内部类,必须继承一个父类或实现一个接口;
  • 在实例化以后,迅速转型为父类/父接口;
  • 这种类型的对象,只能new一个对象,之后以对象名字操作;
  • 可在普通语句和成员变量赋值时使用内部类;
  • 不能定义静态变量,除非是常量(final),也不能定义静态方法;
  • 因为没有类名,所以外部包围类和其他类也无法访问到匿名内部类;
public class Demo {
    public static void main(String[] args){
        Runnable r = new Runnable() {
            public void run() {
                System.out.println("hello world");
            }
        };
        new Thread(r).start();
    }
}

代码说明:创建一个实现Runnable接口的匿名类对象,通过new表达式返回的引用被自动转型为对Runnable的引用;

局部内部类

  • 定义在代码块中(方法和作用域)的非静态类
  • 定义后,即可创建对象使用;
  • 只能活在代码块中,外界无法使用该类;
  • 不能包含静态成员(方法和变量),除了常量;
  • 如果定义在静态方法中,只能访问外围类的静态成员;
  • 可以重用
  • 局部内部类不能是一个接口,即接口不能定义在代码块中

普通内部类

  • 非静态类,不能包含静态变量/方法,除了常量
  • 和外部包围类实例相关,一个普通内部类实例肯定是在一个外部包围类的实例当中
  • 在第三方类中,需要先创建外部包围类实例,才能创建普通内部类实例,不允许单独的普通内部类对象存在;
    示例:
public class Demo {
    void f(){
        System.out.println("Demo.f()");
    }
    public class  Inner{
        public Demo outer(){
            return Demo.this;
            //返回对外部类对象的引用
        }
    }
    public static void main(String[] args){
        Demo demo = new Demo();
        Demo.Inner inner = demo.new Inner(); //new一个内部类
        inner.outer().f();
    }
}

普通内部类的向上转型:
内部类的用武之地:将内部类向上转型为一个类/接口,此时内部类(接口的实现/基类的子类)能够完全不可见,并且不可用,所得到的只是指向基类或接口的引用,能够很好地实现隐藏细节;

public class Outer1{
    private class Inner implements Interface1{
    ...
    }
    public Interface1  interface1(){ 
        return new Inner();
    }
}

静态嵌套类:

public class Outer1{
    ...
   static class Inner1{
      String name;
    }
}
  • 要创建静态嵌套类的对象,并不需要其外围类对象
  • 不能从静态嵌套类的对象中访问非静态的外围类对象

为什么需要嵌套类:

  • 一种代码隐藏机制
  • 可以提供细粒度的访问权限控制
  • 了解外围类,并能与之通信,提供了某种进入其外围类的窗口
  • 每个嵌套类都能独立地继承自一个(接口的)实现,所以无论外围类是否已经继承了某个(接口的)实现,对于嵌套类都没有影响
  • 嵌套类使得多重继承的方案变得完整
  • 简洁,代码优雅而清晰
  • 语言设计过于复杂,较难学习和使用(缺点)

四种类对比

Oracle官方文档比较:

  • 匿名内部类(Anonymous class): Use it if you need to declare fields or additional methods.
  • 局部内部类(Local classes):Use it if you need to create more than one instance of a class, access its constructor, or introduce a new, named type (because, for example, you need to invoke additional methods later).需要创建一个新的类型,并重复使用(比如在一个方法内);
  • 普通内部类:Use it if your requirements are similar to those of a local class, you want to make the type more widely available, and you don't require access to local variables or method parameters.和局部内部类相似,在一个类中定义,可重复使用,可以访问外部类的成员,但不需要访问外部类方法中的形参和内部变量
  • 静态嵌套类:Use a static nested class if you don't require access to an enclosing instance's non-public fields and methods。在一个类中定义,可重复使用,并需要访问外部类的静态成员;


    对比1

    对比2

参考

https://docs.oracle.com/javase/tutorial/java/javaOO/nested.html (官方文档)
http://www.icourse163.org/learn/ECNU-1206500807?tid=1461498462#/learn/content?type=detail&id=1237939864&cid=1258164917

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容