内部类
成员内部类
成员内部类概述
成员内部类即定义在成员位置的类。
成员内部类:
普通类可以使用的权限修饰符:public 和 缺省(可省略)
成员内部类可以使用的修饰符:public protected 缺省 private
语法:
[访问权限修饰符] class EnclosedClazz{ //外围(普通)类的访问权限修饰符,只有两个,public和缺省
[访问权限修饰符] class InnerClazz{//内部类访问权限修饰符,有四个,和普通成员一样
}
}
成员内部类不可以定义静态成员、静态方法和静态代码块,其余成员变量、成员方法、构造方法等和普通类一致。
成员内部类的类加载机制:
成员内部类的类加载要靠创建成员内部类实现,因为成员内部类没有静态成员;如果要创建成员内部类,需要在创建外围类的基础上创建内部类,因为成员内部类是依赖于外围类存在的,即成员内部类的实例化实在外围类实例化的基础上的。
内部类可以继承和实现外部的类和接口
成员内部类的成员访问特点
1. 成员内部类访问外围类
成员内部类可以无条件访问外围类的成员变量和成员方法,不受访问权限限制,因为成员内部类的创建依赖于外围类,所以成员内部类中隐含的存在一个外围类;如果内部类和外围类存在同名变量,会触发java中的“就近原则”,这是如果想访问外围类同名成员变量,需要以下面这种形式访问:
EnclosedClazz.this.成员变量
EnclosedClazz.this.成员方法
外围类访问成员内部类成员
2. 外围类访问成员内部类
外围类与内部类成员之间的访问不受权限修饰符限制,即在外围类中可以访问所有内部类的成员,包括private修饰的私有成员变量和成员方法,外围类如果想要访问内部类成员,需要先创建一个成员内部类的对象,再通过成员内部类的引用去访问内部类的成员,例子如下:
//该形式适合在外围类中创建内部类
EnclosedClazz oz = new EnclosedClazz();
InnerClazz ic = oz.new InnerClazz();
//或者二合一
//该形式适合在外围类中创建内部类
InnerClazz ic2 = new EnclosedClazz().new InnerClazz();
如果在外围类的静态方法中去访问内部类的成员,必须用以上的方式创建内部类,即先创建外围类,再通过外围类创建内部类,因为在静态方法找中既不存在外围类也不存在内部类。
如果在外围类的普通方法中去访问内部类的成员,则可以省略创建外围类的过程,直接创建内部类,其语法如下:
InnerClazz ic = new InnerClazz();
外部类访问成员内部类
3. 外部类访问成员内部类
外部类访问成员内部类成员,受访问权限限制,如果拥有访问权限,必须要通过先创建外围类再创建内部类。
语法:
//该方式最全面,适合任何位置
EnclosedClazz.InnerClazz ic3 = new EnclosedClazz().new InnerClazz();
在外部类中,也无法访问被私有化的成员。
成员内部类访问外部类
- 静态成员直接类名点访问
- 普通成员需创建外部类对象
- 受访问权限控制
静态内部类
静态内部类概述
静态内部类也是定义在成员位置的内部类,不同于成员内部类的是,它需要使用static修饰。
语法:
[访问权限修饰符] class EnclosedClazz{ //外围(普通)类的访问权限修饰符,只有两个,public和缺省
[访问权限修饰符] static class InnerClazz{//内部类访问权限修饰符,有四个,和普通成员一样
}
}
静态内部类的类加载机制:
静态内部类是独立于外围类而存在的
创建外围类对象,不会触发静态内部类的类加载
创建静态内部类对象,也不会触发外围类的类加载
静态内部类的创建不依赖于外围类
外围类与静态内部类的类加载是相互独立的
静态内部类和普通类一样,内部可以定义所有成员,包括静态成员
静态内部类的继承和实现与成员内部类并没有什么不同,区别在于静态内部类只能继承一个静态内部类,而不能继承普通类
静态内部类访问外围类
1. 静态内部类访问外围类
静态内部类与外围类之间的相互访问,不受访问权限限制
静态内部类只能直接访问外围类的静态成员,包括私有
静态内部类如果想要访问外围类的普通成员,需要创建外围类的对象
外围类访问静态内部类
2. 外围类访问静态内部类
如果访问静态内部类的静态成员,可以直接使用静态内部类的类名点访问,不受访问权限限制
如果访问静态内部类的普通成员,需要先创建静态内部类对象,不受访问权限限制
在外围内创建静态内部类的语法:
InnerClazz ic = new InnerClazz();
在外围类任意位置都可以创建外围类,并且不需要先创建外围类,因为它们是相互独立的
外部类访问静态内部类
3. 外部类访问静态内部类
创建静态内部类对象语法:
EnclosedClazz.InnerStaticClazz ecisc = new EnclosedClazz.InnerStaticClazz();
访问静态内部类的对象受到访问权限限制
访问静态内部类静态成员变量,不需要创建对象,语法如下:
EnclosedClazz.InnerStaticClazz.静态成员名
同样首要访问权限限制
静态内部类访问外部类
- 静态成员,类名点直接访问
- 普通成员需创建对象访问
- 受访问权限控制
局部内部类
局部内部类概述
局部内部类是定义在一个方法或者一个作用域里面的类
它和成员内部类的区别在于局部内部类的访问仅限于方法内或者该作用域内
将局部内部类看成是局部变量即可
局部内部类自身的特点
1,访问权限修饰符
没有访问权限修饰符的限制
不可以使用 static 修饰局部内部类
2,成员特点
无法定义静态成员
和成员内部类的成员特点是一致的
3,定义位置
- 方法
- 代码块
- if分支
- for循环内部
4,继承和实现
和成员内部类一致
局部内部类的访问特点
局部内部类相当于方法的局部变量,只能在方法内部生效
如果要触发局部内部类的类加载,必须要在方法内部创建内部类的对象才可以
若该方法是普通方法:
局部内部类可以直接外围内的所有成员
局部内部类和局部变量一样,出了方法就失效了
外围类和外部类中无法创建局部内部类,只能在犯法内部创建
若该方法时静态方法:
局部内部类访问外围类的变量不受访问权限限制,但是要先创建外围的对象
其余特点同普通方法
注意事项:
局部内部类如果访问了方法中的局部变量,该局部变量视为一个常量,原因是局部变量与局部内部类的生命周期不同。
匿名内部类与lambda表达式仍然是局部内部类,以上原则也适用
匿名内部类
语法:
new 类名或者接口名(){
//重写方法
};
匿名内部类可以使用父类接收,但是无法调用子类独有的方法。
当我们只使用一次某类或者某接口的子类对象时,使用匿名内部类,会方便一点,简洁一点
lambda表达式
语法:
(接口中那个抽象方法的形参列表) -> {
//这里面重写这个抽象方法,也就是方法体
}
自行练习
\