定义:将一个类A定义在另一个类B里面,里面的那个类A就称为内部类,B则称为外部类。
一个事物内部还有一个独立的事物,内部的事物脱离外部的事物无法独立使用时,需要使用内部类。
内部类可以直接访问外部类的成员,包括私有成员。
内部类按定义的位置分类可以分为成员内部类和局部内部类;
成员内部类:
创建内部类对象格式:
class 外 部 类 {
// 成员变量
// 成员方法
class 内 部 类 {
// 成员变量
// 成员方法
}
}
外部类名.内部类名 对象名 = new 外部类型().new 内部类型();
内部类仍然是一个独立的类,在编译之后会内部类会被编译成独立的.class文件,但是前面冠以外部类的类名 和$符号 。如:Body$Heart.class
public class Body {
public boolean live = true;
public void walk() {
System.out.println("散步");
}
class Heart {
public void jump() {
// 直接访问外部类成员
if (live) {
System.out.println("心脏在跳动");
} else {
System.out.println("心脏不跳了");
}
}
}
}
public class Body {
private int weight = 30;
// 在成员位置定义一个类
public class Heart {
private int weight = 20;
public void jump() {
int weight = 10;
System.out.println("心脏在跳动 " + weight); // 10
System.out.println("心脏在跳动 " + this.weight); // 20
System.out.println("心脏在跳动 " + Body.this.weight); // 30
}
}
public static void main(String[] args) {
Heart heart = new Body().new Heart();
heart.jump();
}
}
--------------------------------------------------------------------------------------
心脏在跳动 10
心脏在跳动 20
心脏在跳动 30
局部内部类:
局部内部类编译后仍然是一个独立的类,编译后有$还有一个数字。Chinese$1Chopsticks.class
class 外部类名 {
数据类型 变量名;
修饰符 返回值类型 方法名(参数列表) {
// …
class 内 部 类 {
// 成员变量
// 成员方法
}
}
}
public class Chinese {
private String name = "lady gaga";
public void walk() {
System.out.println(name + "散步");
}
public void eat(){
class Chopsticks{
int length = 15;
public void use(){
System.out.println("使用筷子" + length);
// 局部内部类可以直接访问外部类的成员
walk();
System.out.println(name);
}
}
// 在定义好局部内部类后,直接就创建对象
Chopsticks c = new Chopsticks();
c.use();
}
public static void main(String[] args) {
Chinese chinese = new Chinese();
chinese.eat();
}
}
------------------------------------------------------------------
使用筷子15
lady gaga散步
lady gaga
匿名内部类:
匿名内部类是内部类的简化写法,本质是一个带具体的父类或父接口的匿名的子类对象。
使用匿名内部类的前提条件:必须继承一个父类或实现一个接口,但最多只能继承一个父类,或实现一个接口。
使用匿名内部类前使用接口的步骤:
- 定义子类;
- 重写接口方法;
- 创建子类对象;
调用重写后的方法;
interface Swim {
public abstract void swimming();
}
// 1. 定义接口的实现类
class Student implements Swim {
// 2. 重写抽象方法
@Override
public void swimming() {
System.out.println("狗刨式...");
}
}
public class Demo07 {
public static void main(String[] args) {
// 使用匿名内部类
new Swim() {
@Override
public void swimming() {
System.out.println("自由泳...");
}
}.swimming();
// 接口 变量 = new 实现类(); // 多态,走子类的重写方法
Swim s2 = new Swim() {
@Override
public void swimming() {
System.out.println("蛙泳...");
}
};
s2.swimming();
}
}
通常在方法的形式参数是接口或者抽象类时,也可以将匿名内部类作为参数传递。
interface Swim {
public abstract void swimming();
}
// 1. 定义接口的实现类
class Student implements Swim {
// 2. 重写抽象方法
@Override
public void swimming() { System.out.println("狗刨式...");
}
}
public class Demo07 {
public static void main(String[] args) {
// 普通方式传入对象
// 创建实现类对象
Student s = new Student();
goSwimming(s);
// 匿名内部类使用场景:作为方法参数传递
Swim s3 = new Swim() {
@Override
public void swimming() { System.out.println("蝶泳...");
}
};
// 传入匿名内部类
goSwimming(s3);
// 完美方案: 一步到位
goSwimming(new Swim() {
public void swimming() {
System.out.println("大学生, 蛙泳...");
}
});
goSwimming(new Swim() {
public void swimming() {
System.out.println("小学生, 自由泳...");
}
});
}
// 定义一个方法,模拟请一些人去游泳
public static void goSwimming(Swim s) {
s.swimming();
}
}
更多互联网故事欢迎关注公众号:互联网小茶馆