Thinking in Java 3 Edition public static final Month number(int ord)t turn month lord public static void main(String[] args)t System. out. println(m) Month number(12) System. out. println(m)i System. out. println(m== Month. DEC)i System. out. println(m equals(Month. DEC))i System. out. println(Month. month [3])i monitor. expect(new string[ t January dEcember ntrue ntrue }) }///:~ Month是一个带 private构造函数的fina类,因此谁也不能继承 它,或者创建它的实例。所有实例都是由类自己创建的,并且都是 final static的:JAN,FEB,MAR,等等。这些对象也被用于 month数 组。这是一个供你遍历的 Month对象的数组。你可以传一个数字给 number()方法,以选取相应月份的 Month对象。从main()可以 看出,这么做是类型安全的;m是一个 Month的对象,所以它只能被 赋予 Month。再前一个例子中, Month,java所返回的是一个int的 值,因此可能会给这个表示月份的int变量赋上其它的值,因此不是非常 安全。 正如在main()的最后几行所看到的,这里你还能互换地使用==和 equals()。之所以能这么做,是因为 Month的每个值只能有一个实 例。到第11章,你还会学到一种新的定义类的方法,用这种类创建的对 象能够进行相互比较 此外 java util. Calendar里面有一个 month的成员。 Apache的 Jakarta commons项目下还包含了一些创建枚举类型的工 具,它的功能与上述例程相似,但是用起来没那么麻烦。参见 htt:/ akarta. apache. org/ commons下面的“lang”,这个包是 org. apache commons. langenum。这个项目里面还有很多别 的,可能会非常有用的类库 初始化接口中的数据成员 第11页共47页 www.wgqqh.com/shhgs/tij.html email:shhgs@sohu.com
Thinking in Java 3 rd Edition ✄ 11 ☎ ✆ 47 ☎ www.wgqqh.com/shhgs/tij.html email:shhgs@sohu.com public static final Month number(int ord) { return month[ord - 1]; } public static void main(String[] args) { Month m = Month.JAN; System.out.println(m); m = Month.number(12); System.out.println(m); System.out.println(m == Month.DEC); System.out.println(m.equals(Month.DEC)); System.out.println(Month.month[3]); monitor.expect(new String[] { "January", "December", "true", "true", "April" }); } } ///:~ M on th 3׬ private Úc( finalæò[X;ö8 A312A(ñDmñÆ7ýþ12(³Æ final static (LJAN FEBM AR-- Ì¥![v) mon th c 3ס( M on th ¥!(c¡ÝEA3×c¾¬ n umber( )µE¥ >vú( M on th ¥! main ( ) ÝE <! ZThüc( m 3× M on th (¥!DEAó;v M on th Á3×*M on th . java Def(3× in t ( gæòÝ;º¬ ×?ú( in t Û J§A(gæòX¯· üc jÄF main ( )(bi}D<g( Ë¡;|rç= = equal s( )uDE; ZTæ M on th (¶×gó;m3×ñ g 1 1 û¡º0g3Â(O4(µ 12(¥ !;Ô]}>8 ò½ java. u til . Cal en dar ˶m3× m onth (& Apach e ( Jakarta Com m ons x«kl,3Ì12h(y ºA(F;Jâ>E9QYZ http://jakarta.apache.org/commons ¶(Íl ang Ï ×k org. apach e. common s. lan g. en um ×x«Ë¶mV¨ (Ý;º¯·m(
Thinking in Java 3 Edition 接口所定义的数据都自动是 static和 final的。它们不能是“空白的 fina数据成员”,但是可以用非常量的表达式来对它们进行初始化。例 如: // c08: Randvals java // Initializing interface fields with / non-constant initializers import java. util.* public interface Randvals t Random rand new Random(i int randomInt rand. nextInt (10) long randomLong rand. nextLong()*10; float random loat rand. nextLong()*10; 由于数据成员都是 static的,因此装载类的时候,也就是第一次访问这 些数据成员的时候进行初始化。下面就是一个简单的测试: public class TestRandvals t() System. out. println(Randvals randomInt)i System. out. println(Randvals. randomLong)i System. out. println(Randvals. randomFloat) System. out. println(Randvals. randomDouble)i monitor. expect(new String[] t 号各-2\1d+m 号各-?\\d+ 号各-2d\\.\d+E?-?\\d+m 号各-?\\d\\,\d+E?-?\\d+m }) }///: 当然,这些数据都不算是接口的组成部分,相反它们保存在这个接口的静 态存储区内。 接口的嵌套 接口既可以嵌套在类里,也可以嵌套在接口里面。34这一点揭示了许多 非常有趣的特点 //: c08: nesting: NestingInterfaces java package co8.nesting 第12页共47页 www.wgqqh.com/shhgs/tij.html email:shhgs@sohu.com
Thinking in Java 3 rd Edition www.wgqqh.com/shhgs/tij.html email:shhgs@sohu.com ✄ 12 ☎ ✆ 47 ☎ DO4(cmÆý static final(AX;Í( finalcm&ÏÝE¯·Û(?û´Q¥A]}f` ÄL //: c08:RandVals.java // Initializing interface fields with // non-constant initializers. import java.util.*; public interface RandVals { Random rand = new Random(); int randomInt = rand.nextInt(10); long randomLong = rand.nextLong() * 10; float randomFloat = rand.nextLong() * 10; double randomDouble = rand.nextDouble() * 10; } ///:~ 7)cm&Æ static (æòä(M[3¨ Ìcm&(M]}f`¶3×GH(L //: c08:TestRandVals.java import com.bruceeckel.simpletest.*; public class TestRandVals { private static Test monitor = new Test(); public static void main(String[] args) { System.out.println(RandVals.randomInt); System.out.println(RandVals.randomLong); System.out.println(RandVals.randomFloat); System.out.println(RandVals.randomDouble); monitor.expect(new String[] { "%% -?\\d+", "%% -?\\d+", "%% -?\\d\\.\\d+E?-?\\d+", "%% -?\\d\\.\\d+E?-?\\d+" }); } } ///:~ ÌcmÆX(>AF ×( ²ÝEFË[ÝEF˶ ✝ ✞✠✡✟ 3C,V ¯·m ()CL //: c08:nesting:NestingInterfaces.java package c08.nesting;
Thinking in Java 3 Edition class A i interface B I public class BImp implements B oublic void f( private class BImp2 implements B public void f()i1 public interface C void f(i class CImp implements C public void f()) private class CImp2 implements c i public void f()i) private interface D t void f(i private class DImp public void f()iI public class DImp2 implements d i public void f()( public d get(i return new DImp2()i 1 d dRef public void received(dd)i dRef dRef. f(; interface E I // Redundant "public" oid f( void g() / Cannot be private within an interface: vate interface I public class BImp implements A B i ublic void f(i // Cannot implement a private interface excel / within that interface's defining class lass DImp impl 7/1 public void f()() 第13页共47页 www.wgqqh.com/shhgs/tij.html
Thinking in Java 3 rd Edition ✄ 13 ☎ ✆ 47 ☎ www.wgqqh.com/shhgs/tij.html email:shhgs@sohu.com class A { interface B { void f(); } public class BImp implements B { public void f() {} } private class BImp2 implements B { public void f() {} } public interface C { void f(); } class CImp implements C { public void f() {} } private class CImp2 implements C { public void f() {} } private interface D { void f(); } private class DImp implements D { public void f() {} } public class DImp2 implements D { public void f() {} } public D getD() { return new DImp2(); } private D dRef; public void receiveD(D d) { dRef = d; dRef.f(); } } interface E { interface G { void f(); } // Redundant "public": public interface H { void f(); } void g(); // Cannot be private within an interface: //! private interface I {} } public class NestingInterfaces { public class BImp implements A.B { public void f() {} } class CImp implements A.C { public void f() {} } // Cannot implement a private interface except // within that interface's defining class: //! class DImp implements A.D { //! public void f() {}
Thinking in Java 3 Edition lass EImp implements E public void g()i) class GIMp implements E. G ublic void f(] class EImp2 implements E t public void g(t class eg implements E. G t ublic void fo public static void main(String[ args) i // AD ad get() // Doesn't return anything but AD / Cannot access a member of the interface //on1 ther A can do anything with get () a2receiveD(a get()) }///:~ 在类里嵌套接口的语法还是比较明显的。跟没被嵌套在类里的接口一样, 它也可以是 public或 package访问权限的。而且你还可以看到, public和 package权限的接口都被实现成 public, package权限 甚至 private的“嵌套类( nested classes) 正如AD所演示的,作为一种新的技巧,接口也可以是 private的(这 种语法既可用于“嵌套接口「 nested interfaces」”,也可用于“嵌套 类『 nested classes」”)。那么 private的嵌套接口又有什么好处 呢?可能你会认为,它只能被实现成 private的内部类,就像Drmp那 样,但是 A DImp2告诉我们,它也能被实现成 public的类。但是 A.DImp2只能被当作它自己的类型来用。你不能透露任何“它实现了 个 private接口”的信息,因此实现 private接口就成了一种“强制 你去定义那个接口的方法,但是又不让你添加任何类型信息(也就是说不 允许上传)”的手段了。 getD()方法揭示了 private接口的更深层次的困境:它是一个 public 方法,但却会返回一个 private接口的 reference。这个返回值又该怎 么用呢?可以看到,main()作了好几次尝试,试图利用这个返回值,但 是都失败了。唯一行得通的办法就是,把这个返回值交给一个有权用它的 对象—这就是通过A的 received()方法。 第14页共47页 www.wgqqh.com/shhgs/tij.html email:shhgs@sohu.com
Thinking in Java 3 rd Edition www.wgqqh.com/shhgs/tij.html email:shhgs@sohu.com ✄ 14 ☎ ✆ 47 ☎ //! } class EImp implements E { public void g() {} } class EGImp implements E.G { public void f() {} } class EImp2 implements E { public void g() {} class EG implements E.G { public void f() {} } } public static void main(String[] args) { A a = new A(); // Can't access A.D: //! A.D ad = a.getD(); // Doesn't return anything but A.D: //! A.DImp2 di2 = a.getD(); // Cannot access a member of the interface: //! a.getD().f(); // Only another A can do anything with getD(): A a2 = new A(); a2.receiveD(a.getD()); } } ///:~ FË(8 $!(~vFË(3¦ A[ÝE pu blic 3 package (ೡÝE<g pu blic package (Ævñí pu blicpackage "Á private (Í(nested cl asses)Ï jÄ A. D D(13Â(°#[ÝE private (( ²Ý)Í nested interfaces Ï[Ý)Í nested cl asses Ï)YZ private (ümZÙ áÊ Ý;¡ºÙAó;vñí private (} DImp Y ¦ A. DImp2 #A[;vñí pu blic ( A. DImp2 ó;v 1Aýþ(hQ¡X;$%tÍAñí, 3× private Ï(èéæòñí private ,3Í_ ¡O4Y×(µüXÇ¡ìäthèé ([$X JA)Ï(CD, getD( )µ, private (&ª¨('LA3× pu blic µiºef3× private ( reference ×efgüwÕ ZáÊ ÝE<gmain ( )1,i¨() ×efg Æ6*,+3}(,P ×efgR¬3×mA( ¥!55 ^ A ( receivedD( )µ
Thinking in Java 3 Edition 接口E揭示了,接口与接口也可以相互嵌套。不过接口的规则仍然有效一 特别是接口的所有元素都必须是 public的这条,因此嵌套在接口中的 接口也都自动是 public的,它们不能是 private的。 NestingInterfaces演示了各种实现嵌套接口的办法。特别要注意的 是,实现接口的时候,不一定要实现嵌套在里面的接口。同样 private 接口只能在定义它的类里实现 初看起来,这些特性好像只是为“语法的一致性”服务的,但是根据我的 经验,一旦你理解了一种特性,自然会找到运用它的地方。 内部类 在一个类里定义另一个类是完全可以的。这被称为“内部类( Inner cass)”。内部类是一种非常有价值的特性,它能让你在逻辑上将相互从 属的类组织起来,并且在类的内部控制访问权限。但是切记,内部类和合 成是截然不同的,这一点非常重要。 虽然你正在学习内部类,但却不清楚为什么要有它。等到这一节的末尾, 等我们讲完内部类的语法和语义之后,你就会看到一些“能告诉你内部类 有什么好处”的例子了 创建内部类的方法同你想像的完全相同——将类的定义放到它的宿主类 ding class) //: c08: Parcell. java / Creating inner classes public class Parcell lass Contents i lass Destination i private String labeli stri abeloi return labeli h / Using inner classes looks just like // using any other class, withi public void ship(string dest) t Contents c= new Contents ()i System. out. println(d. readLabel())i public static void main(string[] args)i ew Parcell( 第15页共47页 www.wgqqh.com/shhgs/tij.html
Thinking in Java 3 rd Edition ✄ 15 ☎ ✆ 47 ☎ www.wgqqh.com/shhgs/tij.html email:shhgs@sohu.com E ,[ÝE>X^(È9-mØ5 5)¨(Dm¼½Æ pu blic ( .æòF*( [Æý pu blic (AX; private ( N estin gIn terfaces ,Ññí(,)¨%¹( ñí(MX3O%ñíF˶(¦ private ó;FO4A(Ëñí f<9Q Ì)*}óÍ(3/*Ï01(;m( õ23¡¢£,3)*ýº3g\A(rµ F3×ËO4M3×cÝE( vµÍ(inner class)Ï3¯·m4g()*A;Ç¡F56J> 7(9Q³F(Ò8° 9X( 3C¯·% ¡jF0:iXX;Z%mA-g 3<(=> -©(4u¡º<g3ÌÍ;#¡ mZÙÏ(, 12(µ¡|}(c>55(O4kgA(PQ (su rrou nd ing cl ass)L //: c08:Parcel1.java // Creating inner classes. public class Parcel1 { 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; } } // Using inner classes looks just like // using any other class, within Parcel1: public void ship(String dest) { Contents c = new Contents(); Destination d = new Destination(dest); System.out.println(d.readLabel()); } public static void main(String[] args) { Parcel1 p = new Parcel1(); p.ship("Tanzania"); }