内部类
内部类是一类特殊的类,指的是定义在一个类的内部的类。实际开发中,为了方便的使
用外部类的相关属性和方法,这时候我们通常会定义一个内部类。
上图所示,内部类共分为:匿名内部类,局部内部类和成员内部类。而成员内部类又可以分成非静态内部类和静态内部类。
内部类的概念
一般情况,我们把类定义成独立的单元。有些情况下,我们把一个类放在另一个类的内
部定义,称为内部类(innerclasses)。内部类可以使用public、default、protected 、private 以及static 修饰。而外部顶级类(我们以前接触的类)只能使用public 和default 修饰。
==注意!!==
内部类只是一个编译时概念,一旦我们编译成功,就会成为完全不同的两个类。对于一个名为Outer 的外部类和其内部定义的名为Inner 的内部类。编译完成后会出现==Outer.class== 和==Outer$Inner.class== 两个类的字节码文件。所以内部类是相对独立的一种存在,其成员变量/方法名可以和外部类的相同。
内部类的展示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| public class Outer {
private int age = 100;
private void show() { System.out.println("这是外部类!"); }
public static void main(String[] args) { Outer.Inner newname = new Outer().new Inner(); newname.inner(); }
public class Inner{ private int age = 110000; public void inner(){ System.out.println(age); System.out.println(Test000.this.age); show(); } } }
|
内部类的作用:
内部类提供了更好的封装。只能让外部类直接访问,不允许同一个包中的其他类直接访问。
内部类可以直接访问外部类的私有属性,内部类被当成其外部类的成员。但外部类不能访问内部类的内部属性。
非静态内部类
非静态内部类(外部类里使用非静态内部类和平时使用其他类没什么不同)
非静态内部类对象必须寄存在一个外部类对象里。因此,如果有一个非静态内部类对象那么一定存在对应的外部类对象。非静态内部类对象单独属于外部类的某个对象。
非静态内部类可以直接访问外部类的成员,但是外部类不能直接访问非静态内部类成员。
非静态内部类不能有静态方法、静态属性和静态初始化块。
成员变量访问要点:(例子同上面代码)
- 内部类里方法的局部变量:变量名。
- 内部类属性:this.变量名。
- 外部类属性:外部类名.this.变量名。
非静态内部类对象创建方式
非静态内部类对象新建方式一共有两种:(针对Outer类内嵌Inner类举例)
1 2 3 4 5 6
| Outer.Inner in01 = new Outer().new Inner();
Outer out02 = new Outer(); Inner in02 = out02.new Inner();
|
静态内部类
与大多数静态方法相似,静态内部类只需要在类名前加上static即可
1 2 3 4
| static class ClassName { }
|
- 静态内部类可以访问外部类的静态成员,不能访问外部类的普通成员。
- 静态内部类看做外部类的一个静态成员。
(这点与静态方法不能调用非静态成员性质一致)
静态内部类对象创建方式
依旧针对Outer类内嵌Inner类举例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| Outer.Inner in03 = new Outer.Inner();
-----------------------------------------------
Class Outer{ public static int a = 100; public int b = 200; static class Inner{ puiblic void print(){ System.out.println(a); System.out.println(b); } } }
|
匿名内部类
Java 中可以实现一个类中包含另外一个类,且不需要提供任何的类名直接实例化。主要是用于在我们需要的时候创建一个对象来执行特定的任务,可以使代码更加简洁。匿名类是不能有名字的类,它们不能被引用,只能在创建时用 new 语句来声明它们。
1 2 3 4 5
| new 父类构造器(实参类表) \实现接口() { }
|
匿名内部类的应用主要有两种:一种是匿名类继承父类、另一种是匿名类实现接口。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
|
class Polygon { public void display() { System.out.println("在 Polygon 类内部。"); } }
class AnonymousDemo { public void createClass() {
Polygon p1 = new Polygon() { public void display() { System.out.println("在匿名类内部。"); } }; p1.display(); } }
class Main { public static void main(String[] args) { AnonymousDemo an = new AnonymousDemo(); an.createClass(); } }
|
上述代码中,AnonymousDemo匿名类中的createClass()方法内部继承类新建了一个Polygon对象并改写Override了display()方法,这中间的p1对象调用并销毁次数与方法调用次数一致。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
|
interface Inter{ void run(); }
class Imp implements Inter{ @override public void run(){ System.out.println("我正在跑!"); } }
public class AnonymousInnerClass{ public void test(Inter a) { a.run(); } public static void main(String[] args) { AnonymousInnerClass b = new AnonymousInnerClass(); b.test(new Imp);
b.test(new Inter(){ @Override public void run(){ System.out.println("我正在慢跑五分钟!"); } }); } }
|
局部内部类
定义在方法内部的,作用域只限于本方法,称为局部内部类。
局部内部类的的使用主要是用来解决比较复杂的问题,想创建一个类来辅助我们的解决
方案,到那时又不希望这个类是公共可用的,所以就产生了局部内部类。局部内部类和成员
内部类一样被编译,只是它的作用域发生了改变,它只能在该方法中被使用,出了该方法就
会失效。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
|
public class TestLocalInnerClass { public void show() { class Inner { public void test() { System.out.println("Hello World"); } } new Inner().test(); } public static void main(String[ ] args) { new TestLocalInnerClass().show(); } }
|