定义:一个类定义在别的类的内部;
分类:
- 静态嵌套类
- 非静态嵌套类(内部类):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

