什么是内部类
在一个类里面,再定义一个类,这个类就是内部类
内部类表示的事物是外部类的一部分
内部类单独出现没有任何意义
举例:
public class Outer{ //外部类
public class Inner{ } //内部类
}
什么时候用内部类
B类表示的事物是A类的一部分,且B单独存在没有意义。
比如:汽车的发动机,ArrayList的迭代器,人的心脏等等
内部类的访问特点
内部类可以直接访问外部类的成员,包括私有
外部类要访问内部类的成员,必须创建对象
举例说明:
//需求:写一个Javabean类描述汽车。
//属性:汽车品牌,车龄,汽车颜色,发动机品牌,发动机使用年限
//外部类
public class Car {
private String carName;
private int carAge;
private String carColor;
public void show(){
System.out.println(carName);
//外部类要访问内部类的成员,必须创建对象
Engine e = new Engine();
System.out.println(e.engineName);
}
//内部类
public class Engine{
private String engineName;
private int engineAge;
public void show(){
//内部类可以直接访问外部类的成员,包括私有
System.out.println(carName);
System.out.println(engineName);
}
//内部类构造函数
public Engine() {
}
public Engine(String engineName, int engineAge) {
this.engineName = engineName;
this.engineAge = engineAge;
}
//内部类get&set方法
public String getEngineName() {
return engineName;
}
public void setEngineName(String engineName) {
this.engineName = engineName;
}
public int getEngineAge() {
return engineAge;
}
public void setEngineAge(int engineAge) {
this.engineAge = engineAge;
}
}
//外部类构造函数
public Car() {
}
public Car(String carName, int carAge, String carColor) {
this.carName = carName;
this.carAge = carAge;
this.carColor = carColor;
}
//外部类get&set方法
public String getCarName() {
return carName;
}
public void setCarName(String carName) {
this.carName = carName;
}
public int getCarAge() {
return carAge;
}
public void setCarAge(int carAge) {
this.carAge = carAge;
}
public String getCarColor() {
return carColor;
}
public void setCarColor(String carColor) {
this.carColor = carColor;
}
}
内部类的分类
成员内部类,静态内部类,局部内部类,匿名内部类
成员内部类
编写成员内部类注意点
写在成员位置的,属于外部类的成员。(例如上述汽车的发动机就是成员内部类)
成员内部类可以被一些修饰符所修饰,比如:private,默认,protected,public,static等在成员内部类里面,JDK16之前不能定义静态变量,之后才可以定义静态变量
获取成员内部类对象的两种方式
方式一:外部类编写方法,对外提供内部类对象
方式二:直接创建
格式:外部类名.内部类名 对象名= 外部类对象.内部类对象;
范例:Outer Inner oi = new Outer().new Inner( );
内部类用public修饰时,两种方法都可以使用
内部类用private修饰时,只能用方式一,并且只能用父类以多态的方式接收,因此用Object
成员内部类如何调用外部类的成员变量
Outer.this.变量名 (Outer.this获取了外部类对象的地址值)
public class Outer {
private int a = 10;
public class Inner{
private int a = 20;
public void show(){
int a = 30;
System.out.println(Outer.this.a);//10
System.out.println(this.a);//20
System.out.println(a);//30
}
}
}
静态内部类
注意事项
1.静态内部类也是成员内部类中的一种
2.静态内部类只能访问外部类中的静态变量和静态方法
创建静态内部类对象的格式
外部类名.内部类名 对象名 = new 外部类名.内部类名();
Outer.Inner oi = new Outer.Inner();
如何调用静态内部类中的方法
非静态方法: 先创建对象,用对象调用
静态方法: 外部类名.内部类名.方法名();
代码演示
局部内部类
注意事项
1.将内部类定义在成员方法里面就叫做局部内部类,类似于方法里面的局部变量。
2.外界是无法直接使用,需要在方法内部创建对象并使用。
3.该类可以直接访问外部类的成员,也可以访问方法内的局部变量。
代码演示
public class Outer {
//成员变量
int b = 20;
//成员方法
public void show(){
//局部变量
int a =10;
//局部内部类
class Inner{
//非静态方法
public void method1(){
//可以直接访问外部类的成员
System.out.println(b);
//也可以访问方法内的局部变量
System.out.println(a);
System.out.println("非静态方法");
}
//静态方法
public static void method2(){
System.out.println("静态方法");
}
}
//外界是无法直接使用,需要在方法内部创建对象并使用。
Inner i = new Inner();
i.method1();
Inner.method2();
}
}
测试类
public class test {
public static void main(String[] args) {
Outer o = new Outer();
o.show();
}
}
匿名内部类
什么是匿名内部类
隐藏了名字的内部类,可以写在成员位置,也可以写在局部位置。
匿名内部类的格式
new 类名或者接口名 () {
重写方法};
格式的细节
包含了继承或实现,方法重写,创建对象。
整体就是一个类的子类对象或者接口的实现类对象
继承,方法重写,创建对象
1,把前面的class删掉,剩余的内容就变成了一个没有名字的类
2,这个没有名字的类想要继承父类Animal。把Animal写在了大括号的前面,表示这个没有名字的类继承了父类Animal,所以需要在类中重写父类里面所有的抽象方法。
3,还想要创建这个没有名字的类的对象,所以使用new关键字,小括号代表空参构造
实现,方法重写,创建对象
1,把前面的class删掉,剩余的内容就变成了一个没有名字的类
2,这个没有名字的类想要实现Swim接口。把Swim写在了大括号的前面,表示这个没有名字的类实现了Swim接口,所以需要在类中重写接口里面所有的抽象方法。
3,还想要创建这个没有名字的类的对象,所以使用new关键字,小括号代表空参构造
使用场景
当方法的参数是接口或者类时,
如果子类或实现类只要使用一次,就可以用匿名内部类简化代码。
代码演示
传统方式需要建立Dog子类继承父类Animal
而子类只使用一次,所以可以用匿名内部类简化代码