定义 :将一个类定义放在一个类的内部,这就是内部类。
10.1创建内部类
OuterClassName。InnerClassName
10.2链接到外部类
内部类能访问外围对象的所有成员,而不需要任何特殊条件。此外内部类还拥有其外部类的所有元素的访问权。包括private
原因:当某个外围类的对象创建了一个内部类对象时,此内部类对象必定会秘密的捕获一个指向那个外围类对象的引用。然后,在你访问此外围类的成员时,就是用那个引用来选择外围类的成员。
10.3 使用.this和.new
1).this
如果你需要生产对外部类对象的引用,可以说还有外部类的名字后面紧跟圆点和this。
public class DotThis{ void f(){System.out.println("DotThis.f()")} public class Inner{ public DotThis outer(){ return DotThis.this; } } public Inner inner(){ return new Inner();} public static void main(String[] args){ DotThis dt=new DotThis(); DotThis .Inner dti=dt.inner(); dti.outer().f(); } }
输出 DotThis.f()
2).new
告知某些其他对象,去创建其某个内部类的对象,必须在new表达式中提供对其他外部类对象的引用,需要使用.new。
public class DotNew {
public class Inner {}
public static viod main(String [] args){
DotNew dn =new DotNew();
DotNew.Inner dni =dn.new Inner();
}
}
必须先声明外部类,才能创建内部类。除非是静态内部类,则不需要创建外部类。
10.4内部类与向上转型
10.5在方法和作用域内的内部类
1)在方法的作用域内(而不是在其他类的作用域内)创建一个完整的类,叫做局部内部类。
2)在同一个子目录下的任意类中对某个内部类使用已有的局部内部类,并不会产生命名冲突。
10.5 匿名内部类
public class Paecel{
public Contents contents(){
return new Contents(){
private int i=11;
public int value() {return i;}
};
}
public static void main(String[] args){
Parcel p=new Parcel();
Contents c=p.contents();
}
}
这种奇怪的语法指的是:“创建一个继承自Contents的匿名类的对象。”通过new表达式返回的引用自动向上转型为Contents的引用。
其中的 匿名内部类末尾的分号,并不是标记内部类的结束,标记的是表达式的结束。
如果定义一个匿名内部类,并且希望使用一个外部定义的对象,那么编译器会要求其参数引用是final的。如果不使用,那么可以不是final。
匿名内部类没有构造器,因为没有名字,但是通过实例初始化,可以创建一个构造器的效果。
对于匿名内部类而言,实例初始化的实际效果就是构造器。当然,他受到了限制——你不能重载实例初始化方法,所以你只能有一个这样的“构造器”。
匿名内部类与正规的继承相比有些受限,因为匿名内部类既可以拓展类,也可以实现接口,但是两者不能兼备。如果是实现接口,也只能实现一个接口。 10.6工厂方法
10.7嵌套类
如果不需要内部类对象与其外围类对象之间有联系,那么可以将内部类声明为static。这通常称为嵌套类。
普通的内部类对象隐私的保存了一个引用,指向创建他的外围类对象,然鹅,当内部类是static的时,就不说这样了。
嵌套类意味着:
①要创建嵌套类的对象 ,并不需要其外围类对象。
②不能从嵌套类的对象中访问非静态的外围类对象。
嵌套类和普通内部类还有一个区别。普通内部类的字段和方法,只能放在类的外部层次上,所有普通内部类不能有static数据和static字段,也不能包含嵌套类,但是嵌套类可以包含这些东西。
10.7.1接口内部的类
正常情况下,不能再接口内部放置任何代码,但是嵌套类可以作为接口的一部分。你放到接口的任何类都自动的是public 和static 的,因为类是static的,只是将嵌套类置于接口的命名空间内,这听不违反接口的原则。你甚至可以在内部类中实现其外围接口。
10.7.2从多层嵌套类中访问外部类的成员
内部类可以多层嵌套。
class A {
class B{
class c{}
}
}
10.8为什么需要内部类
内部类最吸引人的地方是:每个内部类都能独立的继承自一个(接口的)实现,所以无论外围类是否已经继承了某个(接口的)实现,对于内部类都没有影响。
内部类允许继承多个非接口类型(类或抽象类)
10.8.1 闭包和回调
10.8.2内部类和框架控制
10.9内部类的继承
10.10内部类可以被覆盖吗
“覆盖”内部类就像它是外围类的一个方法,并不起什么作用。
10.11 局部内部类
局部内部类不能有访问说明符,因为它不是外围类的一部分;但是它可以访问当前代码块的常量,以及此外围类的所有成员。
局部构造器的名字在方法外是不可见的。为什么我们要选择局部内部类而且不是匿名内部类,因为需要一个已命名的构造器,或者是需要重载构造器,而匿名内部类只能用于实例初始化。
所以使用局部内部类而不使用匿名内部类的另一个理由就是,需要不只是一个该内部类的对象。
10.12内部类标识符
内部类也会生成.class文件,以包含他们的Class对象信息。命名规则 外围类的名字+“$”,+内部类的名字 A$B.class。
如果内部类是匿名的,编译器会简单的产生一个数字作为其标识符。如果内部类是嵌套在别的内部类中,只需要直接将他们的名字加载器外围类标识符与$后面。
原文:https://www.cnblogs.com/needoffer/p/10885984.html