This document was uploaded by user and they confirmed that they have the permission to share
it. If you are author or own the copyright of this book, please report to us by using this DMCA
report form. Report DMCA
Overview
Download & View Java Basic Details as PDF for free.
class Cups{ static Cup c1 = new Cup(11); static Cup c2; Cup c3 = new Cup(33); Cup c4; { c3 = new Cup(3); c4 = new Cup(4); } static{ c1 = new Cup(1); c2 = new Cup(2); }
PDF 文件使用 "pdfFactory" 试用版本创建 www.fineprint.cn
Cups(){ System.out.println("Cups()"); } }
public class ExplicitStatic{ public static void main(String[] args){ System.out.println("Inside main()"); Cups.c1.f(99); } static Cups x = new Cups(); static Cups y = new Cups(); }
会自动将这些 classes 初见为隶属于该目录的 default package,可 以相互调用 class 中的 friendly 成员。如以下两个 class 分别在同 一个文件夹的两个文件中,虽然没有引入 package,但隶属于相同的 default package。 class Sundae{ //以下两个方法缺省为 friendly Sundae(){} Void f() {System.out.println(“Sundae.f()”); } public class IceCream{ public static void main(String[] args){ Sundae x = new Sundae(); x.f(); } } 2. public:可以被任何 class 调用 3. private:private 成员只能在成员所属的 class 内被调用,如:
PDF 文件使用 "pdfFactory" 试用版本创建 www.fineprint.cn
class Sundae{ private Sundae(){}//只能在 Sundae class 中被调用 Sundae(int i) {} static Sundae makASundae() { return new Sundae(); } } public class IceCream{ public static void main(String[] args){ // Sundae class 中构造函数 Sundae()是 private, // 所以不能用它进行初始化 //Sundae x = new Sundae(); Sundae y = new Sundae(1);//Sundae(int)是 friendly,可以在此 调用 Sundae z = Sundae.makASundae(); } } 4. protected:具有 friendly 访问权限的同时,又能被 subclass (当然包括子孙类,即子类的子类)所访问。即,既能被同一 package 中的 classes 访问,又能被 protected 成员所在 class 的 subclass 访问。
PDF 文件使用 "pdfFactory" 试用版本创建 www.fineprint.cn
二.Class 的访问权限 1.Class 同样具有 public、protect、friendly、private 四种访问 访问权限: 1)public:在任何地方都可被使用 2)protect、private:除了它自己,没有任何 class 可以使用,所 以 class 不能是 protected 或 private(inner class 除外) 3) friendly:同一个 package 中的 classes 能用 2. 如何调用构造函数被声明为 private 的 class 1) 用 static 函数 2) 用 Singteton 模式 class Soup{ private Soup(){} //(1)静态函数方法 public static Soup makeSout(){ return new Soup(); } //(2)The "Singleton" pattern: private static Soup ps1 = new Soup(); public static Soup access(){ return ps1; }
PDF 文件使用 "pdfFactory" 试用版本创建 www.fineprint.cn
public void f(String msg){ System.out.println("f(" + msg + ")"); } } public class Lunch{ public static void main(String[] args){ //Soup priv1 = new Soup();编译错误 Soup priv2 = Soup.makeSout(); Soup priv3 = Soup.access(); priv2.f("priv2"); priv3.f("priv3"); }
第 6 章 重复运用 classes
一.继承(inheritance) 1.在 derived class 中 overriding 某个函数时, 只能覆写 base class 中的接口,即 base class 中的 public 或 protected 或 friendly 函 数。如果试图 overriding 一个 private 函数,虽然编译通过,但实 际上你只是在 derived class 中添加了一个函数。如 class Cleanser{ private void prt(){//(b)
PDF 文件使用 "pdfFactory" 试用版本创建 www.fineprint.cn
System.out.println("Cleanser.prt()"); } } public class ExplicitStatic extends Cleanser{ public void prt(){ System.out.println("ExplicitStatic.prt()"); } public static void main(String[] args){ Cleanser x = new ExplicitStatic(); x.prt();//(a) } } 因为 Cleanser 中的 prt()是 private,所以不能在其 derived
class
中被覆写。ExplicitStatic 中的 prt()只是 ExplicitStatic 中的一 个函数,所以当试图在(a)处通过多态来调用 prt()时,会发生错 误。如果把(b)处的 private 去掉,则结果为 ExplicitStatic.prt() 2. Super 的使用 1)通过关键字 super 可以调用当前 class 的 superclass(父类) 。 例 6.1.1.1 class Base{ Base(){System.out.println("Base()");}
PDF 文件使用 "pdfFactory" 试用版本创建 www.fineprint.cn
public void scrub() { System.out.println(" Base.scrub()"); } } class Cleanser extends Base{ private String s = new String("Cleanser"); public void append(String a) { s+=a; } public void dilute() { append(" dilute()"); } public void apply() { append(" apply()"); } public void scrub() { append(" scrub()"); } public void print() { System.out.println(s); } Cleanser(){ System.out.println("Cleanser(): " + s); } public static void testStatic(){ System.out.println("testStatic()"); } public static void main(String[] args){ Cleanser x = new Cleanser(); x.dilute(); x.apply(); x.scrub(); x.print(); } } public class ExplicitStatic extends Cleanser{ ExplicitStatic(){
PDF 文件使用 "pdfFactory" 试用版本创建 www.fineprint.cn
System.out.println("ExplicitStatic()"); } public void scrub(){ append(" Detergen.scrub()"); super.testStatic(); super.scrub();//调用的是 Cleanser.scrub() } public void foam() { append(" foam()"); } public static void main(String[] args){ ExplicitStatic x = new ExplicitStatic(); x.dilute(); x.apply(); x.scrub(); x.foam(); x.print(); System.out.println("Test base class:"); Cleanser.main(args); testStatic(); } }
baseS = ExplicitStatic , super.baseS = Cleanser 在上面例子中,在三个 class 中都存在 String bases 实例。在 ExplicitStatic 中如果直接调用 baseS,则实际调用的是当前类 ExplicitStatic 中的 baseS(即 (c) 处的成员) ; 如果通过 super.bases 来调用 baseS,则调用的是离当前类 ExplicitStatic 最近的 baseS 成员,即 Cleanser class 中的 baseS 实例(即(b)处) ,产生的结 果如结果 1 所示。如果把(b)处语句注释掉,则将调用 Base class 中的 baseS,结果如结果 2 所示。 结果 2: Base() Cleanser(ExplicitStatic): s = Cleanser ExplicitStatic():s2 = Cleanser, baseS = Base,super.baseS = Base baseS = ExplicitStatic , super.baseS = Base 3. Base class 的初始化 2.1 当你产生 derived class 对象时,其中会包含 base class 子对 象(subobject)。这个子对象就和你另外产生的 base class 对象一 模一样。 2.2 通过 super()可调用 base class 的构造函数,但必须放在构造 函数的第一行,并且只能在构造函数中运用。 2.3 初始化顺序为: 1) 加载代码(.class 文件)
PDF 文件使用 "pdfFactory" 试用版本创建 www.fineprint.cn
2) 初始化 class 的静态成员,初始化顺序了“从里到外” ,即从 base class 开始。 3) 在 derived class 的构造函数中调用 base class 的构造函数。 如果在 derived class 的构造函数中没有通过 super()显式调用调用 base class 的构造函数,编译器会调用 bass class 的 default 构造 函数并自动生成相应的调用语句,从而产生一个 base class 实例。 如果在 derived class 的构造函数中通过 super()显示调用了父类的 构造函数,则调用所指定的构造函数。调用构造函数的调用顺序是“从 里到外”。 4) 调用 derived class 的构造函数。 **:当 base class 没有 default 构造函数时, 必须在 derived class 的构造函数中通过 super 显示调用 base class 的构造函数。 例:下面代码的初始化过程为: 1)装载 ExplicitStatic 的代码 (装载 ExplicitStatic.class 文件)。 2) 发现 ExplicitStatic 有关键字 extends,装载 ExplicitStatic 的 base
class 的代码(装载 Cleanser.class 文件)。
3) 发现 Cleanser 有关键字 extends,装载 Cleanser 的 base
class
的代码(装载 Base.class 文件) 。 4) 初始化 Base class 中的静态成员。 5) 初始化 Cleanser class 中的静态成员。 6) 初始化 ExplicitStatic class 中的静态成员。 如果把(c)处的代码注释掉,那么初始化工作到此就结束了。
PDF 文件使用 "pdfFactory" 试用版本创建 www.fineprint.cn
7) 为 ExplicitStatic 对象分配存储空间,并把存储空间初始化为 0。 8)在 ExplicitStatic class 的构造中调用 super("ExplicitStatic") (在 ExplicitStatic class 的构造函数中显式调用父类的构造函 数) ,试图产生一个 Cleanser class 实例。 9) 为 Cleanser 对象分配存储空间,并把存储空间初始化为 0。 10) 由于 Cleanser class 又是继承自 Base class,会在 Cleanser class 的构造函数中通过 super()(由于没有显式调用父类的构造函 数,所以自动调用父类的 default 构造函数)调用父类的构造函数, 试图产生一个 Cleanser class 实例。 11) 产生一个 Base class 实例。先初始化成员变量,再调用构造函 数。 12) 回到 Cleanser class,产生一个实例。首先初始化 Cleanser class 中的成员数据,再执行构造函数 Cleanser(String a)中的其余部分。 13) 回到 ExplicitStatic class, 产生一 个实 例。首 先初 始化 ExplicitStatic class 中 的 成 员 数 据 , 再 执 行 构 造 函 数 ExplicitStatic
()
中
的
其
余
(System.out.println(“ExplicitStatic()”))。 class Base{ static int s1 = prt("s1 initialized.", 11); int i1 = prt("i1 initialized.", 12);
调 用 base class 的 成 员 。 在 调 用 Cleanser class 的 构 造 函 数 Cleanser(String a)时,在 Cleanser(String a)中没有用 super 显式调用 Base class 的构造函数,所以系统会自 动生成调用 Base class 的 default 构造函数的语句,如(b) 。 4. 组合与继承之间的快择 . 1)继承表示的是一种“is-a(是一个) ”的关系,如货车是汽车中 的一种;组合表示的是一种“has-a(有一个) ”的关系,如汽车有四 个轮子。 2)是否需要将新的 class 向上转型为 base class。 5. 在继承中的访问权限 protect 变量能被子孙类所调用。如 Base class 中的 baseS 能被 Cleanser class 和 ExplicitStatic class 调用。 class Base{ protected String baseS = "Base"; //private String baseS = "Base"; Base(){System.out.println("Base()");} } class Cleanser extends Base{ protected String baseS = "Cleanser"; public String s = new String("Cleanser"); Cleanser(){ System.out.println("Cleanser(): " + s);
PDF 文件使用 "pdfFactory" 试用版本创建 www.fineprint.cn
} Cleanser(String a){ System.out.println("Cleanser(" + a + "): s = " + s ); } } public class ExplicitStatic extends Cleanser{ String s2 = s; String baseS = super.baseS; ExplicitStatic(){ super("ExplicitStatic"); System.out.println("ExplicitStatic():s2 = " + s2 + ", baseS = " + baseS + "super.baseS = " + super.baseS); baseS = "ExplicitStatic"; System.out.println("baseS = " + baseS + " , super.baseS = " + super.baseS); } public static void main(String[] args){ ExplicitStatic x = new ExplicitStatic(); } }
PDF 文件使用 "pdfFactory" 试用版本创建 www.fineprint.cn
结果: Base() Cleanser(ExplicitStatic): s = Cleanser ExplicitStatic():s2 = Cleanser, baseS = Cleanser, super.baseS = Cleanser baseS = ExplicitStatic , super.baseS = Cleanser 二.关键字 final 1.Final data 1.1
final data
1)当基本型别被定义为 final,表示它的数据值不能被改变。如 final int i = 9; i++;//编译错误,不能改变 I 的值 2) 当 object
reference 被定义为 final 时,不能改变的只是
reference 而不是对象本身。如 class Value{ int i = 1; } public class ExplicitStatic extends Cleanser{ public static void main(String[] args){ final Value v = new Value();//v.i = 1 v.i++;//v.i = 2 //v = new Value();
PDF 文件使用 "pdfFactory" 试用版本创建 www.fineprint.cn
} } 由于 v 为 final,所以不能通过 new Value()使 v 重新指向一个对象; 但是 v 所指向的对象的值是可以改变的(v.i++)。 1.2
blank finals
我们可以将数据成员声明为 final 但不给予初值,这就是 blank finals。但 blank
finals 必须且只能在构造函数中进行初始化。
public class ExplicitStatic { final int ib; final int i = 1; ExplicitStatic() { ib = 2;//(a) //i = 3;
(b)
System.out.println("i = " + i + ", ib = " + ib); } public static void main(String[] args){ ExplicitStatic ex = new ExplicitStatic(); } }
ib 为 blank
finals,所以可以在构造函数中进行初始化。如果把(a)
PDF 文件使用 "pdfFactory" 试用版本创建 www.fineprint.cn
处的代码注释掉,则 ib 没有初值,编译出错。而 i 在定义处已进行 了初始化,则不能改变 i 的值,(b)处的代码编译错误。 **:非 blank 2.Final
finals 成员即使在构造函数中也不能更改其值
methods
1)被声明为 final 的函数不能被覆写 2)class 中所有 private 函数自然而然会是 final。 3. Final
classes
1)当一个 class 被声明为 final 时,表示它不能被继承,但 class 的数据成员不是 final,可以被改变。如 class SmallBrain{} final class Dinosaur{ int i = 7; int j = i; SmallBrain x = new SmallBrain(); void f(){}; } //不能继承 final 函数 //class Further extends Dinosaur{} public class ExplicitStatic{ public static void main(String[] args){ Dinosaur n = new Dinosaur(); n.f();
class 中的函数。如 class First{ public void prt(){ System.out.println("First"); } } class Second extends First{ //(a)
PDF 文件使用 "pdfFactory" 试用版本创建 www.fineprint.cn
public void prt(){ System.out.println("Second"); } } public class ExplicitStatic{ public static void main(String[] args){ First n = new Second(); n.prt();; } } 结果为 Second。如果当 Second
class 中的 prt()函数注释掉,将输
出 First。 2. 向上转型后只能调用 base
class 中被 derived
函数。 /* abstract class First{ int i = 122; public void prt(){ System.out.println("First.i = " + i); } public abstract void prt(First f); }
PDF 文件使用 "pdfFactory" 试用版本创建 www.fineprint.cn
class 覆写的
class Second extends First{ public void prt(){ System.out.println("Second.i = " + i); }
public void prt(First i) {
}
public void prt(int i) {
} } public class ExplicitStatic{ public static void main(String[] args){ First n = new Second(); n.prt(2);; } }
PDF 文件使用 "pdfFactory" 试用版本创建 www.fineprint.cn
*/ class First{ public void prt(){ System.out.println("First"); } } class Second extends First{ //(a) public void prt(){ System.out.println("Second"); } public void prt(int i){//(a) System.out.println("Second.i = " + i); } } public class ExplicitStatic{ public static void main(String[] args){ First n = new Second(); n.prt(3); } }
PDF 文件使用 "pdfFactory" 试用版本创建 www.fineprint.cn
(a) 处的函数只是 Second
class 中的函数, 所以不能通过 n.prt(3)
进行调用。 二.Abstract
class 和 Abstract
methods
1. 如果一个 class 中存在 abstract 明为 abstract
class。
2. abstract
class 不能被实例化。
3.如果 base
class 是一个 abstract
必须实现 base
class,则 class 也必须被声
class, 那么 derived
class 中所有的 abstract
class 也必须被声明为 abstract
class
methods;否则,derived
class。
三.其它要点 1. 纯粹继承与扩充 纯粹继承:只有 base
class 所建议的函数,才被 derived
加以覆写。 扩充:除了覆写 base
class 的函数,还实现了自己的函数
abstract class First{ public abstract void f(); public abstract void g(); } //纯粹继承 class Second extends First{ public void f(){} public void g(){}
PDF 文件使用 "pdfFactory" 试用版本创建 www.fineprint.cn
class
} //扩充 class Third extends First{ public void f(){} public void g(){} public void u(){}//base
class 不存在的函数
} 2. 向下转型 1) 向下转型时只能调用 base 2) 只有本来就为 derived
class 中被覆写过的函数
class 对象时才能正确向下转弄。
class First{ public void f(){} public void g(){} } class Second extends First{ public void f(){} public void g(){} public void u(){} public void v(){} } public class ExplicitStatic{ public static void main(String[] args){
PDF 文件使用 "pdfFactory" 试用版本创建 www.fineprint.cn
First[] x = {new First(), new Second()}; x[0].f(); x[1].g(); //!x[1].u();class
First 中不存在函数 u()
//((Second)x[0]).f();(a) ((Second)x[1]).u(); } }
第 8 章 接口与内隐类
一. 接口 1. 如果实现接口的 class 未实现接口中的所有函数,则这个 class 必须被声明为 abstract class 中为 abstract
class,而接口中未被实现的函数在这个
class。
interface Interface{ public void f(); public void g(); } abstract class First implements Interface{ public void f(){} }
PDF 文件使用 "pdfFactory" 试用版本创建 www.fineprint.cn
class Second extends First{ public void g(){} } public class ExplicitStatic{ public static void main(String[] args){ Interface f = new Second(); f.f(); f.g(); } } 2. 接口中的所有函数自动具有 public 访问权限,所以实现某个接 口时,必须将承袭自该接口的所有函数都定义为 public interface MyInterface { public void f(); void g(); } class First implements MyInterface { public void f(){} //!void g(){}出错,应定义为 public } 3. 接口中的数据成员自动成为 static 和 final
PDF 文件使用 "pdfFactory" 试用版本创建 www.fineprint.cn
interface MyInterface{ int i = 5; void f(); void g(); } class First implements MyInterface { public void f(){} public void g(){} } public class ExplicitStatic{ public static void main(String[] args){ MyInterface x = new First(); // MyInterface 的数据成员 I 为 static,可直接调用 System.out.println("MyInterface.i = " + MyInterface.i + " , x.i = " + x.i); // MyInterface 的数据成员 I 为 final,不能修改 //x.i++; // MyInterface.i++; } } 4. 多重继承 1) devriced
interface CanFight{ void fight(); } interface CanSwim{ void swim(); } class ActionCharacter{ public void fight(){} } class Hero extends ActionCharacter implements CanFight, CanSwim{ public void swim(){}; } public class ExplicitStatic{ static void f(CanFight x) { x.fight(); } static void s(CanSwim x) { x.swim(); } static void a(ActionCharacter x) { x.fight(); }
PDF 文件使用 "pdfFactory" 试用版本创建 www.fineprint.cn
static void h(Hero x){ x.fight(); x.swim(); } public static void main(String[] args){ Hero h = new Hero(); f(h); s(h); a(h); h(h); } } 因为在 ActionCharacter
class 中有与接口 CanFight 完全相同的函
数 fight(),所以在 Hero
class 可以不实现 fight()方法。当要调
用 x.fight()时,会调用 ActionCharacter
class 中的 fight()函数。
3) 接口的合并时的名称冲突问题 interface I1 { void f(); } interface I2 { int f(int i); } interface I3 { int f(); } class C { public int f() { return 1; } }
class C2 implements I1, I2{ public void f() {} public int f(int i) { return 1; } } class C3 extends C implements I2{
PDF 文件使用 "pdfFactory" 试用版本创建 www.fineprint.cn
public int f(int i) { return 1; } } class C4 extends C implements I3{ public int f() { return 1; } } //class C5 extends C implements I1{}
(a)
//class C6 extends C implements I1{ public void f(){} } interface I4 extends I1, I3{}
(b)
//(c)
class C7 implements I4{ public void f() {} public int f() { return 1; } }
(a)处代码会产生 以下错误: method f() in class C cannot implement method f() in interface I1 with different return type, was void。(b)处代码也是错误的: method f() in class C6 cannot override method f() in class C with different return type, was int。由(b)处代码也可看出,虽然你试图实现接口 I1 中的函数, 但由于 extends C 在前,所以编译器会把 C6 中的函数看成是覆写 class
public void f2() {} public void fe1() {} public void f1() {} } 接口 Ie2 继承了两个接口。 5. 嵌套的 interfaces 嵌套的 interfaces 可以在定义该内部接口的外部类(接口)之外被 使用(但内隐类不行)。 1) 当接口嵌套于 class 中 a) 不论接口为 public、friendly 或 private,都可被实现为 public、 friendly、private 三种嵌套类。 b) 被声明为 private 的接口不能在 class 外被使用。 class A{ private interface B{ void f(); } public class BImp implements B{ public void f() {} } private class BImp2 implements B{ public void f() {} }
PDF 文件使用 "pdfFactory" 试用版本创建 www.fineprint.cn
public B getB() { return new BImp(); } private B dRef; public void recivedD(B d){ dRef = d; dRef.f();; } } public class ExplicitStatic{ public static void main(String[] args){ A a = new A(); //(a) //A.B ab = a.getB();
(b)
//A.BImp = a.getB();
(c)
a.recivedD(a.getB()); } } 虽然 A
class 含有接口,但它仍可被实例化,如(a) 。
由于接口 B 为 private,所以在(b)处调用接口 B 时会出错。但当 把接口 B 声明为 public 时, (b)将通过编译。但(c)处依然会出错, 因为内隐类的作用域为定义该内隐类的外部类内(见内隐类) 。 2) 当接口嵌套于接口中 1) 嵌套于接口中的接口自动为 public,且只能为 public。 2) 当实现某个接口时,无需实现其中嵌套的接口。
PDF 文件使用 "pdfFactory" 试用版本创建 www.fineprint.cn
3) Private 接口无法在其所定义的 class 之外被实现。 二. Inner classes(内隐类) 1. 内隐类的基本用法 1) 如果要在外围 class 的 non-static 函数之外产生一个 inner class 对象,得以 OuterClassName.InnerClassName 的形式指定该对 象的型别。而在 non-static 函数内则不用。 public class ExplicitStatic{ class Contents{ private int i = 11; public int value() { return i; } } class Destination{ private String label; Destination(String whereTo){ label = whereTo; } String readLabel() { return label; } } public Destination to(String s){ //在 outer class 的 non-static 函数中可直接产生 inner class 对 象 return new Destination(s); //(1)
PDF 文件使用 "pdfFactory" 试用版本创建 www.fineprint.cn
} public Contents cont(){ return new Contents(); //(1) } public void ship(String dest){ //在 outer class 的 non-static 函数中可直接通过 InnerClassName //来指定对象型别 Contents c = cont(); Destination d = to(dest); System.out.println(d.readLabel()); } public static void main(String[] args){ ExplicitStatic p = new ExplicitStatic(); p.ship("Tanzania"); ExplicitStatic q = new ExplicitStatic(); //在 outer class 的非 non-static 函数内产生 inner class 对象 ExplicitStatic.Contents c = q.cont(); ExplicitStatic.Destination d = q.to("Borneo"); //不能在 static 函数直接生成 inner class 对象 // new Contents(); } }
PDF 文件使用 "pdfFactory" 试用版本创建 www.fineprint.cn
2) 对于 non-static
inner
class,在外围 class 的 non-static
函数可以通过 new 产生一个 inner class 对象,如上面的(1)处。 但要在非 non-static 函数产生一个 inner class 对象,则一定要关 联到其 enclosing
class 的某个对象。
3) inner class 的向上转型 当把一个 inner class 对象向上转型成为 interface 时,我们得到的 只是一个 reference。 interface Destination{ String readLabel(); } interface Contents{ int value(); } class Parcel3{ private class PContents implements Contents{ private int i = 11; public int value() { return i; } } protected class PDestination implements Destination{ private String label; PDestination(String whereTo){
PDF 文件使用 "pdfFactory" 试用版本创建 www.fineprint.cn
label = whereTo; } public String readLabel() { return label; } } public Destination to(String s){ return new PDestination(s); } public Contents cont(){ return new PContents(); } } public class ExplicitStatic{ public static void main(String[] args){ Parcel3 p = new Parcel3(); //把 inner class 对象向上转型 Contents c = p.cont(); Destination d = p.to("Borneo"); } } 虽然我们不能在 ExplicitStatic class 无法调用 Pcontents class, 但我们把一个 Pcontents
class 对象
PDF 文件使用 "pdfFactory" 试用版本创建 www.fineprint.cn
向上转型为 Contents,就可对之进行调用。 4) inner inner
class 的作用域为定义该 inner
class 的 scope 内。但
class 可在它的作用域之外被继承(见 4) 。
interface Contents{ int value(); } class Parcel3{ //PContents1
class 的作用域为 Parcel3
class 内
private class PContents1 implements Contents{ private int i = 11; public int value() { return i; } } public Contents cont1(){ return new PContents1(); } public Contents cont2(){ //PContents2
class 的作用域为函数 cont2 内
class PContents2 implements Contents{ private int i = 11; public int value() { return i; } } return new PContents2();
PDF 文件使用 "pdfFactory" 试用版本创建 www.fineprint.cn
} //不能在函数 cont2 外使用 PContents2
class
/* public Contents cont22(){ return new PContents2(); } */ public Contents cont3(boolean b){ if(b){ //PContents3
class 的作用域为当前 if 内
class PContents3 implements Contents{ private int i = 11; public int value() { return i; } } return new PContents3(); } //不能在 if 外使用 PContents3
class
//return new PContents3(); return null; } } public class ExplicitStatic{
PDF 文件使用 "pdfFactory" 试用版本创建 www.fineprint.cn
public static void main(String[] args){ Parcel3 p = new Parcel3(); Contents c1 = p.cont1(); Contents c2 = p.cont2(); Contents c3 = p.cont3(true); } }
2. 内隐类与外围 enclosing class 的连接关系 2.1
non-static
1) inner
inner
class
class 可以访问 enclosing
private 成员),就像 inner
class 自己拥有这些成员一样。即 inner
class 天生具有对 enclosing 2) Inner
class 的所有成员(包括
class 的所有成员的访问权力。
class 对象被产生时,一定要关联到其 enclosing
的某个对象(这个 enclosing 制造者)。建构 inner
class 对象就是 Inner
class
class 对象的
class 对象的同时,得有其 enclosing
class
对象的 reference 才行。 原因:因为 inner
class 可以访问 enclosing
那么当产生一个 inner
class 时,编译器会自动为 inner
象 添 加 一 个 指 向 enclosing
class 对
class 对 象 的 reference ( 这 个
reference 是隐藏的)。所以 Inner 其 enclosing
class 的所有成员,
class 被产生时,一定要关联到
class 的某个对象。
PDF 文件使用 "pdfFactory" 试用版本创建 www.fineprint.cn
3) 同一个 enclosing
class 对象产生出来的 inner
问的是同一个 enclosing
class 对象访
class 对象中的成员。
interface Destination{ String readLabel(); } interface Contents{ int value(); } class Parcel3{ int i1 = 10; private String s1 = "Parcel3_"; Parcel3(String s){ s1 += s; } private class PContents implements Contents{ //可调用 enclosing
class 的成员
(1)
private int i2 = i1; private String s2 = s1; PContents(int num){ System.out.println("" + num + ": i2 = " + i2 + ",s2 = " + s2); } public int value() { return 1; }
PDF 文件使用 "pdfFactory" 试用版本创建 www.fineprint.cn
} public Contents cont(int i){ return new PContents(i); } } public class ExplicitStatic{ public static void main(String[] args){ Parcel3 p1 = new Parcel3("1"); Contents c1 = p1.cont(1); Contents c2 = p1.cont(2); Parcel3 p2 = new Parcel3("2"); c2 = p2.cont(3); c2 = p1.cont(4); } }
interface Contents{ int value(); } class Parcel1{ protected static class PContents implements Contents{ public int value() { return 1; } } public Contents cont(){ //在 non-static 函数中直接通过 new 来产生 PContents class 对象 return new PContents(); } public static Contents cont1(){ //在 static 函数中直接通过 new 来产生 PContents class 对象 return new PContents(); //(1) } public static void test(String[] args){ Parcel1 p1 = new Parcel1(); //在 static 函数中通过外部类 Parcel1 对象来产生
PDF 文件使用 "pdfFactory" 试用版本创建 www.fineprint.cn
Contents c1 = p1.cont(); //调用函数 c1 = p1.new PContents(); //通过 new //在 static 函数中直接通过 new 来产生 PContents class 对象 c1 = new PContents(); //(1) } } public class ExplicitStatic{ public static void main(String[] args){ //通过外部类 Parcel1 对象来产生 Parcel1 p1 = new Parcel1(); Contents c1 = p1.cont(); //调用函数 c1 = p1.new PContents(); //通过 new //直接产生 c1 = Parcel1.cont1(); //(2) } } 上面的(1)和 9(2)中的代码只有在 Pcontents
class 为 static
时才能通过。(1)不能通过的原因见 2.1。 4. inner 1) inner
class 的继承 class 可被继承。inner
class 的 drived
drfault 构造函数必须传入一个 reference 指
PDF 文件使用 "pdfFactory" 试用版本创建 www.fineprint.cn
class 的
向 outer
object,并在构造函数中调用 outer
class WithInner{ class Inner{} } class InheritInner extends WithInner.Inner { //InheritInner(){} 编译错误 InheritInner(WithInner wi) { wi.super(); } } public class ExplicitStatic{ public static void main(String[] args){ WithInner wi = new WithInner(); InheritInner ii = new InheritInner(wi); } } 2) 覆写 inner
class 不具备多态特性。
class Egg{ class Yolk{ public Yolk(){ System.out.println("Egg.Yolk()"); }
PDF 文件使用 "pdfFactory" 试用版本创建 www.fineprint.cn
class 的构造函数。
} private Yolk y; public Egg(){ System.out.println("New Egg()"); y = new Yolk(); //(1) } } class BigEgg extends Egg{ //(2)尝试覆写 inner
class
class Yolk{ public Yolk(){ System.out.println("BigEgg.Yolk()"); } } } public class ExplicitStatic{ public static void main(String[] args){ new BigEgg(); //(3) } } 结果为: New Egg()
class TestException{ //(1)异常规格中声明将抛出 RuntimeException 异常 public void testRuntime() throws RuntimeException {} //(2)异常规格中声明将抛出 NullPointerException 异常 public void testNullPointer() throws NullPointerException {} //(3)异常规格中声明将抛出 non-RuntimeException 异常 public void testNonRuntime() throws SQLException {} } public class Test{ public static void main(String[] args){ TestException te = new TestException(); te.testRuntime();
throw new IOException("IOException"); } } public class ExplicitStatic{ public static void main(String[] args){ Test1 te = new Test1(); try{ te.f(); } catch(Exception ex){
PDF 文件使用 "pdfFactory" 试用版本创建 www.fineprint.cn
//(1)
System.out.println("catch Exception in main"); } } } 在(1)处抛出了一个没有在异常规格中被声明的 non-RuntimeException 异常,在编译时会出错。 3. 取得异常中的信息的几个函数 1) String getMessage()、getLocalizedMessage 、toString 取得异常对象中的信息 import java.lang.RuntimeException; import java.lang.NullPointerException; Import java.sql.SQLException; import java.io.IOException; class TestException{ public void tSql() throws SQLException { System.out.println("Originating the exception in tSql()"); throw new SQLException("throw in tSql"); } } public class Test{ public static void main(String[] args){ TestException te = new TestException();
PDF 文件使用 "pdfFactory" 试用版本创建 www.fineprint.cn
try{ te.tSql(); } catch(SQLException ex){ System.out.println("catch SQLException in main"); System.out.println("ex.getMessage():" + ex.getMessage()); System.out.println("ex.getLocalizedMessage():" + ex.getLocalizedMessage()); System.out.println("ex.toString():" + ex.toString()); } catch(Exception ex){ System.out.println("catch Exception in main"); } } } 运行结果: Originating the exception in tSql() catch SQLException in main ex.getMessage():throw in tSql ex.getLocalizedMessage():throw in tSql ex.toString():java.sql.SQLException: throw in tSql 2) void printStackTrace()、Throwable fillStackTrace()
import java.sql.SQLException; class TestException{ public static void tSql() throws SQLException { System.out.println("Originating the exception in tSql()"); throw new SQLException("throw in tSql"); } public void f() throws SQLException{ try{ tSql(); } catch(SQLException ex){ System.out.println("In f(), e.printStackTrace()"); ex.printStackTrace(); throw ex;
//(1)
//throw (SQLException)ex.fillInStackTrace(); } } } public class Test{
PDF 文件使用 "pdfFactory" 试用版本创建 www.fineprint.cn
(2)
public static void main(String[] args){ TestException te = new TestException(); try{ te.f(); } catch(SQLException ex){ System.out.println("catch in main, e.printStackTrace()"); ex.printStackTrace(); } catch(Exception ex){ System.out.println("catch Exception in main"); } } }
结果为: Originating the exception in tSql() In f(), e.printStackTrace() catch in main, e.printStackTrace() java.sql.SQLException: throw in tSql void TestException.tSql() Test.java:5