一个类A内部定义了一个类B,那么B就是A的内部类。A可以成为外部类。
成员内部类
成员内部类创建对象:
外部类名.内部类名 变量 = 外部类对象.new 内部类构造方法(参数)
代码实例:
public class Test {
public static void main(String[] args) {
// 创建成员内部类的对象 : 外部类名.内部类名 对象名= new 外部类构造方法(...).new 内部类的构造方法(...);
Person.Heart heart = new Person().new Heart();
heart.beats();
}
}
// 外部类
class Person {
class Heart {
private int rate;
public void beats() {
System.out.println("咚咚咚!");
}
}
}
内部类访问外部类成员
成员内部类的方法中默认存在一个外部类对象:外部类名.this。
可以用此格式来调用外部类成员,访问时如果(内部类变量和外部类变量)没有冲突,格式可省略。
对于外部类来讲,没有默认的内部类对象,如果要访问内部类成员,需要创建内部类对象。
代码实例:
package com.itheima.innerclass_demo.member_innerclass;
public class Test {
public static void main(String[] args) {
// 创建成员内部类的对象 : 外部类名.内部类名 对象名= new 外部类构造方法(...).new 内部类的构造方法(...);
Person.Heart heart = new Person().new Heart();
heart.beats();
// 静态成员内部类创建对象的方式
// Person.Heart heart = new Person.Heart();
}
}
// 外部类
class Person {
int num = 30;
// 想拿到 num = 20
public void show() {
// 外部类访问内部类成员
Heart heart = new Heart();
System.out.println(heart.num);// 20
}
// 心脏类
class Heart {
private int rate;
int num = 20;
public void beats() {
int num = 10;
System.out.println("咚咚咚!");
System.out.println(num);// 10
System.out.println(this.num);// 20
System.out.println(Person.this.num);// 30
// 若变量只存在于外部类,内部类没有定义,那么完全可以省略外部类.this
}
}
}
匿名内部类
匿名内部类是一个非常特殊的内部类,顾名思义,匿名内部类没有类名,因此这个内部类只能使用一次。
使用场景
匿名内部类一般用于简化代码,若要快速实现一个抽象类或者接口的抽象方法时,我们就可以使用匿名内部类来简化,可以不用专门定义一个有名类来操作。
使用条件
必须要有一个父类(一般就是抽象类或者接口)
案例代码
先看一段不使用匿名内部类实现的代码:
public class Test2 {
public static void main(String[] args) {
useSwimming(new SwimmingImpl());
}
public static void useSwimming(Swimming swimming) {
swimming.swim();
}
}
// 接口
interface Swimming {
public abstract void swim();
}
class SwimmingImpl implements Swimming {
@Override
public void swim() {
System.out.println("我们去🏊吧");
}
}
// 输出:我们去🏊吧
上面这个程序在主类中定义了一个useSwimming方法,该方法接收一个接口对象,因此在主方法调用该方法时需要传入一个接口的实现类,我们就需要额外定义一个实现类SwimmingImpl。接下来我们将上述代码用匿名内部类实现:会发现使用匿名内部类就无需额外创建一个实现类,而是直接对接口进行重写,然后作为参数传递给主调函数即可。
package com.itheima.innerclass_demo.anonymous_innerclass;
public class Test1 {
public static void main(String[] args) {
// 匿名内部类作为参数传递
useSwimming(new Swimming() {
@Override
public void swim() {
System.out.println("游泳");
}
});
}
// 方法的参数是一个接口 , 那么调用此方法需要传入此接口的实现类对象
/*
Swimming swimming = new SwimmingImpl()
*/
public static void useSwimming(Swimming swimming) {
swimming.swim();
}
}
// 接口
interface Swimming {
public abstract void swim();
}
匿名内部类格式 :
new 抽象类名/接口名(){
重写抽象方法
};
注意 : 匿名内部类创建的是一个 子类/实现类 对象
匿名对象的使用方式
-
使用父类型变量多态接收该匿名子类对象。
-
以匿名对象的方式使用
-
直接调用方法使用
-
当做方法的参数传递
-
当做方法的返回值使用
-
package com.itheima.innerclass_demo.anonymous_innerclass;
public class Test2 {
public static void main(String[] args) {
// 1) 直接调用方法使用
new Flyable() {
@Override
public void fly() {
System.out.println("飞~");
}
}.fly();
// 2) 当做方法的参数传递 !!!
useFly(new Flyable() {
@Override
public void fly() {
System.out.println("飞~");
}
});
}
public static void useFly(Flyable flyable) {
flyable.fly();
}
// 作为方法的返回值
public static Flyable getFlyable(){
return new Flyable() {
@Override
public void fly() {
System.out.println("飞~");
}
};
}
}
// 接口
interface Flyable {
public abstract void fly();
}