文章目录
- 一、Note
- 1、意义
- 2、分类
- 2.1、按照是否是成员来划分
- 2.2、Java语言规范中的分类
- 3、声明
- 3.1、静态内部类(静态嵌套类)
- 3.2、实例内部类(非静态嵌套类)
- 3.3、局部内部类
- 3.4、匿名内部类
- 3.5、注意
- 4、字节码文件的名称
- 5、声明内部类类型变量
- 6、创建内部类的实例
- 7、不关注内部类的继承
- 二、Code
- 1、理解嵌套内部类和局部内部类的区别
- Computer.java
- ComputerTest.java
- 2、在实例内部类中使用 外部类类名.this 来引用外部类的实例
- CellPhone.java
- CellPhoneTest.java
- 3、创建实现了某个接口的匿名类的实例
- Flyable.java
- AnonymousClassTest1.java
- 4、创建继承了某个抽象类并实现其中所有抽象方法的匿名类的实例
- Human.java
- AnonymousClassTest2.java
- 5、创建继承了某个具体类的匿名类的实例
- Aircraft.java
- AnonymousClassTest3.java
- 6、理解匿名类不能显式声明构造方法(但匿名类是有构造方法的)
- AnonymousClassTest4.java
- 7、匿名内部类应用举例:在实参中传入匿名类的实例
- Printable.java
- Store.java
- StoreTest.java
一、Note
1、意义
-
为了更好的封装
- 为了实现更好的封装,普通类(非内部类)的访问修饰符不能为private或protected,而内部类可以。所以当我们将内部类声明为private时,就可对外隐藏内部类
-
使Java的多继承机制变得更加完善
-
每个内部类都能独立的继承或实现其他的类或接口,所以无论外部类是否已经继承或实现其他的类或接口,对于内部类都没有影响,内部类使得多继承的解决方案变得完整。
-
方便编写线程代码
-
方便编写事件驱动程序
-
方便将存在一定逻辑关系的类组织在一起,又可以对外界隐藏
2、分类
2.1、按照是否是成员来划分
(按照是否在类体括号中声明来划分)
-
Nested Classes(嵌套类)
- 静态嵌套类(静态内部类)
- 实例嵌套类(实例内部类)
-
Local Classes(局部类)
- 局部内部类
- 匿名内部类
-
嵌套类和局部类最重要的界限是作用域不同
- 嵌套类的作用域是属于类的,嵌套类属于类的成员
- 局部类的作用域是局部的
- 所有的匿名内部类都是局部的
2.2、Java语言规范中的分类
-
嵌套类
- 静态嵌套类(被static修饰的成员内部类)
-
内部类
-
实例内部类
- 没有被static修饰的成员内部类
- 除了常量外,不能声明static修饰的字段;以及方法
-
因此,实例内部类里可以定义静态变量[相当于常量]
-
-
局部类
-
在宿主类类体括号内部的某个局部区域中声明的内部类
-
除了常量外,不能声明static修饰的字段;以及方法
- 作用域是局部的
-
匿名类
- 不能显式指定类名
- 因此,也不能显式声明构造方法
- 但是创建匿名类的实例时,的确会调用父类的指定构造方法
- 但是通过javac反编译匿名类得到结果可知,匿名类是有构造方法的,只是不公开
- 除了常量外,不能声明static修饰的字段
-
3、声明
3.1、静态内部类(静态嵌套类)
复制代码
1
2
3
4
5
6public class Computer { static class Brand { //在类中写,有static修饰 static int x; } }
3.2、实例内部类(非静态嵌套类)
复制代码
1
2
3
4
5
6
7
8public class Computer { class Brand { //在类中写,没有static修饰 //static int x; final static int x; } } //内部类未加修饰符时,就是默认修饰符,包私有,外部类也可访问此内部类
3.3、局部内部类
- 出了类之后就无法使用,有局部作用域的限制
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18public class Computer { public void show() { class Printer { //static int x; //static void hello(){} //final static void hello(){} final static int x; } } } 或者: public class Compuer{ { class Printer{ } } }
3.4、匿名内部类
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15package cn.edu.ecut; public class Computer{ public void welcome(){ // 以{}作为类体,继承Object类 Object o = new Object() { //只有类体括号,不能显式指定类名 } System.out.println(o.getClass()); } public static void main(String[] args){ Computer c = new Computer(); c.welcome();//输出:class cn.edu.ecut.Computer$1 }
3.5、注意
- 局部内部类和匿名内部类绝不会有static修饰,因为它们不是属于类的,它们属于局部代码块
4、字节码文件的名称
- 嵌套类对应的字节码文件名称是 外部类类名$内部类类名.class
- 局部内部类对应的字节码文件名称是 外部类类名$N内部类类名.class
- 数字N指的是局部内部类在外部类的方法或代码块中出现的次数(顺序)
- 匿名内部类对应的字节码文件名称是 外部类类名$N.class
- 数字N指的是不同局部内部类在外部类的方法或代码块中出现的顺序
- 注意:文件名把
.class
去掉,剩下的其实就是类名
5、声明内部类类型变量
-
对于嵌套类来说,使用 外部类类名.内部类类名 来指定变量类型
- 如:Computer.Brand brand = null ;
-
对于局部类来说,只能在其作用域内部直接使用其类名来声明
- 如:Printer p = null ;
-
对于匿名内部类来说,因为不能显式指定匿名类的类名,所以也就不能声明匿名类类型的引用变量,但是可以声明匿名类所实现的接口类型的引用变量 或 匿名类所继承父类类型的引用变量
6、创建内部类的实例
-
静态内部类(静态嵌套类)
- 使用 new 外部类类名.内部类类名(参数) 形式来创建其实例
- 如:Computer.Brand b = new Computer.Brand();
-
实例内部类(非静态嵌套类)
- 首先需要创建外部类类型的实例(比如Computer c = new Computer();)
- 然后再在外部类的实例的基础上来创建实例内部类的实例(比如Computer.Mainboard m = c.new Minboard())
- 即:Computer.Mainboard m = null; m = new Computer().new Mainboard();
-
局部内部类
- 直接在 其有效作用域{} 中使用new关键字创建即可
-
匿名内部类
-
创建实现了某个接口的匿名类的实例
- 此时匿名类的直接父类是Object类
- 此时匿名类实现了指定的接口(单个)
-
创建继承了某个抽象类并实现其中所有抽象方法的匿名类的实例
- 匿名类的直接父类就是相应的抽象类
- 在创建匿名类实例时可以调用父类中带参数的构造方法
-
创建继承了某个具体类的匿名类的实例
- 匿名类的直接父类就是相应的具体类
- 可以在匿名类中重写被继承类中的某些方法(根据需求来确定)
- 在创建匿名类实例时可以调用父类中带参数的构造方法
-
7、不关注内部类的继承
- 内部类主要是为了封装
二、Code
1、理解嵌套内部类和局部内部类的区别
Computer.java
复制代码
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
40
41
42
43
44
45
46
47
48
49
50
51package cn.edu.ecut; // Computer 是个外部类,它对应的 字节码 文件是 Computer.class public class Computer { // 电脑 // 直接在 外部类 的 类体括号中声明的 类,就是 嵌套类 ( Nested Classes ) // 嵌套类 也被称作 成员内部类 // 有 static 修饰的 嵌套类,也被称作 静态嵌套类 或 静态内部类 static class Brand { // 铭牌 // 对应的 字节码 文件名称是 Computer$Brand.class } // 没有 static 修饰的 嵌套类,也被称作 非静态嵌套类 或 非静态内部类 或 实例嵌套类 或 实例内部类 class Mainboard { // 主板 // 对应的 字节码 文件名称是 Computer$Mainboard.class //static int x;//错误,因为x是类加载时就创建的,但是Mainboard内部类是创造一个类对象时才创建的 final static int x = 100; //定义一个常量是可以的 } public void show() { // 局部内部类 class Printer { // 对应的 字节码 文件名称是 Computer$1Printer.class } Printer p = new Printer(); System.out.println( p ); } public void hello() { // 局部内部类 class Printer { // 对应的 字节码 文件名称是 Computer$2Printer.class } Printer p = new Printer(); System.out.println( p ); } //Object o = new Object() { };// 若放在类{}里面,也可以,但此时它不是成员内部类,它仍然是局部内部类,因为它只能用一次 public void welcome() { Object o = new Object() { // 只有类体括号、不能显式指定类名的局部内部类-匿名内部类 }; System.out.println( o.getClass() ); } public void baby() { Object o = new Object() { }; System.out.println( o.getClass() ); } public static void main(String[] args) { Computer c = new Computer(); c.welcome(); // 输出:class cn.edu.ecut.Computer$1 c.welcome(); //class cn.edu.ecut.Computer$1 c.baby(); //class cn.edu.ecut.Computer$2 } }
ComputerTest.java
复制代码
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
27package cn.edu.ecut; public class ComputerTest { public static void main(String[] args) { // 声明 静态嵌套类 ( 静态内部类 ) 的 引用变量 Computer.Brand b = null ; // 创建 静态嵌套类 ( 静态内部类 ) 的实例 b = new Computer.Brand(); System.out.println( b ); // 获得 Brand 类的全限定名称 System.out.println( b.getClass().getName() ); // 获得 Brand 类的规范化名称(规范化类名),以原点隔开。对以后类加载有用(毕竟类加载的是类,不是文件==>把全限定名称即文件名中的$换为.) System.out.println( b.getClass().getCanonicalName() ); System.out.println( "~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~" ); // m所指向的对象包围在c的对象内部,称作包围实例; // Computer.Mainboard m= new Computer().new Mainboard(); // 声明 非静态嵌套类 ( 实例内部类 ) 的 引用变量 Computer.Mainboard m = null ; // 创建 非静态嵌套类 ( 实例内部类 ) 的实例 Computer c = new Computer() ; // 首先创建外部类的实例 m = c.new Mainboard(); // 在 外部类实例 基础之上创建 实例内部类 实例 System.out.println( m ); //m.toString()形式,即m指向的对象的【类型(包名.类名)@地址】 System.out.println( m.getClass().getName() ); // 全限定名称 System.out.println( m.getClass().getCanonicalName() ); //规范化名称 } }
输出:
复制代码
1
2
3
4
5
6
7
8cn.edu.ecut.Computer$Brand@4d591d15 cn.edu.ecut.Computer$Brand cn.edu.ecut.Computer.Brand ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ cn.edu.ecut.Computer$Mainboard@6a6824be cn.edu.ecut.Computer$Mainboard cn.edu.ecut.Computer.Mainboard
2、在实例内部类中使用 外部类类名.this 来引用外部类的实例
CellPhone.java
复制代码
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
35package cn.edu.ecut; public class CellPhone { public String brand = "一加" ; public class Screen { String brand = "京东方" ; public void show() { String brand =""; // 在 实例内部类 中 使用 this 可以引用 该实例内部类的当前实例 // 有this.则brand指的是“京东方”;没有this.则brand指的是“” System.out.println( this.brand ); // 通过 "外部类类名.this.字段名" 来引用外部类的实例变量 System.out.println( CellPhone.this.brand ); } public CellPhone getOuter() { // 在 实例内部类 中 可以使用 "外部类类名.this" 来引用 外部类的 当前实例 return CellPhone.this ; } } // end : Screen public static class A{ public void show(){ //System.out.println(CellPhone.this); // 错误 //静态内部类只能访问静态成员,不能访问外部类的实例(非静态成员);实例内部类可以访问外部类的实例,不能访问静态成员 } } /* static class B{ CellPhone p = new CellPhone(); } 此代码有些问题,若没有 static,则更加极有可能造成内存溢出,因为在创建实例(new CellPhone())时,就会产生B这个类,但无法确定产生多少B这个类 class B{ CellPhone p = new CellPhone(); } */ }
CellPhoneTest.java
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19package cn.edu.ecut; public class CellPhoneTest { public static void main(String[] args) { /* // 引用变量 p 指向了 一个 CellPhone 类型的实例 CellPhone p = new CellPhone(); // 引用变量 s 指向了一个 Screen 类型的实例 CellPhone.Screen s = p.new Screen(); */ // 创建 实例内部类 Screen 类的实例 CellPhone.Screen s = new CellPhone().new Screen(); // 标记 System.out.println( s ); s.show(); // 用p接收外部类 CellPhone的实例 CellPhone p = s.getOuter(); // 此处的p不是重新new出来的,是在“标记”这行new的这两个实例时就存在的,当时创建外部类Cellphone的实例是什么,p就接收什么 System.out.println( p ); } }
输出:
复制代码
1
2
3
4
5cn.edu.ecut.CellPhone$Screen@65ae6ba4 京东方 一加 cn.edu.ecut.CellPhone@7960847b
3、创建实现了某个接口的匿名类的实例
Flyable.java
复制代码
1
2
3
4
5package cn.edu.ecut; public interface Flyable { void fly(); }
AnonymousClassTest1.java
复制代码
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
40
41
42
43
44
45
46
47
48package cn.edu.ecut; import java.util.Arrays; /** * 【最常见的应用】使用 匿名类 实现 接口,并创建该类的实例 */ public class AnonymousClassTest1 { public static void main(String[] args) { // 声明 Flyable 类型的引用变量,并将 null 赋值给该变量 Flyable f = null ; // 引用变量 f 的 编译时类型 是 Flyable // f = new Flyable() ; // 接口都没有构造方法,也不能被实例化 // 形式上,似乎是在通过 new 关键字 创建 Flyable 接口的实例 【尸体】 // 本质上,创建一个实现了 Flyable 接口的 匿名类 的实例 【借尸还魂】 // {}作为一个类体,实现了接口,实现了接口里的抽象方法 f = new Flyable() { // 匿名类开始 【魂】 @Override public void fly() { // 在匿名类中实现 Flyable 接口中所有的抽象方法 System.out.println( "飞飞飞,在梦里飞,想飞哪里飞哪里" ); } }; // 匿名类结束 f.fly(); /* //匿名内部类只使用这一次;若想再次使用这个类的实例,则需要再写一个匿名类,或者可以重新声明一个类实现接口 f = new Flyable() { @Override public void fly() { System.out.println( "飞飞飞,在梦里飞,想飞哪里飞哪里" ); } }; //若是再写了一个匿名类,则此时字节码文件有: //AnonymousClassTest1$1.class,AnonymousClassTest1$2.class */ Class<?> c = f.getClass() ; // 获得运行时类型 System.out.println( c.getName() ); // 全限定名称-cn.edu.ecut.AnonymousClassTest1$1 System.out.println( c.getCanonicalName() ); // 规范化类名 ( 注意这里是 null ) // 匿名内部类不能显式书写类名,因此输出类名为null Class<?> p = c.getSuperclass(); // 获得 c 所表示类型的父类 System.out.println( p.getName() ); //java.lang.Object // 获得 c 所表示的类所实现的接口 (或 c所表示的接口 所继承的接口) Class<?>[] interfaces = c.getInterfaces(); System.out.println( Arrays.toString( interfaces ) ); //此处调用的是Arrays/toString(Object[] a),Class是Object的子类,因此可直接写Class类型的 } }
输出:
复制代码
1
2
3
4
5
6飞飞飞,在梦里飞,想飞哪里飞哪里 cn.edu.ecut.AnonymousClassTest1$1 null java.lang.Object [interface cn.edu.ecut.Flyable]
4、创建继承了某个抽象类并实现其中所有抽象方法的匿名类的实例
Human.java
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15package cn.edu.ecut; public abstract class Human { public String name ; public Human() { super(); System.out.println( "Human()" ); } public Human( String name ) { super(); this.name = name ; System.out.println( "Human( String )" ); } public abstract void eat( String food ); }
AnonymousClassTest2.java
复制代码
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
31package cn.edu.ecut; /** * 创建继承了某个抽象类并实现其中所有抽象方法的匿名类的实例 */ public class AnonymousClassTest2 { public static void main(String[] args) { Human h = null ; // h = new Human( "张三丰" ); // 抽象类有构造方法,但是抽象类不能实例化 // 形式上,似乎是在通过 new 关键字 创建抽象类 Human 的实例 【尸体】 // 本质上,创建一个继承了 Human 类 并实现了其中所有抽象方法的 匿名类 的实例 【借尸还魂】 h = new Human( "张三丰" ) { // 匿名类开始 【魂】 @Override public void eat(String food) { // 重写抽象类中的抽象方法 System.out.println( this.name + "吃" + food ); } } ; // 匿名类结束 h.eat( "西瓜" ); System.out.println( "~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~" ); h = new Human() { @Override public void eat(String food) { System.out.println( this.name + "吃" + food ); } }; h.name = "张君宝" ; h.eat( "冬瓜" ); } }
输出:
复制代码
1
2
3
4
5
6Human( String ) 张三丰吃西瓜 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ Human() 张君宝吃冬瓜
5、创建继承了某个具体类的匿名类的实例
Aircraft.java
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18package cn.edu.ecut; public class Aircraft { public String type ; public Aircraft(){ super(); } public Aircraft( String type ){ super(); this.type = type ; } public void fly() { System.out.println( "飞行中..." ); } public void travel() { System.out.println( "行驶中..." ); } }
AnonymousClassTest3.java
复制代码
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
40
41
42
43
44
45
46
47
48
49package cn.edu.ecut; import java.util.Arrays; /** * 1、创建继承了某个具体类的匿名类实例 * 2、可以在匿名类中重写被继承类中的某些方法 */ public class AnonymousClassTest3 { public static void main(String[] args) { Aircraft a = new Aircraft(); a.fly(); a.travel(); System.out.println( "~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~" ); Aircraft b = new Aircraft() { } ; // 父类引用 指向 子类对象 ( 因为最后的 { } 就是一个匿名类的类体 ),子类即为匿名类 System.out.println( b.getClass() ); System.out.println( "~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~" ); // 调用 父类无参数构造方法 Aircraft c = new Aircraft() { // 在匿名类中声明实例变量 String name = "航天飞机" ; @Override public void fly() { // 重写从父类 中继承的 fly 方法 System.out.println( this.name + "正在飞行" ); } } ; c.fly(); // 调用重写后的方法 System.out.println( c.getClass() ); System.out.println( "~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~" ); // 调用 父类有参数构造方法 Aircraft d = new Aircraft( "飞船" ) { // 在匿名类中声明实例变量 String name = "嫦娥二号" ; @Override public void fly() { // 重写从父类 中继承的 fly 方法 System.out.println( this.name + this.type + "正在月球上空飞行" ); } } ; d.fly(); // 调用重写后的方法 System.out.println( "~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~" ); Class<?> cc = d.getClass() ; // 获得运行时类型 System.out.println( cc.getName() ); // 全限定名称 System.out.println( cc.getCanonicalName() ); // 规范化类名 ( 注意这里是 null ) Class<?> p = cc.getSuperclass(); // 获得 cc 所表示类型的父类 System.out.println( p.getName() ); Class<?>[] interfaces = cc.getInterfaces(); // 获得 cc 所表示的类所实现的接口 System.out.println( Arrays.toString( interfaces ) ); } }
输出:
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15飞行中... 行驶中... ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ class cn.edu.ecut.AnonymousClassTest3$1 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ 航天飞机正在飞行 class cn.edu.ecut.AnonymousClassTest3$2 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ 嫦娥二号飞船正在月球上空飞行 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ cn.edu.ecut.AnonymousClassTest3$3 null //匿名类在语言规范中不能显式书写类名,因此输出null cn.edu.ecut.Aircraft [] //说明没有实现任何接口,因为匿名类直接继承了父类Aircraft.java
6、理解匿名类不能显式声明构造方法(但匿名类是有构造方法的)
AnonymousClassTest4.java
复制代码
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
29package cn.edu.ecut; import java.lang.reflect.Constructor; import java.util.Arrays; /** * 尝试获取匿名类的构造方法 */ public class AnonymousClassTest4 { public static void main(String[] args) { // 在 java.lang.Cloneable 接口中没有声明任何方法 Cloneable c = new Cloneable() { // 创建 实现了接口Cloneable的 匿名类实例 // 这里什么都不用写 }; /* // {}作为一个类体,继承了父类Human,调用父类Human中的带参数构造(通过匿名类中的带参构造调用父类构造,匿名类中的带参构造中第一行为:super("张翠山");,只不过匿名类中的构造对我们不可见) Human c = new Human( "张翠山" ) { // 创建 继承了具体类Human的 匿名类实例 @Override public void eat(String food) { } }; */ System.out.println( c ); System.out.println( "~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~" ); Class<?> clazz = c.getClass(); // 通过 反射 来获取 匿名类 中所有的构造方法组成的数组 Constructor<?>[] constructors = clazz.getDeclaredConstructors(); System.out.println( Arrays.toString( constructors ) ); } }
输出:
复制代码
1
2
3
4
5
6
7
8
9
10cn.edu.ecut.AnonymousClassTest4$1@4d591d15 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ [cn.edu.ecut.AnonymousClassTest4$1()] //获取到一个无参的构造 若换成注释里的内容,并且将Cloneable一行注释,则输出: Human( String ) cn.edu.ecut.AnonymousClassTest4$1@4aa8f0b4 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ [cn.edu.ecut.AnonymousClassTest4$1(java.lang.String)]
7、匿名内部类应用举例:在实参中传入匿名类的实例
Printable.java
复制代码
1
2
3
4
5
6
7
8
9package cn.edu.ecut; // 打印接口 public interface Printable { // 打印 void print( String content ); // 复印 String copy( String content ); }
Store.java
复制代码
1
2
3
4
5
6
7
8
9
10package cn.edu.ecut; public class Store { public void print( Printable p , String content ) { p.print(content); // 这里调用的是 Printable 实例的 print 方法 } public String copy( Printable p , String content ) { return p.copy(content) ; // 这里调用的是 Printable 实例的 copy 方法 } }
StoreTest.java
复制代码
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
37package cn.edu.ecut; public class StoreTest { public static void main(String[] args) { Store s = new Store(); // 方法一:传入匿名类实例 Printable p = new Printable() { // 引用变量p指向 实现了接口Printable的 匿名内部类的对象 String name = "HP打印机" ; // 匿名类的实例变量 @Override public void print(String content) { System.out.println( this.name + " 正在打印 " + content ); } @Override public String copy(String content) { System.out.println( this.name + " 正在复印 " + content ); String s = new String( content ); return s ; } }; s.print( p , "犯我中华者虽远必诛" ); // 方法二:传入匿名类实例 s.print( new Printable() { String name = "爱普生打印机" ; // 匿名类的实例变量 @Override public void print(String content) { System.out.println( this.name + " 正在打印 " + content ); } @Override public String copy(String content) { System.out.println( this.name + " 正在复印 " + content ); String s = new String( content ); return s ; } } , "犯我中华者虽远必诛" ); } }
输出:
复制代码
1
2
3HP打印机 正在打印 犯我中华者虽远必诛 爱普生打印机 正在打印 犯我中华者虽远必诛
最后
以上就是活泼学姐最近收集整理的关于16、Inner Class(内部类)的全部内容,更多相关16、Inner内容请搜索靠谱客的其他文章。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复