共计 2991 个字符,预计需要花费 8 分钟才能阅读完成。
1、成员内部类
将一个类 A 定义在另一个类 B 里面,里面的那个类 A 就称为内部类,B 则称为外部类。
1.1、定义格式
class 外部类 {class 内部类 {}}
在描述事物时,若一个事物内部还包含其他事物,就可以使用内部类这种结构。比如,电脑 Computer 类中包含鼠标 Mouse 类,这时,Computer 就可以使用内部类来描述,定义在成员位置。如:
class Computer{// 外部类 | |
class Mouse{// 内部类 | |
} | |
} |
1.2、访问
1.2.1、创建内部类对象
外部类名. 内部类名 对象名 = new 外部类型 ().new 内部类型 ();
或
外部类名. 内部类名 对象名 = 外部类对象.new 内部类型 ();
1.2.2、访问特点
内部类可以直接访问外部类的成员,包括私有成员。
外部类要访问内部类的成员,必须要建立内部类的对象。
public class Computer{// 外部类 | |
private boolean kj=false; | |
class Mouse{// 内部类 | |
public void start(){if(kj){System.out.println("鼠标可移动"); | |
}else{System.out.println("鼠标没有反应"); | |
} | |
} | |
} | |
public boolean isKj() {return kj; | |
} | |
public void setKj(boolean kj) {this.kj = kj; | |
} | |
} | |
public class ComputerDemo {public static void main(String[] args) {// 外部类对象 | |
Computer c=new Computer(); | |
// 内部类对象 | |
Computer.Mouse m=c.new Mouse(); | |
// 调用内部类方法 | |
m.start(); | |
// 修改外部类方法 | |
c.setKj(true); | |
// 调用内部类方法 | |
m.start();} | |
} |
运行结果:
2、局部内部类
局部内部类是定义在一个方法或者一个作用域里面的类,它和成员内部类的区别在于局部内部类的访问仅限于方法内或者该作用域内。
2.1、定义格式
class 外部类 { | |
方法(){class 内部类 {}} | |
} |
2.2、应用
class People{public People() {}} | |
class Man{public Man(){ } | |
public People getWoman(){class Woman extends People{// 局部内部类 | |
int age =0; | |
} | |
return new Woman();// 返回局部内部类对象 | |
} | |
} |
局部内部类就像是方法里面的一个局部变量一样,是不能有 public、protected、private 以及 static 修饰符的。
3、静态内部类
静态内部类也是定义在另一个类里面的类,只不过在类的前面多了一个关键字 static。静态内部类是不需要依赖于外部类的,这点和类的静态成员属性有点类似,并且它不能使用外部类的非 static 成员变量或者方法,这点很好理解,因为在没有外部类的对象的情况下,可以创建静态内部类的对象,如果允许访问外部类的非 static 成员就会产生矛盾,因为外部类的非 static 成员必须依附于具体的对象。
3.1、定义格式
class 外部类 {static class 内部类 {}}
3.2、应用
3.2.1、创建内部类对象
外部类名. 内部类名 对象名 = new 外部类名. 内部类名 ();
3.2.2、案例
public class Test {public static void main(String[] args) {// 产生静态内部类对象 | |
Outter.Inner inner = new Outter.Inner();} | |
} | |
class Outter {public Outter() { } | |
// 静态内部类 | |
static class Inner {public Inner() {}} | |
} |
4、匿名内部类
是内部类的简化写法。它的本质是一个带具体实现的父类或者父接口的匿名的子类对象。是最常用的内部类方式。
4.1、定义格式
匿名内部类必须继承一个父类或者实现一个父接口。
匿名内部类有两个步骤:
a. 临时定义一个类型的子类
b. 定义后即刻创建刚刚定义的这个类的对象
new 父类名或者接口名 (){// 方法重写 | |
public void method() {// 执行语句 | |
} | |
}; |
4.2、应用
4.2.1、使用方式
// 已经存在的父类: | |
public abstract class Person{public abstract void eat(); | |
} | |
// 定义并创建该父类的子类对象,并用多态的方式赋值给父类引用变量 | |
Person p = new Person(){public void eat() {System.out.println("我吃了"); | |
} | |
}; | |
// 调用 eat 方法 | |
p.eat(); | |
// 将定义子类与创建子类对象两个步骤由一个格式一次完成 | |
new Person(){public void eat() {System.out.println("我吃了"); | |
} | |
}.eat(); |
4.2.2、案例
// 接口 | |
public interface Fly {public abstract void open(); | |
public abstract void fly(); | |
public abstract void close(); | |
} | |
// 实现接口 | |
public class YanZi implements Fly{ | |
public void open() {System.out.println("张开小翅膀"); | |
} | |
public void fly() {System.out.println("能飞 3000 米高空"); | |
} | |
public void close() {System.out.println("关闭小翅膀,安全着陆"); | |
} | |
} |
匿名内部类完成
public class FlyDemo {public static void main(String[] args) {Fly yz = new YanZi(); | |
yz.open(); | |
yz.fly(); | |
yz.close(); | |
new YanZi().open(); | |
System.out.println("-------------------"); | |
// 实现类对象赋值给父接口 | |
Fly fj = new Fly(){ | |
public void open() {System.out.println("不需要张开翅膀,一直都是张开状态"); | |
} | |
public void fly() {System.out.println("喷气式助力飞行!"); | |
} | |
public void close() {System.out.println("不需要关闭翅膀,得哪撞哪"); | |
} | |
}; | |
fj.open(); | |
fj.fly(); | |
fj.close(); | |
System.out.println("-----------------------------"); | |
// 实现类对象直接以匿名对象的方式调用方法 | |
new Fly() { | |
public void open() {System.out.println("小翅膀"); | |
} | |
public void fly() {System.out.println("乱飞"); | |
} | |
public void close() {System.out.println("各种撞树"); | |
} | |
}.fly();} | |
} |
运行结果:
