## 7.10 内部类
1、内部类的概念
声明在另外一个类里面的类就是内部类。
2、内部类的4种形式
(1)静态内部类
(2)非静态成员内部类
(3)有名字的局部内部类
(4)匿名内部类
### 7.10.1 匿名内部类
1、语法格式:
```java
//在匿名子类中调用父类的无参构造
new 父类(){
内部类的成员列表
}
//在匿名子类中调用父类的有参构造
new 父类(实参列表){
内部类的成员列表
}
//接口没有构造器,那么这里表示匿名子类调用自己的无参构造,调用默认父类Object的无参构造
new 父接口名(){
}
```
2、匿名内部类、匿名对象的区别?
```java
System.out.println(new Student("张三"));//匿名对象
Student stu = new Student("张三");//这个对象有名字,stu
//既有匿名内部类,又是一个匿名的对象
new Object(){
public void test(){
.....
}
}.test();
//这个匿名内部类的对象,使用obj这个名字引用它,既对象有名字,但是这个Object的子类没有名字
Object obj = new Object(){
public void test(){
.....
}
};
```
3、使用的形式
(1)示例代码:继承式
```java
abstract class Father{
public abstract void test();
}
class Test{
public static void main(String[] args){
//用父类与匿名内部类的对象构成多态引用
Father f = new Father(){
public void test(){
System.out.println("用匿名内部类继承了Father这个抽象类,重写了test抽象方法")
}
};
f.test();
}
}
```
(2)示例代码:实现式
```java
interface Flyable{
void fly();
}
class Test{
public static void main(String[] args){
//用父接口与匿名内部类的对象构成了多态引用
Flyable f = new Flyable(){
public void fly(){
System.out.println("用匿名内部类实现了Flyable这个接口,重写了抽象方法");
}
};
f.fly();
}
}
```
(3)示例代码:用匿名内部类的匿名对象直接调用方法
```java
new Object(){
public void test(){
System.out.println("用匿名内部类的匿名对象直接调用方法")
}
}.test();
```
(4)示例代码:用匿名内部类的匿名对象直接作为实参
```java
Student[] all = new Student[3];
all[0] = new Student("张三",23);
all[1] = new Student("李四",22);
all[2] = new Student("王五",20);
//用匿名内部类的匿名对象直接作为实参
//这个匿名内部类实现了Comparator接口
//这个匿名内部类的对象,是定制比较器的对象
Arrays.sort(all, new Comparator(){
public int compare(Obeject o1, Object o2){
Student s1 = (Student)o1;
Student s2 = (Student)o2;
return s1.getAge() - s2.getAge();
}
});
```
### 7.10.2 静态内部类
1、语法格式
```java
【修饰符】 class 外部类名 【extends 外部类的父类】 【implements 外部类的父接口们】{
【其他修饰符】 static class 静态内部类 【extends 静态内部类自己的父类】 【implements 静态内部类的父接口们】{
静态内部类的成员列表;
}
外部类的其他成员列表;
}
```
2、 使用注意事项
(1)包含成员是否有要求:
可以包含类的所有成员
(2)修饰符要求:
* 权限修饰符:4种
* 其他修饰符:abstract、final
(3)使用外部类的成员上是否有要求
* 只能使用外部类的静态成员
(4)在外部类中使用静态内部类是否有要求
* 正常使用
(5)在外部类的外面使用静态内部类是否有要求
```java
(1)如果使用的是静态内部类的静态成员
外部类名.静态内部类名.静态成员
(2)如果使用的是静态内部类的非静态成员
①先创建静态内部类的对象
外部类名.静态内部类名 对象名 = new 外部类名.静态内部类名(【实参列表】);
②通过对象调用非静态成员
对象名.xxx
```
(6)字节码文件形式:外部类名$静态内部类名.class
3、示例代码
```java
class Outer{
private static int i = 10;
static class Inner{
public void method(){
//...
System.out.println(i);//可以
}
public static void test(){
//...
System.out.println(i);//可以
}
}
public void outMethod(){
Inner in = new Inner();
in.method();
}
public static void outTest(){
Inner in = new Inner();
in.method();
}
}
class Test{
public static void main(String[] args){
Outer.Inner.test();
Outer.Inner in = new Outer.Inner();
in.method();
}
}
```
### 7.10.3 非静态内部类
1、语法格式
```java
【修饰符】 class 外部类名 【extends 外部类的父类】 【implements 外部类的父接口们】{
【修饰符】 class 非静态内部类 【extends 非静态内部类自己的父类】 【implements 非静态内部类的父接口们】{
非静态内部类的成员列表;
}
外部类的其他成员列表;
}
```
2、 使用注意事项
(1)包含成员是否有要求:
不允许出现静态的成员
(2)修饰符要求
权限修饰符:4种
其他修饰符:abstract,final
(3)使用外部类的成员上是否有要求
都可以使用
(4)在外部类中使用非静态内部类是否有要求
在外部类的静态成员中不能使用非静态内部类
(5)在外部类的外面使用非静态内部类是否有要求
```java
//使用非静态内部类的非静态成员
//(1)创建外部类的对象
外部类名 对象名1 = new 外部类名(【实参列表】);
//(2)通过外部类的对象去创建或获取非静态内部类的对象
//创建
外部类名.非静态内部类名 对象名2 = 对象名1.new 非静态内部类名(【实参列表】);
//获取
外部类名.非静态内部类名 对象名2 = 对象名1.get非静态内部类对象的方法(【实参列表】);
//(3)通过非静态内部类调用它的非静态成员
对象名2.xxx
```
(6)字节码文件形式:外部类名$非静态内部类名.class
3、示例代码
```java
class Outer{
private static int i = 10;
private int j = 20;
class Inner{
public void method(){
//...
System.out.println(i);//可以
System.out.println(j);//可以
}
}
public void outMethod(){
Inner in = new Inner();
in.method();
}
public static void outTest(){
// Inner in = new Inner();//不可以
}
public Inner getInner(){
return new Inner();
}
}
class Test{
public static void main(String[] args){
Outer out = new Outer();
Outer.Inner in1 = out.new Inner(); //创建
in1.method();
Outer.Inner in2 = out.getInner(); //获取
in2.method();
}
}
```
### 7.10.4 局部内部类
1、语法格式
```java
【修饰符】 class 外部类名 【extends 外部类的父类】 【implements 外部类的父接口们】{
【修饰符】 返回值类型 方法名(【形参列表】){
【修饰符】 class 局部内部类 【extends 局部内部类自己的父类】 【implements 局部内部类的父接口们】{
局部内部类的成员列表;
}
}
外部类的其他成员列表;
}
```
2、 使用注意事项
(1)包含成员是否有要求
不允许出现静态的成员
(2)修饰符要求
权限修饰符:不能
其他修饰符:abstract、final
(3)使用外部类的成员等上是否有要求
①使用外部类的静态成员:随便用
②使用外部类的非静态成员:能不能用要看所在的方法是否是静态的
③使用所在方法的局部变量:必须 final修饰的
(4)在外部类中使用局部内部类是否有要求
有作用域
(5)在外部类的外面使用局部内部类是否有要求
没法使用
(6)字节码文件形式:外部类名$编号局部内部类名.class
3、示例代码
```java
class Outer{
private static int i = 10;
private int j = 20;
public void outMethod(){
class Inner{
public void method(){
//...
System.out.println(i);//可以
System.out.println(j);//可以
}
}
Inner in = new Inner();
in.method();
}
public static void outTest(){
final int k = 30;
class Inner{
public void method(){
//...
System.out.println(i);//可以
System.out.println(j);//不可以
System.out.println(k);//可以
}
}
Inner in = new Inner();
in.method();
}
}