java内部类详解
内部类
概述
-
定义:把类定义在其他类的内部,这个类就被称为内部类。
-
作用:
- 可以实现细节隐藏
- 可以实现多继承
- 程序编写更高效或节省空间
- 优化接口的实现
- 讲太多也没啥意义,项目做得越多,对这些理论知识的理解会更深刻。多敲多练。
-
访问特点:
- 内部类可以直接访问外部类的成员,包括私有成员
- 外部类要访问内部类的成员,必须创建对象
- 注意,内部类和外部类之间没有继承关系
内部类的类型
- 成员内部类
- 非静态内部类
- 静态内部类
- 局部内部类
- 匿名内部类
详解
-
成员内部类
- 概述:创建在成员位置
- 外界如何创建内部类对象:
- 外部类名.内部类名 对象名 =new 外部类名().new 内部类名();
![enter description here enter description here](https://img2018.cnblogs.com/blog/805060/201911/805060-20191123122320708-1188779027.png)
-
常见修饰符
- private:
一般来说,内部类是不会让外界直接访问的,为了保证数据的安全性,常用private来修饰内部类。- 用private修饰后,在其他类里是直接访问不到内部类的,所以要采用如下访问方式:在成员方法中创建内部类对象,然后调用其方法:
- 用private修饰后,在其他类里是直接访问不到内部类的,所以要采用如下访问方式:在成员方法中创建内部类对象,然后调用其方法:
- static:
为了访问数据更方便,可以把内部类定义为static- 注意:
1.被静态修饰的成员内部类只能访问外部类的静态成员(这里是因为static先加载的原因)
2.静态内部类内部可以有静态方法也可以有非静态方法
3.外部类不能直接访问静态内部类的实例成员,但可以使用静态内部类的类名作为调用者来访问静态内部类的类成员,也可以使用静态内部类对象作为调用者来访问静态内部类的实例成员。 (这里的本质还是封装和静态) - 访问方式:内部类名 对象名 = 外部类名.内部类名();
- 注意:
- private:
-
面试题:补齐下列程序(ABC三处应该填入什么),让控制台依次输出30,20,10
class Outer { public int num = 10; class Inner { public int num = 20; public void show() { int num = 30; System.out.println(A); System.out.println(B); System.out.println(C); } } }
答案:A-num; B-this.num(this指向当前对象); C-Outer.this.num(限制为外部类对象。也可以写new Outer().num,但是这里主要考内部外部类this的使用)
-
局部内部类
- 概述:如果把一个内部类定义在方法里面定义,等同一个局部变量,则这个内部类就是一个局部内部类。可以直接访问外部类的成员。
![enter description here enter description here](https://img2018.cnblogs.com/blog/805060/201911/805060-20191123122321584-1961540444.png)
- 访问方式:创建内部类对象,通过对象调用内部类方法,来使用局部内部类功能
- 局部内部类访问局部变量的注意事项:
- 局部变量必须用final修饰:因为局部变量会随着方法的调用完毕而消失,这个时候,局部对象并没有立马从堆内存中消失,还要使用那个变量。为了让数据还能继续被使用,就用fianl修饰,这样,在堆内存里面存储的其实是一个常量值。
- 匿名内部类
- 概述:匿名内部类的语法有些特别,创建匿名内部类时会立即创建一个该类的实例,这个类定义立即消失,匿名内部类不能重复使用。因此匿名内部类适合创建那种只需要一次使用的类。
- 格式:
new 父类构造器|实现接口(){
重写方法;
} - 本质:一个继承了类或者实现了接口的子类匿名对象
![enter description here enter description here](https://img2018.cnblogs.com/blog/805060/201911/805060-20191123122321857-505231508.png)
- 开发中的写法(这里以TreeSet实现比较器为例)
![enter description here enter description here](https://img2018.cnblogs.com/blog/805060/201911/805060-20191123122322108-497573003.png)
-
注意:
- 匿名内部类不能定义构造器,因为匿名内部类没有类名,也就无法定义构造器,但是匿名内部类可以定义实例初始化块,通过初始化块来完成初始化操作。
-
面试题:补齐代码,在控制台输出helloworld
interface Inter { void show(); } class Outer { //补齐代码 } class OuterDemo { public static void main(String[] args) { Outer.method().show(); } }
分析:
1:Outer.method()可以看出method()应该是Outer中的一个静态方法。
2:Outer.method().show()可以看出method()方法的返回值是一个对象。又由于接口Inter中有一个show()方法,所以method()方法的返回值类型是一个接口。
答案:public static Inter method() { return new Inter() { public void show() { System.out.println("HelloWorld"); } }; }