1. 什么是内部类
- 在Java中,可以将一个类定义在另一个类里面或者一个方法里边,这样的类称为内部类。
- 广泛意义上的内部类一般包括四种:成员内部类,局部内部类,静态内部类,匿名内部类 。
注意:
对于外部类来说,只有两种修饰,public和默认(default),因为外部类放在包中,只有两种可能,包可见和包不可见。
对于内部类来说,可以有所有的修饰,因为内部类放在外部类中,与成员变量的地位一致,所以有四种可能。
2. 内部类分几种
2-1. 成员内部类
// 外部类访问修饰符只有2种:public、default(默认)
public class Outter {
private int age = 12;
private static final String name = "iteng";
// 成员内部类访问修饰符有4种:public、default(默认)、private、protected
class Inner{
private int age = 10;
public void test() {
System.out.println(age); // 10
// 可以访问外部类的私有成员变量、成员方法
System.out.println(Outter.this.age); // 12
System.out.println(name); // iteng
}
}
// 在外部类内访问成员内部类的成员
Inner inner = new Inner();
public static void main(String[] args) {
// 创建内部类对象
Outter.Inner inner = new Outter().new Inner();
inner.test();
System.out.println(inner.age); // 10
}
}
- 成员内部类像是外部类的一个成员,可以无条件的访问外部类的所有成员属性和成员方法(包括private成员和静态成员)
- 成员内部类拥有与外部类同名的成员变量时,会发生隐藏现象,即默认情况下访问的是成员内部类中的成员。如果要访问外部类中的成员,需要以下形式访问:【
外部类.this.成员变量
或外部类.this.成员方法
】 - 在外部类中如果要访问成员内部类的成员,必须先创建一个成员内部类的对象,再通过指向这个对象的引用来访问
- 成员内部类是依附外部类而存在的,也就是说,如果要创建成员内部类的对象,前提是必须存在一个外部类的对象
Inner inner = new Outter().new Inner();
- 内部类可以拥有private、protected、public及包访问权限。
- 如果成员内部类用private修饰,则只能在外部类的内部访问;如果用public修饰,则任何地方都能访问;如果用protected修饰,则只能在同一个包下或者继承外部类的情况下访问;如果是默认访问权限,则只能在同一个包下访问。
- 外部类只能被public和包访问两种权限修饰。
总结:
- 把成员内部类当作成员变量即可,只不过在使用方式有所不同
2-2. 局部内部类
- 局部内部类是定义在一个方法或者一个作用域里面的类
- 它和成员内部类的区别在于局部内部类的访问仅限于方法内或者该作用域内
- 局部内部类就像是方法里面的一个局部变量一样,是不能有
public
、protected
、private
以及static
修饰符的。
public static void main(String[] args) {
// 局部内部类
class LocalInnerClass{
}
}
总结:
- 把局部内部类当作局部变量即可,只不过在使用方式有所不同
2-3. 静态内部类
- 静态内部类是不需要依赖于外部类的,这点和类的静态成员属性有点类似
- 不能使用外部类的非static成员变量或者方法。
public class Outter {
private int age = 12;
private static final String name = "iteng";
static class Inner{
private int age = 10;
public void test() {
System.out.println(age); // 10
System.out.println(Outter.this.age); // 编译错误,不能访问外部类非static成员变量或者方法。
System.out.println(name); // iteng
}
}
// 在外部类内访问内部类
Inner inner = new Inner();
public static void main(String[] args) {
// 创建静态内部类对象
Outter.Inner inner = new Outter.Inner();
}
}
总结:
- 把静态内部类当作静态变量即可,只不过在使用方式有所不同
2-4. ★匿名内部类
public class Outter {
public static void main(String[] args) {
Thread t1 = new Thread(){
// 匿名内部类, 其实就是Thread类没有名字的子类,重写了Thread类的run(),临时用一下而已
@Override
public void run() {
System.out.println("t1");
}
};
Runnable task = new Runnable() {
// 匿名内部类, 其实就是Runnable接口没有名字的实现类,重写了Runnable接口的run(),临时用一下而已
@Override
public void run() {
}
};
}
}
- 一般使用匿名内部类的方法来编写事件监听代码
- 匿名内部类是不能有访问修饰符和static修饰符的
- 匿名内部类是唯一一种没有构造器的类
- 匿名内部类用于继承其他类或是实现接口,并不需要增加额外的方法,只是对继承方法的实现或是重写。
总结:
- 匿名内部类的写法,都可以用Lambda表达式来简化
- 匿名内部类需要对方法进行重写