《Java编程思想》笔记10-内部类
可以将一个类的定义放在另一个类的定义内部,这就是内部类。
public class Outer {
class Inner {
Inner() {System.out.println("Hello I am Inner Class!");}
public Outter outer(){
return Outter.this; // 返回外部类对象
}
}
Inner getInner(){return new Inner();}
Outer(){System.out.println("Hello I am Outer Class!");}
public static void main(String[] args) {
Outer outer=new Outer();
Inner myInner=outer.getInner(); // 实例化内部类,方法一
Inner newInner=outer.new Inner(); // 实例化内部类,方法二
}
}
- 在初始化外部类 Outer 的时候,并不会自动初始化内部类 Inner。
- 如果 Inner 类不是静态的,要实例化内部 Inner 类,必须通过外部 Outer 类的实例。
- 非静态内部类自动拥有对其外部类所有成员的访问权。
- 内部类持有对外部类对象引用的语法:
外部类名称.this
。 - private 内部类,可以完全隐藏实现的细节。
在方法和作用域内的内部类
方法内部,称为局部内部类。
作用域方面,如果内部类声明在if条件语句下作用域中,那超出这个域也是不可用的。
匿名内部类
匿名类没有命名的构造器(类本身就没有名字),可以通过实例初始化来完成构造器的功能。
匿名内部类从 JDK8 开始能访问非 final 的参数了
JDK8 之前为保护外部类的变量不被破坏,Java 硬性规定匿名内部类只能访问 final 类型的外部对象。但从 JDK8 开始,访问非 final 对象编译器也不会报错了。但匿名内部类内部仍然不能改变这些对象,因为匿名内部类内部会对这些对象做一份拷贝。所有操作都在这个镜像上进行。
嵌套类
静态内部类
普通的内部类不能有 static 数据和 static 字段,也不能包含嵌套类。但是嵌套类可以包含这些。
接口的内部类,嵌套类可以作为接口的一部分。
为什么需要内部类
每个内部类都能独立地继承自一个(接口的)实现,所以无论外部类是否已经继承了某个(接口的)实现,对于内部类都没有影响。可以有效的实现了多重继承。
如果拥有的是抽象的类或具体的类,而不是接口,那就只能使用内部类才能实现多重继承。
class D {}
abstract class E {}
class Z extends D {
E makeE() { return new E() {}; }
}
public class MultiImplementation {
static void takesD(D d) {}
static void takesE(E e) {}
public static void main(String[] args) {
Z z = new Z();
takesD(z);
takesE(z.makeE());
}
}
- 内部类可以有多个实例,每个实例可以拥有独立于外部类对象的不同信息;
- 一个外部类可以有多个内部类,每个内部类可以以不同的方式实现同一个接口或者继承同一个类;
- 内部类实例创建时刻并不受到外部类对象创建的限制;
- 用内部类不会制造“is-a”关系的混乱,每个内部类都是个实体。
闭包和回调
闭包是一种可调用的对象,它记录了来自创建它的作用域的一些信息。内部类是一种面向对象的闭包,不仅包含了外部类的信息,而且通过包含一个指向外部类对象的引用,可以操作所有成员,包括private。
回调,通过其它对象携带的信息,可以在稍后的某个时刻调用初始对象。回调的价值在于灵活性,可以在运行时决定需要调用的方法。 GUI编程将体现得更明显。
继承内部类
class Outer {
class Inner {}
}
public class InheritInner extends Outer.Inner {
//! InheritInner() {} // Won’t compile
InheritInner(Outer o) {
o.super();
}
}
内部类可以被覆盖吗
继承外部类,如果直接再定义一遍内部类,并不会覆盖原有内部类。若想覆盖原有内部类,必须连同外部类一起,同时显式地继承内部类,然后再重写内部类子类的方法。
class Outer {
class Inner {
public innerMethod(){System.out.println("Outer.Inner.innerMethod()")}
}
}
public class InheritOuter extends Outer {
public class InheritInner extends Outer.Inner {
public innerMethod(){System.out.println("InheritOuter.InheritInner.innerMethod()")}
}
}
局部内部类
局部内部类不能有访问限定符;有访问局部final变量和外部类所有成员的权限;可以有命名的构造器;在方法外不能访问。
绝大部分情况下,可以用匿名类来替代局部内部类,除非:
- 需要命名的构造器,或者需要重载构造器
- 需要多个内部类的对象
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 bin07280@qq.com
文章标题:《Java编程思想》笔记10-内部类
文章字数:1.2k
本文作者:Bin
发布时间:2018-03-28, 21:12:22
最后更新:2019-08-06, 00:46:42
原始链接:http://coolview.github.io/2018/03/28/Java%E7%BC%96%E7%A8%8B%E6%80%9D%E6%83%B3/%E3%80%8AJava%E7%BC%96%E7%A8%8B%E6%80%9D%E6%83%B3%E3%80%8B%E7%AC%94%E8%AE%B010-%E5%86%85%E9%83%A8%E7%B1%BB/版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。