2020年9月3日 内部类总结

## 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种
* ​        其他修饰符:abstractfinal3)使用外部类的成员上是否有要求

* ​        只能使用外部类的静态成员

(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种

​    其他修饰符:abstractfinal3)使用外部类的成员上是否有要求

​    都可以使用

(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)修饰符要求

​    权限修饰符:不能

​    其他修饰符:abstractfinal3)使用外部类的成员等上是否有要求

​    ①使用外部类的静态成员:随便用

​    ②使用外部类的非静态成员:能不能用要看所在的方法是否是静态的

​    ③使用所在方法的局部变量:必须 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();
    }
}
原文地址:https://www.cnblogs.com/douyunpeng/p/13608863.html