理解:
一个类中又完整的嵌套了另一个类结构,被嵌套的类称为内部类。外面的类称为外部类,和内部类无关的外部类称为外部其他类。
class A{ // B的外部类
String name;
public void method(){
for(){
int i;
class B{ // A的内部类
String name;
}
}
}
}
class Other{ // B的外部其他类
}
好处:
可以直接访问外部类中的所有成员,包含私有的!!!
分类:
定义在成员位置上:
成员内部类(没有使用static修饰) √
静态内部类(使用static修饰)
定义在局部位置上:
局部内部类(有类名)
匿名内部类(没有类名) √
1、成员内部类
特点:
① 内部类中可以有五大普通成员,不能有静态成员!(因为静态成员随着外部类的加载而加载,但成员内部类随着外部类的对象创建而加载,静态内部类可以)
② 可以添加任意访问修饰符,遵循访问权限限定!
③ 互访原则:
内部类—>外部类
直接访问,包含任意成员(私有的也可以)
外部类—>内部类
不能直接访问,需要通过创建内部类对象再去访问,包含任意成员(私有的也可以)
语法:new Inner().方法();
外部其他类—>内部类
不能直接访问,需要通过创建内部类对象再去访问,只能访问在权限范围内的成员(私有的不可以!!!)
语法:new Outer().new Inner().方法();
④ 当外部类和内部类成员重名时,默认访问的是内部类的成员,遵循就近原则。如果非要访问外部类的成员,可以通过外部类名.this.成员的方式!
示例:
/**
* 此类用于演示内部类:成员内部类的特点和使用
*
*/
public class TestInner1 {
String color;
public static void main(String[] args) {
Outer o = new Outer();
o.new Inner().show();
// o.new Inner().color="";
}
}
class Outer{
protected class Inner{
private String name="张无忌";
// public Inner(){
//
// }
// static{
//
// }
// class InnerInner{
// class InnerInner2{
//
// }
// }
public void show(){
System.out.println(Outer.this.name);
}
}
private String name = "张翠山";
public void method(){
new Inner().show();
// new Inner().color="";
}
}
2、匿名内部类
语法:
new 类名或接口名(参数){
类体
}
功能:创建了一个匿名内部类 & 创建了一个该类对象(类或接口)
使用示例:
// 创建A的子类&创建A的子类对象
new A(){
//类体
public void method(){}
}.method();
// 另一种方法
A a = new A(){
//类体
public void method(){}
};
a.method();
interface A{
void method();
}
对比:
//创建A本类的对象
new A();
特点:
① 类中可以有除了构造器之外的其他成员(属性、方法、初始化块、内部类),不可以有静态成员!
② 不能添加访问修饰符和static,作用域:仅仅在定义它的方法或代码块中使用,并且遵循前向引用的特点!
③ 互访原则:
内部类—>外部类的成员
直接访问,包含私有的成员
外部类—>内部类的成员
只能在作用域内,通过匿名内部类的对象去访问,包含私有的成员
语法:
父类或接口名 引用名 = 匿名内部类对象;
引用名.方法();
细节:匿名内部类可以访问外部类的局部变量,但只能读取,不能更新!(只能访问外部类的final修饰的局部变量!)
原因:局部内部类的生命周期>局部变量生命周期,所以不能直接访问一个可能已经消亡的变量。于是将局部变量复制了一个拷贝让局部内部类使用,
但不能更新,因为如果更新,会导致两个变量的值不一致!
jdk7:要求局部内部类中访问的局部变量必须显式的声明final修饰符
jdk8:局部内部类中访问的局部变量不用显式的声明final修饰符
应用场景:
当做接口的实例作为实参传递给方法!
示例:
//代表示例1:
TreeSet set = new TreeSet(new Comparator(){
@Override
public int compare(Object o1, Object o2) {
// TODO Auto-generated method stub
return 0;
}
});
//代表示例2:
Thread t= new Thread(new Runnable(){
@Override
public void run() {
// TODO Auto-generated method stub
}
});