treenode

          在路上。

          BlogJava 首頁(yè) 新隨筆 聯(lián)系 聚合 管理
            5 Posts :: 1 Stories :: 53 Comments :: 0 Trackbacks
          請(qǐng)比較一下這兩段功能大致相同的代碼。拋開(kāi)語(yǔ)法的差別不論,你覺(jué)得哪種風(fēng)格好?你愿意維護(hù)哪一段代碼?

          ????????b.addSelectionListener(?new?SelectionAdapter()
          ????????{
          ????????????
          public?void?widgetSelected(?SelectionEvent?e?)
          ????????????{
          ????????????????Runnable?longJob?
          =?new?Runnable()
          ????????????????{
          ????????????????????
          boolean????done????=?false;
          ????????????????????
          int????????id;

          ????????????????????
          public?void?run()
          ????????????????????{
          ????????????????????????Thread?thread?
          =?new?Thread(?new?Runnable()
          ????????????????????????{
          ????????????????????????????
          public?void?run()
          ????????????????????????????{
          ????????????????????????????????id?
          =?nextId[0]++;
          ????????????????????????????????display.syncExec(?
          new?Runnable()
          ????????????????????????????????{
          ????????????????????????????????????
          public?void?run()
          ????????????????????????????????????{
          ????????????????????????????????????????
          if?(?text.isDisposed()?)
          ????????????????????????????????????????????
          return;
          ????????????????????????????????????????text
          ????????????????????????????????????????????????.append(?
          "\nStart?long?running?task?"
          ????????????????????????????????????????????????????????
          +?id?);
          ????????????????????????????????????}
          ????????????????????????????????}?);
          ????????????????????????????????
          for?(?int?i?=?0;?i?<?100000;?i++?)
          ????????????????????????????????{
          ????????????????????????????????????
          if?(?display.isDisposed()?)
          ????????????????????????????????????????
          return;
          ????????????????????????????????????System.out
          ????????????????????????????????????????????.println(?
          "do?task?that?takes?a?long?time?in?a?separate?thread?"
          ????????????????????????????????????????????????????
          +?id?);
          ????????????????????????????????}
          ????????????????????????????????
          if?(?display.isDisposed()?)
          ????????????????????????????????????
          return;
          ????????????????????????????????display.syncExec(?
          new?Runnable()
          ????????????????????????????????{
          ????????????????????????????????????
          public?void?run()
          ????????????????????????????????????{
          ????????????????????????????????????????
          if?(?text.isDisposed()?)
          ????????????????????????????????????????????
          return;
          ????????????????????????????????????????text
          ????????????????????????????????????????????????.append(?
          "\nCompleted?long?running?task?"
          ????????????????????????????????????????????????????????
          +?id?);
          ????????????????????????????????????}
          ????????????????????????????????}?);
          ????????????????????????????????done?
          =?true;
          ????????????????????????????????display.wake();
          ????????????????????????????}
          ????????????????????????}?);
          ????????????????????????thread.start();
          ????????????????????????
          while?(?!done?&&?!shell.isDisposed()?)
          ????????????????????????{
          ????????????????????????????
          if?(?!display.readAndDispatch()?)
          ????????????????????????????????display.sleep();
          ????????????????????????}
          ????????????????????}
          ????????????????};
          ????????????????BusyIndicator.showWhile(?display,?longJob?);
          ????????????}
          ????????}?);
          另外一種:
          ????????delegate?void?NotifyStartDelegate(?int?threadId?);
          ????????
          delegate?void?NotifyFinishDelegate(?int?threadId?);
          ????????
          ????????btnInvoke.Click?
          +=?BtnInvokeClick;
          ????????
          ????????
          void?BtnInvokeClick(object?sender,?System.EventArgs?e)
          ????????{
          ????????????text.Text?
          =?"invoke?long?running?job";
          ????????????
          ????????????Cursor?
          =?Cursors.WaitCursor;
          ????????????Thread?thread?
          =?new?Thread(?new?ThreadStart(ThreadProc)?);
          ????????????thread.Start();
          ????????}
          ????????
          ????????
          private?void?ThreadProc()
          ????????{
          ????????????
          int?threadId?=?nextId?++;
          ????????????
          bool?done?=?false;
          ????????????
          ????????????
          if?(?IsDisposed?)
          ????????????????
          return;
          ????????????
          ????????????Invoke(?
          new?NotifyStartDelegate(notifyThreadStart),?new?object[]?{?threadId?}?);
          ????????????
          for?(?int?i=0;?i<100000;?i++?)
          ????????????{
          ????????????????
          if?(?IsDisposed?)
          ????????????????????
          return;
          ????????????????Console.WriteLine(?
          "do?task?that?takes?a?long?time?in?a?separate?thread?"?+?threadId?);
          ????????????}
          ????????
          ????????????
          if?(?IsDisposed?)
          ????????????????
          return;
          ????????????Invoke(?
          new?NotifyFinishDelegate(notifyThreadFinish),?new?object[]?{?threadId?}?);
          ????????????done?
          =?true;
          ????????}
          ????????
          ????????
          private?void?notifyThreadStart(?int?threadId?)
          ????????{
          ????????????text.Text?
          +=?"\r\nStart?long?task?"?+?threadId;
          ????????????threadCount?
          ++;
          ????????}
          ????????
          ????????
          private?void?notifyThreadFinish(?int?threadId?)
          ????????{
          ????????????text.Text?
          +=?"\r\nCompleted?long?running?task?"?+?threadId;????
          ????????????threadCount?
          --;
          ????????????
          if?(?threadCount?==?0?)
          ????????????????Cursor?
          =?Cursors.Default;
          ????????}
          ????????
          ????????
          private?int?nextId?=?0;
          ????????
          private?int?threadCount?=?0;

          我在另一個(gè)地方也抱怨過(guò):在所有我了解的語(yǔ)言特性里面,沒(méi)有一種像Java內(nèi)部類(lèi)一樣讓我覺(jué)得反感——甚至到了惡心的地步。大多作B/S系統(tǒng)的Java程 序員可能不會(huì)有這樣的感覺(jué),因?yàn)槟莻€(gè)領(lǐng)域基本上很少會(huì)用到這個(gè)概念。可是在C/S,不管用Swing還是SWT,內(nèi)部類(lèi)都是繞不過(guò)去的一座大山。在閱讀Eclipse站點(diǎn)上許多代碼示例以后,我終于有了痛苦到——一點(diǎn)也不夸張——想要作嘔的地步。上面第一段代碼就是讓我感到窩心的代碼之一(僅僅是其中之一,還不是最丑陋的)。我想,Java 語(yǔ)言的發(fā)明者大概從來(lái)就沒(méi)寫(xiě)過(guò)桌面程序;他根本也不打算為這個(gè)領(lǐng)域的程序員提供一種比較好的事件回調(diào)機(jī)制。

          內(nèi)部類(lèi)有什么問(wèn)題呢?首先,你愿意在去看代碼邏輯之前,先花上好幾分鐘去搞清楚“這個(gè)括號(hào)到底是和哪個(gè)配對(duì)”這種蠢問(wèn)題嗎?你不妨回頭看看第一段的代碼,想想這段其實(shí)相當(dāng)簡(jiǎn)單的程序,是不是真的值得用這么多括號(hào)去考驗(yàn)?zāi)愕闹橇Α?br />
          內(nèi)部類(lèi)是對(duì)封裝的嚴(yán)重破壞。它對(duì)外部類(lèi)的任何私有變量都有完全的訪問(wèn)權(quán)限——如果你突然發(fā)現(xiàn)某個(gè)變量的內(nèi)容不對(duì)勁了,你不能僅僅在setXXX里面加個(gè)斷 點(diǎn)就指望能捕獲到錯(cuò)誤;真正的元兇可能是內(nèi)部類(lèi)里面的哪一句呢。如果內(nèi)部類(lèi)都非常簡(jiǎn)單,那倒也沒(méi)什么??墒钱?dāng)內(nèi)部類(lèi)用來(lái)實(shí)現(xiàn)事件的時(shí)候,你就沒(méi)法指望它一 直那么簡(jiǎn)單了。

          內(nèi)部類(lèi)是測(cè)試的盲區(qū)。TDD總是說(shuō),要測(cè)試,測(cè)試,所有包含邏輯的類(lèi)都應(yīng)當(dāng)通過(guò)充分的測(cè)試。可是內(nèi)部類(lèi)怎么測(cè)試?只要想想就能知道,大多數(shù)內(nèi)部類(lèi)是根本沒(méi)法測(cè)試的,它和外部類(lèi)實(shí)在是耦合的太緊密了。匿名內(nèi)部類(lèi)的問(wèn)題更嚴(yán)重——它是絕對(duì)無(wú)法測(cè)試的。你怎么測(cè)試一個(gè)連名字都沒(méi)有的方法?

          不管有意無(wú)意,內(nèi)部類(lèi)在(至少我看到的)實(shí)踐中事實(shí)上鼓勵(lì)了不好的編程風(fēng)格。就是說(shuō),它違背了DRY(Don't Repeat Yourself)的原則。比如,button.addSelectionListener后面幾乎總是跟著SelectionAdapter+括號(hào)+ widgetSelected原型再+一堆括號(hào);Display.asyncExec后面總是要寫(xiě)上new Runnble(),void run(),括號(hào),等等。千篇一律的東西,可是又不得不寫(xiě)。而且,幾乎沒(méi)有什么好的辦法可以改進(jìn)!因?yàn)檎Z(yǔ)法的規(guī)則要求你必須這樣做。每天寫(xiě)這些無(wú)聊的東 西,你的話會(huì)不會(huì)煩?哦,工具是有的??墒枪ぞ咧回?fù)責(zé)生成代碼,以后的維護(hù)還是要你來(lái)做——不是么?
          posted on 2006-06-15 22:37 TreeNode 閱讀(3627) 評(píng)論(31)  編輯  收藏 所屬分類(lèi): Java技術(shù)

          Feedback

          # re: 內(nèi)部類(lèi)讓我厭惡Java 2006-06-15 22:44 Anders小明
          嘿嘿,java語(yǔ)言有些地方是不如.net做的好!另外java的語(yǔ)言的演化在有些地方背離了它的初衷。.net平臺(tái)一開(kāi)始規(guī)劃的比較好!  回復(fù)  更多評(píng)論
            

          # re: 內(nèi)部類(lèi)讓我厭惡Java 2006-06-15 23:07 CowNew開(kāi)源團(tuán)隊(duì)
          其實(shí)你完全可以這樣寫(xiě),只把內(nèi)部類(lèi)需要實(shí)現(xiàn)的方法中抽取出一個(gè)新的方法來(lái),比如:
          b.addSelectionListener( new SelectionAdapter()
          {
          public void widgetSelected( SelectionEvent e )
          {
          on_widgetSelected(e);
          }
          } );



          private on_widgetSelected(SelectionEvent e)
          {
          Runnable longJob = new Runnable()
          。。。。。。。
          }
          on_widgetSelected中的方法還可以進(jìn)一步如此抽取。java確實(shí)不適合做界面開(kāi)發(fā)這種層次的工作(雖然sun在努力改進(jìn)這一點(diǎn))。如果用好了,java的內(nèi)部類(lèi)可比.net的delegate 好用多了,內(nèi)部類(lèi)可不光光只是用來(lái)做回調(diào)這么簡(jiǎn)單的工作的。  回復(fù)  更多評(píng)論
            

          # re: 內(nèi)部類(lèi)讓我厭惡Java 2006-06-15 23:39 江南白衣
          JFunctor這種用反射實(shí)現(xiàn)函數(shù)指針的方法可以用么?  回復(fù)  更多評(píng)論
            

          # re: 內(nèi)部類(lèi)讓我厭惡Java 2006-06-15 23:46 TreeNode
          答CowNew:我自己就經(jīng)常這么寫(xiě)。不過(guò)這樣也沒(méi)多少好處,比比看C#怎么寫(xiě):
          btnInvoke.Click += BtnInvokeClick;

          再看看Java如何用四五行代碼、兩層括號(hào)實(shí)現(xiàn)同樣的功能。何苦呢?

          我倒是很想看看什么地方可以用內(nèi)部類(lèi)優(yōu)雅的解決其他辦法解決不了或很難解決的問(wèn)題。但是我還沒(méi)有看到過(guò)。倒是很多Java教科書(shū)都苦口婆心的說(shuō):學(xué)會(huì)適應(yīng)內(nèi)部類(lèi)吧,熟悉以后你會(huì)發(fā)現(xiàn)它并不是那么難。這樣的說(shuō)明本身就讓我覺(jué)得很有趣。

          回調(diào)簡(jiǎn)單嗎?我在這個(gè)BLOG上的另外一篇里面也說(shuō)到這個(gè)問(wèn)題。回調(diào)概念簡(jiǎn)單,實(shí)現(xiàn)起來(lái)其實(shí)是相當(dāng)復(fù)雜多變的。這個(gè)領(lǐng)域里C++有functor,MFC有Handle Map,ATL有Thunk,VCL有TMethod,Python和Ruby有closure。多到讓人眼花繚亂的地步。Java的實(shí)現(xiàn)是最讓我覺(jué)得難看的一種。

          答江南白衣:
          JFunctor我不了解,有機(jī)會(huì)看看。
          自己曾想過(guò)用反射,不過(guò)反射的問(wèn)題是Java并不把函數(shù)當(dāng)成對(duì)象,因此C#那樣的語(yǔ)法是行不通的。如果用方法名稱(chēng)的話就沒(méi)有編譯器檢查,同步是個(gè)問(wèn)題。
          另反射的性能也要考慮,對(duì)于一般的消息沒(méi)有問(wèn)題,如果是MouseMove或者很頻繁的Timer事件是會(huì)影響效率的。  回復(fù)  更多評(píng)論
            

          # re: 內(nèi)部類(lèi)讓我厭惡Java 2006-06-16 00:14 CowNew開(kāi)源團(tuán)隊(duì)
          我對(duì).net的delegate 理解并不是很深入,可能說(shuō)的有錯(cuò)誤。我認(rèn)為delegate只是一個(gè)方法指針而已,而java的內(nèi)部類(lèi)則是一個(gè)類(lèi),雖然可能有的時(shí)候會(huì)和宿主類(lèi)共享一些成員,但是其封裝性和可復(fù)用性更強(qiáng)。  回復(fù)  更多評(píng)論
            

          # re: 內(nèi)部類(lèi)讓我厭惡Java 2006-06-16 00:34 TreeNode
          delegate事實(shí)上不是指針而是對(duì)象,一個(gè)派生于MulticaseDelegate的對(duì)象。M$隱藏了它的細(xì)節(jié)而已。

          內(nèi)部類(lèi)的封裝和復(fù)用體現(xiàn)在哪呢?我是這么看的:如果它和外部類(lèi)需要如此緊密的耦合,以至于可以完全訪問(wèn)外部類(lèi)的所有私有字段,那么它恐怕根本就不應(yīng)該作為一個(gè)類(lèi)。不然的話,它反而只是在破壞外部類(lèi)的封裝。如果它和外部類(lèi)沒(méi)有耦合或者只有接口耦合,那么它完全應(yīng)當(dāng)拿出來(lái)作為單獨(dú)的類(lèi)。

          我不知道內(nèi)部類(lèi)復(fù)用性強(qiáng)指的是什么。內(nèi)部類(lèi)嚴(yán)重依賴(lài)于外部類(lèi)的存在,你根本沒(méi)法把它單獨(dú)拿出來(lái)復(fù)用。也許你說(shuō)的是多個(gè)方法可以共用同一個(gè)內(nèi)部類(lèi)?這不是什么值得一提的優(yōu)點(diǎn),其他語(yǔ)言的回調(diào)方法一樣是可以共用的。

          我還是希望能看到一個(gè)能證明內(nèi)部類(lèi)優(yōu)點(diǎn)的實(shí)例,空對(duì)空的感覺(jué)實(shí)在是不太好。
            回復(fù)  更多評(píng)論
            

          # re: 內(nèi)部類(lèi)讓我厭惡Java 2006-06-16 00:58 綠色使者、綠色心情
          @TreeNode
          同意這種說(shuō)法
          .net很多語(yǔ)法概念,相比java來(lái)說(shuō),都更便利、高效
          原來(lái)一直專(zhuān)注于.net,其中的attribute、delegate,property等等的用法都很喜歡的
          delegate和event配合起來(lái),還可以實(shí)現(xiàn)觀察者設(shè)計(jì)模式,在很多用到事件、消息交換等等的邏輯中,顯得非常直觀
            回復(fù)  更多評(píng)論
            

          # re: 內(nèi)部類(lèi)讓我厭惡Java 2006-06-16 09:52 Robin's Java World
          我想說(shuō)的是,首先你不應(yīng)該這么討厭內(nèi)部類(lèi),作為一種語(yǔ)法存在,肯定有一定的道理,而在編程中,我們也確實(shí)由于內(nèi)部類(lèi)而獲得了一些方便。

          或許你是從.net到j(luò)ava,所以有一些.net先入為主的感覺(jué),你的思維有些習(xí)慣.net的做法。我一開(kāi)始就做java,在做VB和VC編程時(shí)反而有些不習(xí)慣,思維上有很多方式調(diào)整不過(guò)來(lái),有些問(wèn)題自然而然的就想到了用java的思維方式來(lái)解決問(wèn)題。
            回復(fù)  更多評(píng)論
            

          # re: 內(nèi)部類(lèi)讓我厭惡Java 2006-06-16 10:10 原創(chuàng)專(zhuān)欄 開(kāi)源學(xué)習(xí)
          不要眼中只有java,c#.
          內(nèi)部類(lèi)可以模擬閉包的一些特性。

          那估計(jì)你不會(huì)接受 python,ruby,javascript這些靈活的語(yǔ)言了。

          .net的delegate只是對(duì)MVC的一種封裝,自己實(shí)現(xiàn)了個(gè)萬(wàn)能的監(jiān)聽(tīng)器,又做了優(yōu)化。
          代碼寫(xiě)起來(lái)是好了,可理解上就比較差了。 偶是看了 李建忠 翻譯的那本書(shū)才弄明白的。其實(shí).net也有很多問(wèn)題,為了讓開(kāi)發(fā)人員方面,丟掉很多面向?qū)ο蟮母拍?,?duì)有些人,比如我來(lái)說(shuō),覺(jué)得不倫不類(lèi)。

          http://www.dearbook.com.cn/book/12797
          這本書(shū)不錯(cuò)  回復(fù)  更多評(píng)論
            

          # re: 內(nèi)部類(lèi)讓我厭惡Java 2006-06-16 13:29 google
          內(nèi)部類(lèi)有時(shí)候很不錯(cuò)喲  回復(fù)  更多評(píng)論
            

          # re: 內(nèi)部類(lèi)讓我厭惡Java 2006-06-16 13:40 puke
          既然惡心到這個(gè)程度就不要用了,blogjava也清靜點(diǎn)  回復(fù)  更多評(píng)論
            

          # re: 內(nèi)部類(lèi)讓我厭惡Java 2006-06-16 15:29 steeven
          彼此彼此,avalon里面的靜態(tài)***Property也很惡心嘛,一堆一堆的.

          畢竟java出來(lái)的早,還在恐龍年代,別指望和現(xiàn)代美女比較啦.
          sun也不爭(zhēng)氣,趕快被google收購(gòu)算球,浪費(fèi)java  回復(fù)  更多評(píng)論
            

          # re: 內(nèi)部類(lèi)讓我厭惡Java 2006-06-16 18:41 CowNew開(kāi)源團(tuán)隊(duì)
          內(nèi)部類(lèi)不只是用來(lái)做回調(diào),回調(diào)也不只能用內(nèi)部類(lèi)來(lái)實(shí)現(xiàn),用內(nèi)部類(lèi)實(shí)現(xiàn)的回調(diào)如果設(shè)計(jì)合理的話也不一定會(huì)ugly。只能說(shuō)java中因?yàn)闆](méi)有delegate所以在事件監(jiān)聽(tīng)實(shí)現(xiàn)上只能用接口實(shí)現(xiàn),而很多人用的時(shí)候是直接寫(xiě)了實(shí)現(xiàn)接口的內(nèi)部類(lèi),而沒(méi)有進(jìn)行必要的抽象。內(nèi)部類(lèi)沒(méi)有錯(cuò),只是有人把它用錯(cuò)了。  回復(fù)  更多評(píng)論
            

          # re: 內(nèi)部類(lèi)讓我厭惡Java 2006-06-16 19:29 TreeNode
          還是沒(méi)看到一個(gè)實(shí)例。呵呵。

          @綠色使者、綠色心情
          基本同意你的看法。Anders做了那么多年Delphi的架構(gòu),對(duì)于語(yǔ)言的理解的確很少有人能超過(guò)他。更重要的是他是一個(gè)注重實(shí)際的人,了解這方面程序員的實(shí)際要求。不過(guò)在企業(yè)架構(gòu)這方面他也并不怎么在行,人無(wú)完人吧


          @Robin's Java World:
          你猜錯(cuò)了,我的背景是VC和Delphi。接觸.Net要比Java晚兩三年。
          我自認(rèn)對(duì)語(yǔ)言沒(méi)什么偏見(jiàn),Java的語(yǔ)言特性絕大多數(shù)也都樂(lè)意接受。只有內(nèi)部類(lèi)是例外。

          @原創(chuàng)專(zhuān)欄 開(kāi)源學(xué)習(xí):
          估計(jì)錯(cuò)誤。我很喜歡Ruby,我覺(jué)得Ruby用Block來(lái)實(shí)現(xiàn)回調(diào)的辦法很靈巧。

          理解性差何指?如果不研究實(shí)現(xiàn)細(xì)節(jié),語(yǔ)法上沒(méi)什么不好理解的。
          .Net面向?qū)ο笮詥?wèn)題,我認(rèn)為ADO.NET和ASP.NET的總體設(shè)計(jì)是有缺陷的。
          但是對(duì)delegate這個(gè)語(yǔ)法特性,我覺(jué)得沒(méi)什么問(wèn)題。


          @puke:
          內(nèi)部類(lèi)我能不用就不用,但是Java我還是要用的。OTL

          @CowNew:
          如果大家都在用看上去有問(wèn)題的辦法,那就一定存在真正的問(wèn)題。為什么那些人都要用內(nèi)部類(lèi)呢?因?yàn)闆](méi)有辦法。難道有多少個(gè)菜單/按鈕你就寫(xiě)多少個(gè)外部類(lèi)不成?如果說(shuō)有人用錯(cuò)了,那么Java也有責(zé)任,因?yàn)檫@種語(yǔ)法就是在逼著人用錯(cuò)誤的辦法做事。


          另:在google上搜索jfunctor竟然只有幾個(gè)看上去像C++的東西,關(guān)鍵字錯(cuò)誤嗎?  回復(fù)  更多評(píng)論
            

          # re: 內(nèi)部類(lèi)讓我厭惡Java 2006-06-16 19:55 江南白衣
          不好意思我完全寫(xiě)錯(cuò)單詞了,應(yīng)該是FunctionalJ(http://functionalJ.sf.net)  回復(fù)  更多評(píng)論
            

          # re: 內(nèi)部類(lèi)讓我厭惡Java 2006-06-16 20:12 寒寒
          哈哈,繼續(xù)  回復(fù)  更多評(píng)論
            

          # re: 內(nèi)部類(lèi)讓我厭惡Java 2006-06-16 20:22 TreeNode
          看了,F(xiàn)unctionalJ還是弱類(lèi)型的,引用方法名用的是字符串。
          這種辦法還是需要得到工具的支持才用得起來(lái)。
            回復(fù)  更多評(píng)論
            

          # re: 內(nèi)部類(lèi)讓我厭惡Java 2006-06-20 11:46 霉干菜
          同意 CowNew說(shuō)的
          b.addSelectionListener( new SelectionAdapter()
          {
          public void widgetSelected( SelectionEvent e )
          {
          on_widgetSelected(e);
          }
          } );

          多數(shù)用倒內(nèi)部類(lèi)的時(shí)候都是這種swing寫(xiě)法,就在listener里面新聲明一個(gè)
          內(nèi)部類(lèi)就是了,不用寫(xiě)到外面得,多看看就習(xí)慣了,哪種語(yǔ)言就算再爛用的
          多了以后看的都會(huì)習(xí)慣得  回復(fù)  更多評(píng)論
            

          # re: 內(nèi)部類(lèi)讓我厭惡Java 2006-06-22 04:17
          匿名類(lèi)確實(shí)惡心,惡心的要命. 什么還沒(méi)寫(xiě)呢,先弄四五行沒(méi)用的垃圾在代碼里。

          不過(guò),和什么“可測(cè)試”啊,“封裝”啊就別往一塊兒拉扯了。除了語(yǔ)法難看之外,它和其它任何一種closure技術(shù)概念上都一樣。想要單獨(dú)測(cè)試那塊代碼,你不會(huì)單獨(dú)做個(gè)命名外部類(lèi)先?匿名類(lèi)本來(lái)就是為了封裝一些和局部上下文緊密相關(guān)的比較簡(jiǎn)單trivial的邏輯的。


          functionalj這種東西我不看好。除了一個(gè)簡(jiǎn)單的reflection to abstract class的轉(zhuǎn)換器 (差不多的程序員都可以花半個(gè)小時(shí)自己寫(xiě)一個(gè)的),難用的curry機(jī)制,簡(jiǎn)陋的幾個(gè)初級(jí)函數(shù)式算法,啥都沒(méi)了。

          要找java的delegate實(shí)現(xiàn),google一下,有比它更好的。
          要在java里搞函數(shù)編程,思想可以借鑒,但是這么邯鄲學(xué)步不成的。
            回復(fù)  更多評(píng)論
            

          # re: 內(nèi)部類(lèi)讓我厭惡Java 2006-06-22 09:54 fantasy
          內(nèi)部類(lèi)讓我厭惡 ? .... 匿名類(lèi)好象才怎么不好玩~

          不過(guò)看Java集合類(lèi)的 Iterator 模式的實(shí)現(xiàn)....

          內(nèi)部類(lèi)還是很好的。   回復(fù)  更多評(píng)論
            

          # re: 內(nèi)部類(lèi)讓我厭惡Java 2006-06-22 18:59 TreeNode
          @豬:
          我不知道你有沒(méi)有用過(guò)Swing或SWT。為什么我討厭內(nèi)部類(lèi)還不得不用它?原因文章和回復(fù)里已經(jīng)說(shuō)過(guò)好幾次了。

          我還特意把程序代碼擺了出來(lái),似乎很多人都不看。哪位有信心說(shuō)“我能把第一段代碼改到很漂亮”嗎?那樣我就相信你。
            回復(fù)  更多評(píng)論
            

          # re: 內(nèi)部類(lèi)讓我厭惡Java 2006-07-06 21:50 auguusstt
          樓上太夸張了八,你把java的寫(xiě)成那樣,再把c#的粉飾一遍,這是不是太哲學(xué)腦瓜了!
          隨便揮揮手重構(gòu)2分鐘都不會(huì)讓人有這樣的錯(cuò)覺(jué)?。?!
          因?yàn)閖ava中沒(méi)有把函數(shù)作為一等公民,所以確實(shí)沒(méi)有C#的簡(jiǎn)潔,但還不至于像陀屎,在很多情況下也還是很漂漂的。當(dāng)然加上c#的語(yǔ)法特性會(huì)讓有些情況簡(jiǎn)單下來(lái)

          class MyRunnable3 implements Runnable{
          public void run() {
          if ( text.isDisposed() ) return;
          text.append( "\nCompleted long running task " + id );
          }
          }

          class MyRunnable2 implements Runnable{
          public void run() {
          if ( text.isDisposed() )
          return;
          text.append( "\nStart long running task "+ id );
          }
          }

          class MyRunnable implements Runnable{
          public void run(){
          id = nextId[0]++;
          display.syncExec(new MyRunnable2());
          for ( int i = 0; i < 100000; i++ ){
          if ( display.isDisposed() )
          return;
          System.out.println( "do task that takes a long time in a separate thread " + id );
          }
          if ( display.isDisposed() )
          return;

          display.syncExec(new MyRunnable3());
          done = true;
          display.wake();
          }
          }

          class MySelectionAdapter extends SelectionAdapter implements Runnable {
          public void widgetSelected( SelectionEvent e ){
          BusyIndicator.showWhile( display, this );
          }
          public void run() {
          Thread thread = new Thread( new MyRunnable());
          thread.start();
          while ( !done && !shell.isDisposed() )
          {
          if ( !display.readAndDispatch() )
          display.sleep();
          }
          }
          }

          b.addSelectionListener( new MySelectionAdapter ());
            回復(fù)  更多評(píng)論
            

          # re: 內(nèi)部類(lèi)讓我厭惡Java 2006-07-07 08:43 TreeNode
          樓上:這段代碼不是我寫(xiě)的。我不過(guò)是把Eclipse.org上面那些大牛的code摘下來(lái)一段。

          你看看你重構(gòu)出來(lái)的這幾個(gè)類(lèi)有什么特點(diǎn)?它們都只有一個(gè)方法,并且沒(méi)有自己的任何狀態(tài)。這是一個(gè)典型的反模式。一個(gè)沒(méi)有自己狀態(tài)的類(lèi)根本不應(yīng)當(dāng)是一個(gè)類(lèi)。就像Math一樣,不過(guò)是為了為那些沒(méi)主的方法找一個(gè)雜貨柜。內(nèi)部類(lèi)在這里就像一個(gè)雜貨柜。

          更新text文本本來(lái)就應(yīng)當(dāng)是窗口的責(zé)任。把它作為類(lèi)的方法是最自然最清晰的,而且可以重用。硬是塞一個(gè)內(nèi)部類(lèi)干什么?為了滿足方法簽名而已。除此以外對(duì)代碼結(jié)構(gòu)沒(méi)有一點(diǎn)好處。
            回復(fù)  更多評(píng)論
            

          # re: 內(nèi)部類(lèi)讓我厭惡Java 2006-07-07 15:28 auguusstt
          這是java沒(méi)有函數(shù)為第一公民的功能缺少,而不是匿名類(lèi)或內(nèi)部類(lèi)的問(wèn)題
          有一天您上茅廁,上完后,發(fā)現(xiàn)茅廁并沒(méi)有準(zhǔn)備廁紙,沒(méi)辦法,發(fā)現(xiàn)每個(gè)隔檔都有一個(gè)門(mén)簾,得救,但由于門(mén)簾質(zhì)地太硬,把屁股擦爛了,于是大罵門(mén)簾過(guò)于粗糙。  回復(fù)  更多評(píng)論
            

          # re: 內(nèi)部類(lèi)讓我厭惡Java 2006-07-07 21:36 TreeNode
          Java和內(nèi)部類(lèi)都不是我罵的對(duì)象。語(yǔ)法只是語(yǔ)法,語(yǔ)法是無(wú)辜的。我想罵的是這個(gè)設(shè)計(jì)語(yǔ)言的人。
            回復(fù)  更多評(píng)論
            

          # re: 內(nèi)部類(lèi)讓我厭惡Java 2006-12-01 15:57 心內(nèi)求法
          @TreeNode
          罵也沒(méi)用啊,默默承受吧,默默享受吧,呵呵  回復(fù)  更多評(píng)論
            

          # re: 內(nèi)部類(lèi)讓我厭惡Java 2007-03-31 17:57 喜來(lái)樂(lè)哈哈
          @TreeNode
          沒(méi)有萬(wàn)能的語(yǔ)言。

          記得一位大牛說(shuō)過(guò),"設(shè)計(jì)一門(mén)語(yǔ)言最難的一個(gè)問(wèn)題就是對(duì)一些優(yōu)秀的概念說(shuō)不。" Java沒(méi)有加入delegate肯定和當(dāng)時(shí)Java團(tuán)隊(duì)的設(shè)計(jì)目的有關(guān),別忘了Java最初只是作為小電器的控制語(yǔ)言而設(shè)計(jì)的,俗話說(shuō),三歲看老。都是有歷史原因的。怎樣說(shuō)Java比C#對(duì)編程語(yǔ)言的貢獻(xiàn)要大很多。有人采訪C++的創(chuàng)始人Bjarne Stroup的時(shí)候問(wèn)他對(duì)C#的意見(jiàn),Bjarne Stroup說(shuō),他不知道為什么還要開(kāi)發(fā)一門(mén)新的像C#這樣的語(yǔ)言。

          匿名類(lèi)和內(nèi)部類(lèi)是在Java1.1才增加的,當(dāng)時(shí)很多Java程序員也反感這東西,主要是不喜歡的它的句法。在此之前的Java程序員往往是這么寫(xiě)的

          class Clazz implements SelectionAdapter {
          public void widgetSelected(SelectionEvent e){
          // 你的實(shí)現(xiàn)
          }

          Clazz() {
          b.addSelectionListener(this);
          }
          }

          這樣寫(xiě), 一個(gè)不好的地方就是, Clazz也是一個(gè)SelectionAdapter.

          應(yīng)該說(shuō)當(dāng)我們習(xí)慣內(nèi)部類(lèi)以后, 內(nèi)部類(lèi)還是給我們帶來(lái)了一定的便利. 還是一句老話, 天下沒(méi)有免費(fèi)的午餐. 凡事都是有代價(jià)的.

          內(nèi)部類(lèi)相比delegate的長(zhǎng)處還是有的, 比如, 內(nèi)部類(lèi)也可以繼承自另一個(gè)類(lèi), 從而繼承了另一個(gè)類(lèi)的實(shí)現(xiàn). 這樣的例子比比皆是, 我想, delegate沒(méi)法做到吧.

          當(dāng)然喜歡delegate的人不只你一個(gè), 德國(guó)的一個(gè)教授搞過(guò)一個(gè)項(xiàng)目, 好像叫Darwin Lava, 就嘗試為Java加上delegate.

          Java也有可能在將來(lái)加入delegate.

          順帶說(shuō)一句, IBM的大牛們寫(xiě)的Java代碼, 從細(xì)了講談不上漂亮, 那幫人大多原來(lái)都是用Smalltalk的, 但是大的結(jié)構(gòu)和框架非常漂亮. 里面有太多軟件設(shè)計(jì)的大牛了.

          其實(shí)從編程語(yǔ)言本身來(lái)說(shuō)Smalltalk要比Java優(yōu)秀, 而且出現(xiàn)的時(shí)間也差不多, Java成功了, 使用Smalltalk的人卻越來(lái)越少. 這個(gè)世界很有意思的啦.

            回復(fù)  更多評(píng)論
            

          # re: 內(nèi)部類(lèi)讓我厭惡Java 2007-03-31 18:10 喜來(lái)樂(lè)哈哈
          @auguusstt
          您的廁所和門(mén)簾的比喻非常形象. 問(wèn)題是,

          下次該換個(gè)廁所呢, 還是繼續(xù)用門(mén)簾呢?
          廁所該不該提供廁紙?

          純屬搞笑, 把內(nèi)部類(lèi)比喻成門(mén)簾有點(diǎn)冤枉.  回復(fù)  更多評(píng)論
            

          # re: 內(nèi)部類(lèi)讓我厭惡Java 2010-10-18 18:13 anonymous
          @TreeNode
          看到你給的這段代碼, 懷疑這位 eclipse 中的大牛的水準(zhǔn), 最少是可讀性代碼 coding 的水準(zhǔn)  回復(fù)  更多評(píng)論
            

          # re: 內(nèi)部類(lèi)讓我厭惡Java 2013-09-10 15:35 yicone
          @auguusstt
          要罵肯定也是罵廁所居然不提供廁紙,罵門(mén)簾的心理不健全 /tx  回復(fù)  更多評(píng)論
            

          # re: 內(nèi)部類(lèi)讓我厭惡Java 2013-09-10 15:56 yicone
          @喜來(lái)樂(lè)哈哈
          很客觀了。
          另外,lz客觀地痛陳使用內(nèi)部類(lèi)的缺點(diǎn),對(duì)于已經(jīng)很客觀看待該問(wèn)題的人可能沒(méi)什么幫助,但是多數(shù)人不見(jiàn)得有那個(gè)見(jiàn)識(shí),所以還是有好處的,比如參與討論的多數(shù)人,仍然只是空空地來(lái)一句“還是有好處的”。

          “ 這個(gè)世界很有意思的啦”,贊。  回復(fù)  更多評(píng)論
            


          只有注冊(cè)用戶(hù)登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 克什克腾旗| 秦安县| 西乌珠穆沁旗| 屏东市| 喀喇| 桐庐县| 荔波县| 托里县| 长海县| 垫江县| 宁南县| 古丈县| 伊宁县| 淮安市| 嘉祥县| 江口县| 沅陵县| 长葛市| 方正县| 乌兰察布市| 梨树县| 内江市| 鄢陵县| 桓仁| 德庆县| 翁牛特旗| 日土县| 通榆县| 武胜县| 左权县| 余干县| 海原县| 淮南市| 韶关市| 明星| 呼玛县| 遂宁市| 乡城县| 文昌市| 会泽县| 武汉市|