共计 5570 个字符,预计需要花费 14 分钟才能阅读完成。
外部类(Inner Class)和动态外部类(Static Nested Class)的区别:
定义在一个类外部的类叫外部类,蕴含外部类的类称为外部类。外部类能够申明 public、protected、private 等拜访限度,能够申明 为 abstract 的供其余外部类或外部类继承与扩大,或者申明为 static、final 的,也能够实现特定的接口。外部类按惯例的类拜访形式应用外部 类,惟一的差异是外部类能够拜访外部类的所有办法与属性,包含公有办法与属性。
(1) 创立实例
OutClass.InnerClass obj = outClassInstance.new InnerClass(); // 留神是外部类实例.new,外部类
AAA.StaticInner in = new AAA.StaticInner();// 留神是外部类自身,动态外部类
(2) 外部类中的 this
内 部类中的 this 与其余类一样是指的自身。创立外部类对象时,它会与发明它的外围对象有了某种分割,于是能拜访外围类的所有成员,不需任何非凡条件,可理 解为外部类链接到外部类。用外部类创立外部类对象时,此外部类对象会机密的捕捉一个指向外部类的援用,于是,能够通过这个援用来拜访外围类的成员。
(3) 外部类拜访外部类
外部类相似外部类的属性,因而拜访外部类对象时总是须要一个创立好的外部类对象。外部类对象通过‘外部类名.this.xxx’的模式拜访外部类的属性与办法。如:
System.out.println("Print in inner Outer.index=" + pouter.this.index);
System.out.println("Print in inner Inner.index=" + this.index);
(4)外部类向上转型
外部类也能够和一般类一样领有向上转型的个性。将外部类向上转型为基类型,尤其是接口时,外部类就有了用武之地。如果外部类是 private 的,只能够被它的外部类问,从而齐全暗藏实现的细节。
(5)办法内的类
办法内创立的类(留神办法中也能定义类),不能加拜访修饰符。另外,办法外部的类也不是在调用办法时才会创立的,它们一样也被当时编译了。
(6)动态外部类
定义动态外部类:在定义外部类的时候,能够在其后面加上一个权限修饰符 static。此时这个外部类就变为了动态外部类。
通常称为嵌套类,当外部类是 static 时,意味着:
[1] 要创立嵌套类的对象,并不需要其外围类的对象;
[2] 不能从嵌套类的对象中拜访非动态的外围类对象(不可能从动态外部类的对象中拜访外部类的非动态成员);
嵌 套类与一般的外部类还有一个区别:一般外部类的字段与办法,只能放在类的内部档次上,所以一般的外部类不能有 static 数据和 static 字段,也不能蕴含嵌套类。然而在嵌套类里能够蕴含所有这些货色。也就是说,在非动态外部类中不能够申明动态成员,只有将某个外部类润饰为动态类,而后才可能在这 个类中定义动态的成员变量与成员办法。
另外,在创立动态外部类时不须要将动态外部类的实例绑定在外部类的实例上。一般非动态外部类的 对象是附丽在外部类对象之中的,要在一个外部类中定义一个动态的外部类,不须要利用关键字 new 来创立外部类的实例。动态类和办法只属于类自身,并不属于 该类的对象,更不属于其余外部类的对象。
(7)外部类标识符
每个类会产生一个.class 文件,文件名即为类名。同样,外部类也会产生这么一个.class 文件,然而它的名称却不是外部类的类名,而是有着严格的限度:外围类的名字,加上 $, 再加上外部类名字。
(8)为何要用外部类?
- 外部类个别只为其外部类应用;
- 外部类提供了某种进入外部类的窗户;
- 也是最吸引人的起因,每个外部类都能独立地继承一个接口,而无论外部类是否曾经继承了某个接口。因而,外部类使多重继承的解决方案变得更加残缺。
加深印象,参考一下:
例子 1:
package cn.tobin.cls;
public class OutClassTest {
static int a;
int b;
public static void test() {System.out.println("outer class static function");
}
public static void main(String[] args) {OutClassTest oc = new OutClassTest();
// new 一个外部类
OutClassTest oc1 = new OutClassTest();
// 通过外部类的对象 new 一个非动态的外部类
OutClassTest.InnerClass no_static_inner = oc1.new InnerClass();
// 调用非动态外部类的办法
System.out.println(no_static_inner.getKey());
// 调用动态外部类的动态变量
System.out.println(OutClassTest.InnerStaticClass.static_value);
// 不依赖于外部类实例, 间接实例化外部动态类
OutClassTest.InnerStaticClass inner = new OutClassTest.InnerStaticClass();
// 调用动态外部类的非静态方法
System.out.println(inner.getValue());
// 调用外部动态类的静态方法
System.out.println(OutClassTest.InnerStaticClass.getMessage());
}
private class InnerClass {
// 只有在动态外部类中才可能申明或定义动态成员
// private static String tt = "0";
private int flag = 0;
public InnerClass() {
// 三. 非动态外部类的非动态成员能够拜访外部类的非动态变量和动态变量
System.out.println("InnerClass create a:" + a);
System.out.println("InnerClass create b:" + b);
System.out.println("InnerClass create flag:" + flag);
//
System.out.println("InnerClass call outer static function");
// 调用外部类的静态方法
test();}
public String getKey() {return "no-static-inner";}
}
private static class InnerStaticClass {
// 动态外部类能够有动态成员,而非动态外部类则不能有动态成员。private static String static_value = "0";
// 动态外部类也能够有非动态成员
private int flag = 0;
public InnerStaticClass() {System.out.println("InnerClass create a:" + a);
// 动态外部类不可能拜访外部类的非动态成员
// System.out.println("InnerClass create b:" + b);
System.out.println("InnerStaticClass flag is" + flag);
System.out.println("InnerStaticClass tt is" + static_value);
}
public int getValue() {
// 动态外部类拜访外部类的静态方法
test();
return 1;
}
public static String getMessage() {return "static-inner";}
}
public OutClassTest() {
// new 一个非动态的外部类
InnerClass ic = new InnerClass();
System.out.println("OuterClass create");
}
}
运行后果:
InnerClass create a:0
InnerClass create b:0
InnerClass create flag:0
InnerClass call outer static function
outer class static function
OuterClass create
InnerClass create a:0
InnerClass create b:0
InnerClass create flag:0
InnerClass call outer static function
outer class static function
OuterClass create
InnerClass create a:0
InnerClass create b:0
InnerClass create flag:0
InnerClass call outer static function
outer class static function
no-static-inner
0
InnerClass create a:0
InnerStaticClass flag is 0
InnerStaticClass tt is 0
outer class static function
1
static-inner
/**
- 总结:
- 1. 动态外部类能够有动态成员 (办法,属性),而非动态外部类则不能有动态成员 (办法,属性)。
- 2. 动态外部类只可能拜访外部类的动态成员, 而非动态外部类则能够拜访外部类的所有成员 (办法,属性)。
- 3. 实例化一个非动态的外部类的办法:
- a. 学生成一个外部类对象实例
- OutClassTest oc1 = new OutClassTest();
- b. 通过外部类的对象实例生成外部类对象
- OutClassTest.InnerClass no_static_inner = oc1.new InnerClass();
- 4. 实例化一个动态外部类的办法:
- a. 不依赖于外部类的实例, 间接实例化外部类对象
- OutClassTest.InnerStaticClass inner = new OutClassTest.InnerStaticClass();
- b. 调用外部动态类的办法或动态变量, 通过类名间接调用
- OutClassTest.InnerStaticClass.static_value
- OutClassTest.InnerStaticClass.getMessage()
*/
例子 2:
package cn.tobin.cls;
public class OutClassTest2 implements AA {
private static String flag ="OutClassTest2";
private int index =1;
@Override
public void a() {System.out.println("OutClassTest2 implements AA.a");
}
private void setValue() {
flag ="setValue";
index =2;
// 非静态方法外部不能定义动态外部类 , 切不能加 private,public 管制修饰符, 不能加 static, 编译报错
class InnerClass implements BB {
// flag ="InnerClass"; // 办法非动态外部类不能间接拜访外围动态成员
// index =3; // 办法非动态外部类不能间接拜访外围非动态成员
// 办法中非动态外部类不能定义动态成员
// private static ss ="InnerClass";
// 办法中非动态外部类能定义非动态成员
private int inn1=1;
@Override
public void b() {System.out.println(inn1);
System.out.println("InnerClass implements BB.b");
}
public InnerClass() {System.out.println("InnerClass:"+inn1);
}
}
InnerClass inn = new InnerClass();
inn.b();}
private static void printValue() {
flag ="setValue";
// index =2;
// 在静态方法外部类, 切不能加 private,public 管制修饰符, 不能加 static, 编译报错
class InnerStaticClass {
// flag ="InnerClass"; // 静态方法外部类不能间接拜访外围动态成员
// index =3; // 静态方法外部类不能间接拜访外围非动态成员
// 静态方法中外部类不能定义动态成员
// private static ss2 ="InnerStaticClass";
// 静态方法中外部类能定义非动态成员
private int inn2=2;
public InnerStaticClass() {System.out.println("InnerStaticClass:"+inn2);
}
}
new InnerStaticClass();}
public static void main(String[] args) {OutClassTest2 out = new OutClassTest2();
out.setValue();
out.printValue();}
}
interface AA {abstract void a();
}
interface BB {abstract void b();
}
运行后果:
InnerClass:1
1
InnerClass implements BB.b
InnerStaticClass:2
总结:因为办法外部类不能在外部类的办法以外的中央应用,因而办法外部类不能应用拜访控制符和 static 修饰符。