1. 内部类分类
- 成员内部类(static成员内部类和非static成员内部类)
- 局部内部类(不谈修饰符)、匿名内部类 匿名内部类属于局部内部类,在方法中
2. 创建内部类
case1: 这种情况在外部类的的成员方法中使用内部类和使用普通类没有什么区别
public class Parcel1 {
class Contents {
private int i = 11;
public int value() { return i; }
}
class Destination {
private String label;
Destination(String whereTo) {
label = whereTo;
}
String readLabel() { return label; }
}
// Using inner classes looks just like
// using any other class, within Parcel1:
public void ship(String dest) {
Contents c = new Contents();
Destination d = new Destination(dest);
System.out.println(d.readLabel());
}
public static void main(String[] args) {
Parcel1 p = new Parcel1();
p.ship("Tasmania");
}
}
/* Output:
Tasmania
*/
case2: 在外部类的方法中使用内部类的引用
package innerclasses;
public class Parcel2 {
class Contents {
private int i = 11;
public int value() { return i; }
}
class Destination {
private String label;
Destination(String whereTo) {
label = whereTo;
}
String readLabel() { return label; }
}
public Destination to(String s) {
return new Destination(s);
}
public Contents contents() {
return new Contents();
}
public void ship(String dest) {
Contents c = contents();
Destination d = to(dest);
System.out.println(d.readLabel());
}
public static void main(String[] args) {
Parcel2 p = new Parcel2();
p.ship("Tasmania");
Parcel2 q = new Parcel2();
// Defining references to inner classes:
Parcel2.Contents c = q.contents(); // Contents c = q.contents();也可以
Parcel2.Destination d = q.to("Borneo");//Destination d = q.to("Borneo"); 也可以
}
}
/* Output:
Tasmania
*/
在外部类的静态方法和非静态方法中创建内部类的对象,可以使用OuterClassName.InnerClassName来访问,也可以直接使用InnerClassName来访问,但是在其它类中必须使用OuterClassName.InnerClassName来访问
3. 使用.this 和.new
使用.this: 需要生成对外部类对象的引用,可以使用外部类的名字后面紧跟圆点和this
public class DotThis {
void f() { System.out.println("DotThis.f()"); }
public class Inner {
public DotThis outer() {
return DotThis.this;
// A plain "this" would be Inner's "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();
}
}
/* Output:
DotThis.f()
*/
使用.new: 创建某个内部类的对象
public class DotNew {
public class Inner {}
public static void main(String[] args) {
DotNew dn = new DotNew();
DotNew.Inner dni = dn.new Inner();
}
}
必须使用外部类的对象来创建该内部类对象,在拥有外部类对象之前是不可能创建内部类对象的。这是因为内部类对象会暗暗地连接到建它的外部类对象上。但是,如果你创建的是嵌套类(静态内部类),那么它就不需要对外部类对象的引用
4. 局部内部类
- 只能在声明它的方法或代码块中使用,而且是先声明后使用。除此之外的任何地方都不能使用该类
- 局部内部类的对象可以通过外部方法的返回值返回使用,返回值类型只能是局部内部类的父类或父接口类型
- 局部内部类可以使用外部类的成员,包括私有的
- 局部内部类可以使用外部方法的局部变量,但是必须是final的(比如方法被销毁了,方法里面的局部变量也就没有了,但该方法中的内部类可能还在执行(如线程),还要使用该变量,所以外部类变量设置为final的,变成常量,使用的时候内部类可以复制一个副本过去,相当于就不使用该局部变量了)
3. 匿名内部类
public interface Contents {
int value();
}
public class Parcel7 {
public Contents contents() {
return new Contents() { // Insert class definition
private int i = 11;
@Override public int value() { return i; }
}; // Semicolon required
}
public static void main(String[] args) {
Parcel7 p = new Parcel7();
Contents c = p.contents();
}
}
contents() 方法将返回值的生成与表示这个返回值的类的定义结合在一起!另外,这个类是匿名的,它没有名字
- 一个匿名内部类一定是在new的后面,用其隐含实现一个接口或实现一个类
- 匿名内部类必须继承父类或实现接口
- 定义一个匿名内部类,并且希望它使用一个在其外部定义的对象,那么编译
器会要求其参数引用是 final 的
4. 嵌套类(静态内部类)
-
如果不需要内部类对象与其外部类对象之间有联系,那么可以将内部类声明为
static,这通常称为嵌套类 -
普通的内部类不能有 static 数据和 static 字段,也不能包含嵌套类。但是嵌套类可以包含所有这些东西
5. 内部类的访问权限
- 普通内部类拥有其外围类的所有元素的访问权,没有任何限制
- 静态内部类只能访问外部类的静态成员变量
- 非static的成员内部类中的成员不能声明为static的