中国高校课件下载中心 》 教学资源 》 大学文库

《Thinking in Java》中文版 第四章 初始化与清理

文档信息
资源类别:文库
文档格式:PDF
文档页数:42
文件大小:375.02KB
团购合买:点击进入团购
内容简介
随着计算机革命的进步,“不安全”的编程方式已经成为让编程变得如此 昂贵的主要原因了。 这类安全性问题包括初始化(initialization)和清理( cleanup)这两项。C 程序的很多bug都是由程序员忘了对变量进行初始化引起的。碰到一些 用户不知道该如何初始化,甚至不知道要进行初始化的类库时,情况就更 是这样了。清理是一个特殊的问题,因为变量用过之后就没用了,因此会 很容易把这一步给忘了。这样程序仍然保留着那些元素所占用的资源
刷新页面文档预览

致读者 我从2002年7月开始翻译这本书,当时还是第二版。但是翻完前言和介绍部分 后, chinapub就登出广告,说要出版侯捷的译本。于是我中止了翻译,等着侯 先生的作品。 我是第一时间买的这本书,但是我失望了。比起第一版,我终于能看懂这本书 了,但是相比我的预期,它还是差一点。所以当 Bruce eckel在他的网站上公开 本书的第三版的时候,我决定把它翻译出来。 说说容易,做做难。一本1000多页的书不是那么容易翻的。期间我也曾打过退 堂鼓,但最终还是全部翻译出来了。从今年的两月初起,到7月底,我几乎放 弃了所有的业余时间,全身心地投入本书的翻译之中。应该说,这项工作的难 度超出了我的想像。 首先,读一本书和翻译一本书完全是两码事。英语与中文是两种不同的语言 用英语说得很畅的句子,翻成中文之后就完全破了相。有时我得花好几分钟, 用中文重述一句我能用几秒钟读懂的句子。更何况作为读者,一两句话没搞 懂,并不影响你理解整本书,但对译者来说,这就不一样了 其次,这是一本讲英语的人写给讲英语的人的书,所以同很多要照顾非英语读 者的技术文档不同,它在用词,句式方面非常随意。英语读者会很欣赏这 点,但是对外国读者来说,这就是负担了。 再有, Bruce eckel这样的大牛人,写了1000多页,如果都让你读懂,他岂不是 太没面子?所以,书里还有一些很有“禅意”的句子。比如那句著名的“The genesis of the computer revolution was in a machine. The genesis of our programming languages thus tends to look like that machine.”我就一直没吃准该怎 么翻译。我想大概没人能吃准,说不定 Bruce要的就是这个效果 这是一本公认的名著,作者在技术上的造诣无可挑剔。而作为译者,我的编程 能力差了很多。再加上上面讲的这些原因,使得我不得不格外的谨慎。当我重 读初稿的时候,我发现需要修改的地方实在太多了。因此,我不能现在就公开 全部译稿,我只能公开已经修改过的部分。不过这不是最终的版本,我还会继 续修订的。 本来,我准备到10月份,等我修改完前7章之后再公开。但是,我发现我又有 点要放弃了,因此我决定给自己一点压力,现在就公开。以后,我将修改完 章就公开一章,请关注www.wgqgh.com/shags/tii.htm 如果你觉得好,请给告诉我,你的鼓励是我工作的动力;如果你觉得不好,那 就更应该告诉我了,我会参考你的意见作修改的。我希望能通过这种方法,译 出一本配得上原著的书。 2003年9月8日 第1页共42页

shhgs@wgqqh.com ￾ 1 ✁ ✂ 42 ✁   2002 7    chinapub  !"# $%!&'( )*+, -.& /0(12 345( 67,893 :);8(?@ AB3CDE Bruce Eckel FG(HIJK (L(M NOPA!Q $$RS TTU3 1000 VW( XYZRS(@4[\]^_ `a b:c!Q,d(ef9 g 7 h ijk l,Dm(no4 cpqrst (u*vw$ xy1(U z{!,(|} ~/ 3 3 ce€‚ƒ„*…e†X‡(ƒ ˆ‚ƒ$‰Š‹(Œ Ž*…uc,>m‰‘i’ ˆ*…3Œ;ˆi•’=(Œ1™š 3eŒ›œ = žXŸ ¡¢£¤ ¥šQ$ X3¦, §¨ 3 ©‚ƒ(ª«¬©‚ƒ(ª( DE‡ŠV%­®¯‚ƒ š(°±…²X‡ AFˆ³ Œ´µ¶¯·¸¹‚ƒšºŠ»¼ 3 C ¥½¾šQ$ ¿À, Ám Bruce Eckel ¦(Âê «, 1000 VW ÄÅÆÇ¡= GÈX ɜ¶Ê DE Ëm3̊mÍιÏ(Œ8ÄYŒÐÑ(ÍThe genesis of the computer revolution was in a machine. The genesis of our programming languages thus tends to look like that machine.Ï3ҜÓÔwÕ Z|Â֜ª;ÓÔ $XO Bruce %( רÅ 3 KÙ(ÑÐ 1šF°±J(ÚÛÜÝÞßà1™š (áâ ;ãB,ŠVÁäJJ¶©( Ìåæ ç‰X‰Xè½(éê  fë(M ìíî%ïð(rµñFÉV,æò X;íFK cë ó;Kôõïð^(X^ Xb:( ºö ÷ïø( Q Ôùg 10 ú -ïð 7 ûuÁK ìíüm C%kl, æòNO¬ý þ3Cã íFKE ïð3 ûK3û  www.wgqqh.com/shhgs/tij.html ÄÅ¡‰‘ ¬# ¡(ay1( ã ÄÅ¡‰X‘ Y vw#, º ¡(¹ 1ïð(7;^ †µ  !3 ‰JåÐ(  shhgs 2003 9  8 

4:初始化与清理 随着计算杋革命的进步,“不安全”的编程方式已经成为让编程变得如此 昂贵的主要原因了。 这类安全性问题包括初始化( initialization)和清理( cleanup)这两项。C 程序的很多buq都是由程序员忘了对变量进行初始化引起的。碰到一些 用户不知道该如何初始化,甚至不知道要进行初始化的类库时,情况就更 是这样了。清理是一个特殊的问题,因为变量用过之后就没用了,因此会 很容易把这一步给忘了。这样程序仍然保留着那些元素所占用的资源,因 此资源会很快被耗尽(最常见的就是内存)。 C++引入了构造函数( constructor)的概念,这是一种能在对象创建的时 候自动调用的方法。Java也采纳了这种做法,此外对于那些无需再用的 对象,它还有一个会自动释放其所占内存的垃圾回收器。本章探讨了初始 化和清理问题,并且讲解了Java是如何处理这两个问题的 用构造函数确保初始化 可以这样认为,每个类都有一个名为 initialize()的方法。这个名字就 暗示了它得在对象使用之前调用。不幸的是,这么做的话,用户就得记住 要调用这个方法。Java类库的设计者们可以通过提供一种被成为构造函 数( constructor)的特殊方法,来保证每个对象都能得到初始化。如果类 有构造函数,那么Java就会在对象刚刚创建,用户还来不及得到的时 候,自动调用那个构造函数。这样初始化就有保障了 接下来的问题是如何命名这个方法。这有两层意思。第一,名字不能与类 的成员的名字相冲突。第二,由于构造函数是由编译器调用的,因此编译 器必须要能知道该调用哪个方法。既然C++的解决方案既简单又合理, 那么Java就沿用了这种做法:构造函数的名字就是类的名字。于是初始 化的时候这个方法的自动调用就变得顺理成章了。 下面是一个带构造函数的简单的类 //: c04: SimpleConstructor java / Demonstration of a simple constructor import com. bruceeckel. simpletest *i class Rock Rock((// This is the constructor System. out. println ("Creating Rock") public class SimpleConstructor t static Test monitor new Test ( public static void main(String[] args) i 第2页共42页

shhgs@wgqqh.com ￾ 2 ✁ ✂ 42 ✁ 4: ¸.( ÍXcÏ(áâµ´ôõŽ™Çáâ‰Äò (%åæ, c !"#$f%(initialization)&¢(cleanup) exC â'(ŠV b u g Æ(â')*,¥+,f%-9(.g3Ì ˆ/X01wÄf% 23X01%,f%(4 5  ¦,&¢3×67(!" æ™+ˆ^uœˆ, æòº ŠRSP 3¬*, ¦â'89:;.Ÿ(?@ æ ò?@ºŠABCD(b· (EF) C++-t,GÚHI(constructor)(ÖJ 3†;F¥KLM( Mý Nˆ(µJava [OP, †T ò½¥)YÌÜîÁˆ( ¥K Am3׺ý Qk§D>EF(RSTUV ûWX,f %&¢!" žY©£, Java ÄZ¢ e×!"(  ÝE ¦Ù™ [ׯm3×љ initialize( )(µ ×Ñ\ ]^,A‰F¥KçˆuNˆX_( ZT(› ˆ/‰`a %Nˆ ×µJava 4(bšcÝE^de3†BŽ™GÚH I(constructor)(67µ Q:f[×¥KÆ;‰gf%ÄÅ mGÚHI YZ Java ºF¥KggLM ˆ/QXh‰g( M ý NˆY×GÚHI ¦f%m:i, jkQ(!"ÄÑ ×µ mel¹m3 Ñ\X;„ (Ž)(Ñ\>no ()GÚHI(áVNˆ( æòá Vpq%;01wNˆr×µs9 C++(£Nµtsuvüw¢ YZ Java xˆ, †TyGÚHI(Ñ\(Ñ\)f %(M ×µ(ý Nˆ‰z¢Žû, k¶3×{GÚHI(uv(y //: c04:SimpleConstructor.java // Demonstration of a simple constructor. import com.bruceeckel.simpletest.*; class Rock { Rock() { // This is the constructor System.out.println("Creating Rock"); } } public class SimpleConstructor { static Test monitor = new Test(); public static void main(String[] args) {

for (int i=0; i< 10: 1++) new Rock()i monitor. expect(new String[] i Creating Rock "Creating Rock "Creating Rock" "Creating Rock", "Creating Rock" Creating Rock", "Creating Rock Creating Rock }///:~ 现在,创建对象的时候 new Rock (i 不但要分配内存而且还要调用构造函数。这个过程是有保障的。因此,在 你能得到这个对象之前,它就已经被妥善地初始化了。 注意,编程风格要求的方法的首字母要小写的要求不适用与构造函数,因 为构造函数的名字必须与类的名字完全相同。 与其他方法一样,构造函数也可以有参数,这样你就能告诉它该如何进行 初始化了。前面这段程序经过简单地修改之后,也能让它的构造函数接受 参数 //: c04: SimpleConstructor2 java / Constructors can have arguments import com. bruceeckel simpletest*i class Rock2 I Rock2(int i)I System. out. println ("Creating Rock number " i public class simpleConstructor2 static Test monitor new Test ( public static void main(String[] args) i for (int i=0: i< 10: 1++) new Rock2(i) monitor.expect (new String[] i Creating Rock number 0", "Creating Rock number 1" Creating Rock number 2 "Creating Rock number 3 第3页共42页

shhgs@wgqqh.com ￾ 3 ✁ ✂ 42 ✁ for(int i = 0; i ‡ „§Gµ3¦ GÚHI[ÝEm I ¦¡;#AwÄ, f%,¶ „â'õ^uvrïðu [;ÇA(GÚHIj… Iy //: c04:SimpleConstructor2.java // Constructors can have arguments. import com.bruceeckel.simpletest.*; class Rock2 { Rock2(int i) { System.out.println("Creating Rock number " + i); } } public class SimpleConstructor2 { static Test monitor = new Test(); public static void main(String[] args) { for(int i = 0; i < 10; i++) new Rock2(i); monitor.expect(new String[] { "Creating Rock number 0", "Creating Rock number 1", "Creating Rock number 2", "Creating Rock number 3",

"Creating Rock number 4" Creating Rock number 5", "Creating Rock number 6 ", "Creating Rock number 7" Creating Rock number 8 Creating Rock number 9 }///: 构造函数的参数是一种能让你对对象的初始化提供参数的方法。比方说, Tree类有一个拿整数作参数的构造函数,而这个整数又表示树的高度, 那么你就可以这样来创建一个Tree对象: Tree t new Tree(12): // 12-foot tree 如果Tree(int)是类仅有的构造函数,那么编译器不会让你再用其它方 法创建Tree对象了。 构造函数解决了一大堆问题,提高了代码的可读性。比如,在上述的代码 中,根本用不着去调用像 initialize()这种,在概念上同对象的创建相 分离的方法。Java的对象创建和初始化是同一个概念—你不能要这个 而不要那个。 构造函数是一种特殊的方法,它没有返回值。这一点同void型的方法有 着本质上的区别,void型的方法什么都不返回,但这是你决定的,你也 可以让它返回些什么。而构造函数则什么都不返回,而且你别无选择 (new表达式确实会返回这个新创建的对象的 reference,但是构造函数 本身不返回任何值)。如果构造函数能有返回值,而且你还可以选择这个 值,那么编译器就要问了,它应该怎样处置这个返回值 方法的重载 名字管理是编程语言的一项重要特性。创建对象的时候,你会给内存空间 起名字。而方法是动作的名字。通过使用名字,别人就能更容易地理解和 修改程序了。这就像是在写散文——其目的就是要与读者交流 你用名字来表示对象和方法。不管是对你还是别人,好的名字能让代码读 起来更简单。 但是在把人类语言映射到编程语言的时候,会碰到了一件麻烦事。同一个 单词经常可以表达很多不同的意思——也就是说这个词被重载( overload) 了。碰到这些意思只有微不足道的差别的时候,这种情况就更常见了。你 会说“洗衬衫”,“洗车”,或者“给狗洗澡”。但是,如果你为了要让 第4页共42页

shhgs@wgqqh.com ￾ 4 ✁ ✂ 42 ✁ "Creating Rock number 4", "Creating Rock number 5", "Creating Rock number 6", "Creating Rock number 7", "Creating Rock number 8", "Creating Rock number 9" }); } } ///:~ GÚHI( I3†;Ç¡¥¥K(f%de I(µ8µ$ Tree m3׆¤I1 I(GÚHI à פIü‡^ˆ(‰z YZ¡ÝE ¦QLM3× Tree ¥Ky Tree t = new Tree(12); // 12-foot tree ÄÅ Tree(int) Šm(GÚHI YZáVXºÇ¡Áˆ§Aµ LM Tree ¥K, GÚHI£N,3‹!" d‰,Œ€(Ý 8Ä FJ(Œ€ *  ˆX.ŽNˆ} initialize( ) † FÖJJ‡¥K(LM> (µJava (¥KLMf%‡3×ÖJ¡X;% × àX%Y× GÚHI3†67(µ Aœm‘T’ 3C‡ void (µm . J(• void (µZÆX‘T  ¡NO( ¡[ ÝEÇA‘TÌZàGÚHIZÆX‘T àY¡Ü™š (new ‡›´œñº‘T םLM(¥K( referen ce GÚHI pX‘Tž’)ÄÅGÚHI;m‘T’ àY¡ÝE™š × ’ YZáV%!, AvwÕ¦ZŸ בT’  Ñ\ ¢áâƒ(3x%6 LM¥K(M ¡º¬EF¡4 9Ñ\ൠ1(Ñ\^çˆÑ\ ª;RSr¢£ ïðâ', }F«¢…§£(%„𤥠¡ˆÑ\Q‡^¥KµX ¥¡ª ‘(Ñ\;nj€ 9Quv FPªƒ¦§gáâƒ(M º.g,3¨©ª‡3× v³õ·ÝE‡›ŠVX‡(¹m[$ ׳B«(overload) ,.g ̹móm¬X­1(B(M †5· ,¡ º$Í®¯°Ï Í®±Ï ²šÍ¬³®´Ï ÄÅ¡™,%Ç

听众不用去区分这些动作的区别,而在那里说“用洗衬衫的方式洗衬 衫”,“用洗车的方式洗车”,或者“用给狗洗澡的方式给狗洗澡”,那 就太傻了。绝大多数的人类语言都有冗余,所以即使我们省掉几个字,你 也能知道他在讲些什么。我们不需要排除所有的两义性—我们可以从上 下文作出判断。 绝大多数的编程语言(特别是C)都要你为每个函数都起一个独一无二的标 识符。所以你不能让一个 print()专门打印整数,而让另一个 print() 专门打印浮点数—每个函数都需要一个唯一的名字。 Java(以及C++)里还有一个让我们不得不对方法进行重载的原因:构造 函数。由于构造函数的名字已经由类名决定了,因此构造函数就只能有 个名字。但是假如你要用几种不同的方法来创建对象的话,那又该怎么办 呢?假设你要创建这样一个类,它既能以标准的方式进行初始化,又能从 文件里读取信息以进行初始化。你得有两个构造函数,一个是不需要参数 的(即默认的构造函数( default constructo),9也称为无参数(no-arg) 构造函数),另一个是需要一个 String作参数的构造函数。而这个 String就是初始化所需的文件的文件名。这两个都是构造函数,所以它 们得用同一个名字——类的名字。于是,为了能让相同名字的方法使用不 同的参数类型,方法的重载( method overloading)就变得非常重要了 重载不仅对构造函数来说是必须,而且也是一种很通用的,能用于任何方 法的技巧 下面这段程序既演示了构造函数的重载,也演示了普通方法的重载 //: c04: Overloading. java / Demonstration of both constructor and ordinary method overloading import com. bruceeckel simpletest. import java. util.* class Tree t int height System. out. println("Planting a seedling ")i Tree (int i)t System. out. println ("Creating new Tree that is + i +"feet tall")i height =i System. out. println("Tree is " height +#feet ta11"); void info(String s)t System. out. println(s +": Tree is eight "feet tall")i 第5页共42页

shhgs@wgqqh.com ￾ 5 ✁ ✂ 42 ✁ µ¶XˆŽ• Ì 1(• àFYË$͈®¯°(µ´®¯ °Ï ͈®±(µ´®±Ï ²šÍˆ¬³®´(µ´¬³®´Ï Y É·,¸ÂVI(ªƒÆm¹o DEºçc»¼i×\ ¡ [;01GF©ÌZcXî%½¾Dm(e¿ cÝEJ k…1!ÀÁ ¸ÂVI(áâƒ(6 C)Æ%¡™[×HIÆ93×Â3Ü(à ÄÅDE¡X;Ç3× print( )ÆÇ]ȤI àÇÉ3× print( ) ÆÇ]ÈÊCI[×HIÆî%3×Ë3(Ñ\ Java(Eh C++)Ëm3×ÇcX‰X¥µ,«(åæyGÚ HI()GÚHI(Ñ\ôõ(ÑNO, æòGÚHIó;m3 ×Ñ\ÌÄ¡%ˆi†X‡(µQLM¥K(› YüwÕZÍ ÎÊ Ìb¡%LM ¦3× As;EÃÔ(µ´,f% ü; …¨ËÏÐÑE,f%¡‰me×GÚHI 3×Xî% I ((ºÒÙ(GÚHI(default constructor) ✄ ☎ ✆ ✝ [ I(no-arg) GÚHI) É3×î%3× String 1 I(GÚHIà × String f%Dî(…¨(…¨Ñ eׯGÚHI DEA c‰ˆ‡3×Ñ\(Ñ\) ™,;Ç>‡Ñ\(µçˆX ‡( I µ(«(method overloading)‰¯·%, «XŠ¥GÚHIQ$pq àY[3†Šˆ( ;ˆ)žµ (°Ô k¶ „â'sÕ^,GÚHI(« [Õ^,Öµ(«y //: c04:Overloading.java // Demonstration of both constructor // and ordinary method overloading. import com.bruceeckel.simpletest.*; import java.util.*; class Tree { int height; Tree() { System.out.println("Planting a seedling"); height = 0; } Tree(int i) { System.out.println("Creating new Tree that is " + i + " feet tall"); height = i; } void info() { System.out.println("Tree is " + height + " feet tall"); } void info(String s) { System.out.println(s + ": Tree is " + height + " feet tall"); } }

public class overloading t static Test monitor =new Test ( public static void main(String[] args)i for (int t info oi / Over loaded constructor new Tree( monitor. expect (new String[] t Tree is o feet tall" overloaded method: Tree is o feet tall "Creating new Tree that is 1 feet tall", "Tree is 1 feet tall", overloaded method Tree is 1 feet tall# "Creating new Tree that is 2 feet tall", Tree feet tall overloaded method: Tree is 2 feet tall "Creating new Tree that is 3 feet tall" 3 feet tall" overloaded method: Tree is 3 feet tall" Creating new Tree that is 4 feet tall "Tree is 4 feet tall", overloaded method: Tree is 4 feet tall", Planting a seedling }///: 创建Tree对象的时候,既可以不用参数,也可以用一个表示高度的int 当参数。前者表示它还是一棵树苗,后者表示它已经成材了。为了能提供 这种功能,程序得有一个默认的构造函数,以及一个需要拿现有高度作参 数的构造函数 或许你还想多要几种调用info()的方法。比如,想多打印些东西的时 候,你可以用info( String),什么都不想说的时候,可以用info() 同一种概念要用两个名字,那肯定会很怪。所幸的是,有了方法重载,你 就可以让这两者使用同一个名字。 区分经重载的方法 如果方法的名字相同,那么Java又该如何判断你要用哪个方法的呢?有 个很简单的规则:每一个经过重载的方法都必须有唯一的参数类型的列 表 只要稍微想一下,你就会发现这是最合情理的办法。如果不是用参数的类 型,程序员又怎么来区分两个有着相同名字的方法呢? 第6页共42页

shhgs@wgqqh.com ￾ 6 ✁ ✂ 42 ✁ public class Overloading { static Test monitor = new Test(); public static void main(String[] args) { for(int i = 0; i ‡ YZ Java üwÄÀÁ¡%ˆr×µ(ÎÊ m 3׊uv(ày[3×õ^«(µÆpqmË3( I(á ‡ ó%â¬|3k ¡ºìí bw5¢(ÍÄÅXˆ I( â')üÕZQ•e×m.>‡Ñ\(µÎÊ

即使是参数顺序的颠倒也足以将两个方法区分开来:(不过,通常情况下 别用这种办法,因为这会产生难以维护的代码。) // c04: Overloadingorder Overloading based on the order of the arguments import com. bruceeckel. simpletest *i public class overloadingorder t static Test monitor new Test ( static void print (string s, int i)t System. out. println("string: +s Int static void print (int i, String s) t System. out. println ("int: " i + String public static void main(String[ args)t print ("String first", 1l)i print (99,"Int first")i monitor. expect (new string[] t wint: 99, String: Int firsti r "String: String first, int: 1l' }///:~ 两个 print()有着相同的参数,但是顺序不同,而这是它们唯一不同的 地方。 对 primitive进行重载 primitive会自动地从较小的类型升级到较大的类型。如果重载的时候又 碰到这个问题,那就有点让人麻烦了。下面这段程序演示了向重载方法传 primitive的时候,会发生什么事: //: c04: Primitiveoverloading java Promotion of primitives and overloading mport com. bruceeckel. simpletest. public class Primitiveoverloading static Test monitor new Test ( void fl(char x) System. out. printin(" fl(char)")i void fl(byte x)i System. out. println("fl(byte)")K t System. out. println("fl(short)")i j void fl(int x) System. out. println("fl(int)")i] ("f1(1ong)"); void fl(float x t System. out. println("fl(float)")i j id fl(double x) roid f2(byte x)i System. out. println("f2(byte)")i K 第7页共42页

shhgs@wgqqh.com ￾ 7 ✁ ✂ 42 ✁ ºç Iz'(ãä[­Ee×µ•Qy(X^ ·5k ˆ †Í æ™ ºå0UEæç(Œ€) //: c04:OverloadingOrder.java // Overloading based on the order of the arguments. import com.bruceeckel.simpletest.*; public class OverloadingOrder { static Test monitor = new Test(); static void print(String s, int i) { System.out.println("String: " + s + ", int: " + i); } static void print(int i, String s) { System.out.println("int: " + i + ", String: " + s); } public static void main(String[] args) { print("String first", 11); print(99, "Int first"); monitor.expect(new String[] { "String: String first, int: 11", "int: 99, String: Int first" }); } } ///:~ e× print( )m.>‡( I z'X‡ à AcË3X‡( rµ prim i tive  p ri m iti ve ºý rè(éêgèÂ(ÄÅ«(Mü .g ×!" YmCǪ©ª,k¶ „â'Õ^,뫵ì p ri m iti ve (M ºì0Zy //: c04:PrimitiveOverloading.java // Promotion of primitives and overloading. import com.bruceeckel.simpletest.*; public class PrimitiveOverloading { static Test monitor = new Test(); void f1(char x) { System.out.println("f1(char)"); } void f1(byte x) { System.out.println("f1(byte)"); } void f1(short x) { System.out.println("f1(short)"); } void f1(int x) { System.out.println("f1(int)"); } void f1(long x) { System.out.println("f1(long)"); } void f1(float x) { System.out.println("f1(float)"); } void f1(double x) { System.out.println("f1(double)"); } void f2(byte x) { System.out.println("f2(byte)"); }

oid f2(short x) t System. out. println("f2(short)")i) void f2(int x) System. out. println("f2(int)")i 1 void f2 (long x)[ System. out. println("f2(long)")iJ void f2(float x) t System. out. println(" f2(float)")i F void f2(double x) t System. out. println("f2(double)")i) id f3(short x) t System. out. println("f3(short)")i d f3(int x) Syst tln ("f3(int)") void f3(long x)[ System. out. println ("f3(long)")i t System. out. println("f3(float)")i void f3(double x) t System. out. println("f3(double)")i) void f4(int x)( System. out. println("f4(int)")i void f4(long x)i System. out. println("f4(long)")i F void f4(float x t System. out. println(f4(float)")i F t System. out. println(" f4(double)")i) void f5 (long x) System. out. println("f5(long)")i F t System. out. println(" f5(float)")i F oid f5(double x) t Syst id f6(doubl I System. out. println("f6(double)")i) void f7(double x) t System. out. println("f7(double)")i) void testConstVal() i Sy: ting (5);f2(5);f3(5);f4(5);f5(5);f6(5 void testchar()( System. out. println("char argument: " 1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x); id testByte() ut.pi f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x) () System. out. println("short argument: ")i f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x); void testInt ( 0 System. out. println("int argument: ")i 第8页共42页

shhgs@wgqqh.com ￾ 8 ✁ ✂ 42 ✁ void f2(short x) { System.out.println("f2(short)"); } void f2(int x) { System.out.println("f2(int)"); } void f2(long x) { System.out.println("f2(long)"); } void f2(float x) { System.out.println("f2(float)"); } void f2(double x) { System.out.println("f2(double)"); } void f3(short x) { System.out.println("f3(short)"); } void f3(int x) { System.out.println("f3(int)"); } void f3(long x) { System.out.println("f3(long)"); } void f3(float x) { System.out.println("f3(float)"); } void f3(double x) { System.out.println("f3(double)"); } void f4(int x) { System.out.println("f4(int)"); } void f4(long x) { System.out.println("f4(long)"); } void f4(float x) { System.out.println("f4(float)"); } void f4(double x) { System.out.println("f4(double)"); } void f5(long x) { System.out.println("f5(long)"); } void f5(float x) { System.out.println("f5(float)"); } void f5(double x) { System.out.println("f5(double)"); } void f6(float x) { System.out.println("f6(float)"); } void f6(double x) { System.out.println("f6(double)"); } void f7(double x) { System.out.println("f7(double)"); } void testConstVal() { System.out.println("Testing with 5"); f1(5);f2(5);f3(5);f4(5);f5(5);f6(5);f7(5); } void testChar() { char x = 'x'; System.out.println("char argument:"); f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x); } void testByte() { byte x = 0; System.out.println("byte argument:"); f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x); } void testShort() { short x = 0; System.out.println("short argument:"); f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x); } void testInt() { int x = 0; System.out.println("int argument:");

f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x); void testlong() i System. out. println("long argument: " )i f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x); void testFloato( float x=0 System. out. println("float argument: f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x); void testDoubleoi double 0 System. out. println("double argument: " f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x); publ ic void main(St Primitiveoverloading p new PrimitiveOverloading () p. testConstval( p. testchar()i ttt p ashort( p testInt () ttt sss Long () tFloat( p.te monitor. expect (new String[] i "Testing with 5", 234 fffff nnnn "f7(double)", "char argument fl(char) "f3(int) f6(float)", 7(double) byte argument: 123 (byte)", eer "f5(1ong)" ffs 7(double) nfl(short)nnt: " "f2(short) f3(short) "f4(int)# "f6( "f7 1fd o1o 第9页共42页

shhgs@wgqqh.com ￾ 9 ✁ ✂ 42 ✁ f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x); } void testLong() { long x = 0; System.out.println("long argument:"); f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x); } void testFloat() { float x = 0; System.out.println("float argument:"); f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x); } void testDouble() { double x = 0; System.out.println("double argument:"); f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x); } public static void main(String[] args) { PrimitiveOverloading p = new PrimitiveOverloading(); p.testConstVal(); p.testChar(); p.testByte(); p.testShort(); p.testInt(); p.testLong(); p.testFloat(); p.testDouble(); monitor.expect(new String[] { "Testing with 5", "f1(int)", "f2(int)", "f3(int)", "f4(int)", "f5(long)", "f6(float)", "f7(double)", "char argument:", "f1(char)", "f2(int)", "f3(int)", "f4(int)", "f5(long)", "f6(float)", "f7(double)", "byte argument:", "f1(byte)", "f2(byte)", "f3(short)", "f4(int)", "f5(long)", "f6(float)", "f7(double)", "short argument:", "f1(short)", "f2(short)", "f3(short)", "f4(int)", "f5(long)", "f6(float)", "f7(double)

f2(int) 6(f1oat)", f7(double) fl (long) "f4(1ong)", f5 (long) float argument: " fl(float)", f2(float) "f3(float)", f 4(float) "f5(float)", "f6(float)" double argument: " "fl(double)", f 4(double) 你会发现,常量5会被当作int,所以,如果重载的方法里有拿int作参 数的,它会用这个方法。在其他情况下,如果实参(译者注:真正调用方 法的那个参数)的类型比形参(译者注:方法的定义中所声明的参数)的类 型小,那么数据会先提升。char的反映会有些不同,因为如果如果找不 到匹配的char的话,它会被提升到int 如果实参比形参更大,那又会怎样呢?我们修改一下上面那段程序,让它 来告诉你答案 Demotion of primitives and ov er⊥ oading import com. bruceeckel. simpletest *i static Test monitor new Test ( void fl(char x)[ System. out. println("fl(char)")iJ t System. out. println("fl(short)")i j 第10页共42页

shhgs@wgqqh.com ￾ 10 ✁ ✂ 42 ✁ "int argument:", "f1(int)", "f2(int)", "f3(int)", "f4(int)", "f5(long)", "f6(float)", "f7(double)", "long argument:", "f1(long)", "f2(long)", "f3(long)", "f4(long)", "f5(long)", "f6(float)", "f7(double)", "float argument:", "f1(float)", "f2(float)", "f3(float)", "f4(float)", "f5(float)", "f6(float)", "f7(double)", "double argument:", "f1(double)", "f2(double)", "f3(double)", "f4(double)", "f5(double)", "f6(double)", "f7(double)" }); } } ///:~ ¡ºìí ·+ 5 ºB 1 int DE ÄÅ«(µËm† int 1 I( Aºˆ ×µF§G5k ÄÅñ (šyíîNˆµ (Y× I)(8ï (šyµ(O¿*Dðñ( I)(  YZIòº/déchar (ó¦ºmÌX‡ æ™ÄÅÄÅôX gõ( char (› AºBdég int ÄÅñ 8ï  YüºÕ¦ÎÊ cïð3kJ¶Y„â' ÇA Q#¡öty //: c04:Demotion.java // Demotion of primitives and overloading. import com.bruceeckel.simpletest.*; public class Demotion { static Test monitor = new Test(); void f1(char x) { System.out.println("f1(char)"); } void f1(byte x) { System.out.println("f1(byte)"); } void f1(short x) { System.out.println("f1(short)"); }

刷新页面下载完整文档
VIP每日下载上限内不扣除下载券和下载次数;
按次数下载不扣除下载券;
注册用户24小时内重复下载只扣除一次;
顺序:VIP每日次数-->可用次数-->下载券;
相关文档