内部类的分类及内部类的特点
引入
比如人这个类中,要定义大脑这个类,而大脑这个类除了人这个类别的类都不用,那就把大脑声明为人 的内部类了。
内部类使用总结
1、内部类分类
2、内部类的特点
3、如何实例化成员内部类
4、成员内部类中调用外部类的结构
/*
* 类的内部成员之五:内部类
* 1. Java中允许将一个类A声明在另一个类B中,则类A就是内部类,类B称为外部类
*
* 2.内部类的分类:成员内部类(静态、非静态) vs 局部内部类(方法内、代码块内、构造器内)
*
* 3.成员内部类:
* 一方面,作为外部类的成员:
* >调用外部类的结构
* >可以被static修饰(static不能修饰外部类,但能修饰内部类)
* (静态内部类,不能访问外部类的非静态成员,静态内部类,不需要创建外部类的对象就可访问,静态内部类可以有public、protected、默认的、private等多种类型)
* (内部类 可以访问外部类的成员变量)
* >可以被4种不同的权限修饰
*
* 另一方面,作为一个类:
* > 类内可以定义属性、方法、构造器等
* > 可以被final修饰,表示此类不能被继承。言外之意,不使用final,就可以被继承(内部类可以被继承)
* > 可以被abstract修饰(表示该类不能被实例化)
*
*
* 4.关注如下的3个问题
* 4.1 如何实例化成员内部类的对象
* 4.2 如何在成员内部类中区分调用外部类的结构
* 4.3 开发中局部内部类的使用 见《InnerClassTest1.java》,即下面的**5、局部内部类的使用**
*
*/
public class InnerClassTest {
public static void main(String[] args) {
//创建Dog实例(静态的成员内部类):
Person.Dog dog = new Person.Dog();
dog.show();//输出:卡拉是条狗
//创建Bird实例(非静态的成员内部类):
// Person.Bird bird = new Person.Bird();//错误的
//↑因为Bird类是非静态的,非静态的要有外部类的实例才能有类里面非静态的结构
//↓所以要先造人 类,在造Bird类。
Person p = new Person();
Person.Bird bird = p.new Bird();
bird.sing();//输出:我是一只小小鸟
System.out.println();
bird.display("黄鹂");
// 黄鹂
// 杜鹃
// 小明
}
}
//Person是外部类
class Person{
String name = "小明";
int age;
public void eat(){
System.out.println("人:吃饭");
}
//静态成员内部类
static class Dog{
String name;//内部类可以定义属性
int age;
public void show(){//内部类可以定义方法
System.out.println("卡拉是条狗");
// eat();//静态不能调非静态
}
}
//非静态成员内部类
//可以被4种不同的权限修饰
private/protected/public/default class Bird{
String name = "杜鹃";//内部类可以定义属性
public Bird(){//内部类可以定义构造器
}
public void sing(){//内部类可以定义方法
System.out.println("我是一只小小鸟");
eat();//省略的是Person.this.eat();
// this.eat();这样反而错了,因为
// 这意味着调用的本内部类的方法,然而本内部类没有这个方法
Person.this.eat();//这里是 调用外部类的非静态属性
System.out.println(age);
}
//↓调用属性的知识点!!!!!!!!!!!!!!!!!!
public void display(String name){
System.out.println(name);//方法的形参 // 黄鹂
System.out.println(this.name);//内部类的属性 // 杜鹃
System.out.println(Person.this.name);//外部类的属性 // 小明
}
}
public void method(){
//局部内部类(声明在method()方法内)
class AA{
}
}
{
//局部内部类(声明在代码块内)
class BB{
}
}
public Person(){
//局部内部类(声明在构造器内)
class CC{
}
}
}
5、局部内部类的使用
InnerClassTest1.java
public class InnerClassTest1 {
//开发中很少见
public void method(){
//局部内部类
class AA{
}
}
//Comparable是个接口,通过下面这个方法,
// 返回一个实现了Comparable接口 的 类 的对象
public Comparable getComparable(){
//创建一个实现了Comparable接口的类:局部内部类
//有名的实现类的一个匿名对象
//方式一:
// class MyComparable implements Comparable{
//
// @Override//重写了接口中的抽象类
// public int compareTo(Object o) {
// return 0;
// }
//
// }
//
// return new MyComparable();//返回一个实现了Comparable接口 的 类 的对象
//方式二:
// 实现类没有名,对象也没有名
return new Comparable(){
@Override//重写了接口中的抽象类
public int compareTo(Object o) {
return 0;
}
};
}
}
局部内部类使用的一个注意点
public class InnerClassTest {
/*
* 在局部内部类的方法中(比如:show)如果调用局部内部类所声明的方法(比如:method)中的局部变量(比如:num)的话,
* 要求此局部变量声明为final的。
*
* jdk 7及之前版本:要求此局部变量显式的声明为final的
* jdk 8及之后的版本:可以省略final的声明
*
* //通过副本变相地延长局部变量的生命周期让局部内部类可以一直能够访问该局部变量,
* 同时final防止内部类的代码对局部变量产生修改;
* (局部内部类里的num是method(方法)里的副本,修改副本无法修改原num)
*/
public void method(){
(final) int num = 10;//局部变量
class AA{//局部内部类
public void show(){
// num = 20;//规定就是final
System.out.println(num);
}
}
}
}