日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢(xún)
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷(xiāo)解決方案
相同中的不同:Java程序員應(yīng)該停止低看C#

【.com 5月24日外電頭條】我們建立的開(kāi)發(fā)網(wǎng)站kalistick算是個(gè)Java專(zhuān)營(yíng)店了,從一開(kāi)始的***版起,全部產(chǎn)品使用的都是Java代碼,但我們并不偏執(zhí),從2008年開(kāi)始,我們也開(kāi)始分析和使用C#。我注意到Java開(kāi)發(fā)者大都在看待C#的時(shí)候多少帶些輕蔑,就好像這是一只微軟仿造的山寨貓,蠢人和軟蛋們才會(huì)用它。我在博客中開(kāi)始清除這些觀念和誤解,展示C#的種種好處。

Java和C#的相同之處比不同處要多得多:兩種語(yǔ)言都是寫(xiě)在大括號(hào)里的,就像C和C++,類(lèi)型都是靜態(tài)、強(qiáng)類(lèi)型和顯式形態(tài),兩種語(yǔ)言都是基于類(lèi)的面向?qū)ο笳Z(yǔ)言,兩者用的都是運(yùn)行時(shí)編譯的思路,并且很好的使用了垃圾處理。

所以這篇文章里,我要重點(diǎn)談?wù)勊鼈兊南嗤c(diǎn),以及C#的巧妙之處。

推薦專(zhuān)題:Visual Studio進(jìn)化史

統(tǒng)一類(lèi)型系統(tǒng)(Unified type system)

在Java中,原始數(shù)據(jù)類(lèi)型(byte、int、bool、float、char等)和其他的類(lèi)不同,它們并不算是面向?qū)ο?,也不和引用?lèi)型共享相同的祖先類(lèi),但它們是有自己的包裝類(lèi)的,用來(lái)代表自己并且用來(lái)插入到對(duì)象結(jié)構(gòu)中(例如int使用Integer類(lèi)),這樣做可以提高性能。

在另一邊,C#的統(tǒng)一類(lèi)型系統(tǒng)卻都是從一個(gè)公用的根類(lèi)型System.Object類(lèi)中衍生而來(lái)的,即使是原始數(shù)據(jù)類(lèi)型。所有的數(shù)據(jù)都要用到對(duì)象方法(ToString、Equal、GetHashCode等),所以你會(huì)碰上像3.ToString()這樣的表達(dá)式,這種把方法混合到后綴,就帶來(lái)了dsl風(fēng)格的語(yǔ)句:

 
 
 
 
  1. TimeSpan workingTime = 7.Hours() + 30.Minutes(); 

這么做的美妙之處在于當(dāng)開(kāi)發(fā)者把數(shù)據(jù)類(lèi)型當(dāng)做值來(lái)使用時(shí),它們能夠和Java的原始類(lèi)型一樣高效,只有在想要把它們當(dāng)做對(duì)象使用時(shí),系統(tǒng)才需要使用boxing/unboxing來(lái)分配堆內(nèi)存。

顯式虛方法(Explicit virtual method)

在Java中,默認(rèn)所有的方法都是虛方法(雖然這些方法可以使用final封裝起來(lái)而不允許覆蓋),而C#則不同,如果想在C#中寫(xiě)一個(gè)虛方法,必須先要用virtual關(guān)鍵字顯式聲明一下。

有幾種原因決定了這樣的選擇,首先是性能上的考慮:虛方法都有一個(gè)懸在頭上的性能問(wèn)題,因?yàn)樗鼈儾皇钦5膬?nèi)聯(lián),需要通過(guò)vtable來(lái)進(jìn)行調(diào)用,這種做法并不直接(Sun的JVM可以?xún)?nèi)聯(lián)上最經(jīng)常調(diào)用的虛方法)。第二個(gè)也是更重要的原因就是版本問(wèn)題:C#的設(shè)計(jì)思路是向后兼容,因此不同版本類(lèi)庫(kù)中的基類(lèi)和衍生類(lèi)是可以進(jìn)化發(fā)展和保持兼容的。例如,C#能夠完全支持基類(lèi)中新加入的成員和衍生類(lèi)中的成員同名,而不會(huì)導(dǎo)致無(wú)法預(yù)料的錯(cuò)誤。***一點(diǎn)是可讀性:開(kāi)發(fā)者的編程意圖能夠非常明顯的讀出來(lái)。在Java中,如果開(kāi)發(fā)者不寫(xiě)出Override annotation的話,你不會(huì)知道他到底是不是想要重寫(xiě)這個(gè)方法。

 
 
 
 
  1. class Meme 
  2. public virtual void Spread() {} 
  3. class ThreeHundred : Meme 
  4. public override void Spread() 
  5. Console.Write("This is sparta!"); 
  6. class Dbz: Meme 
  7. // Not a method override 
  8. public void Spread() 
  9. Console.Write("It's over nine thousaaannnd!"); 

真正的泛型(True Generic)

關(guān)于泛型,Java和C#顯示出語(yǔ)法上的相似性,但真正深入理解之后你會(huì)發(fā)現(xiàn)這兩種語(yǔ)言在泛型處理上的差別很大。

Java的泛型是在編譯器中處理的,運(yùn)行時(shí)并不關(guān)心泛型類(lèi)型。Java在編譯中使用叫做類(lèi)型擦除轉(zhuǎn)換的泛型類(lèi)與方法:所有的泛型類(lèi)型都被它們的原始版本替換,并且會(huì)在客戶(hù)代碼中插入cast和類(lèi)型檢查,生成的字節(jié)代碼中并不包含任何泛型類(lèi)型或參數(shù)的引用。Java的泛型是讓你在語(yǔ)法編寫(xiě)上嘗到甜頭,但不會(huì)讓你的應(yīng)用執(zhí)行起來(lái)更有效。

而C#的泛型并不全是語(yǔ)言上的功能,它是放置在CLR(Common Language Runtime, 相當(dāng)于JVM)中的。在編譯時(shí)需要進(jìn)行泛型類(lèi)型檢查驗(yàn)證,但指定類(lèi)型會(huì)推遲到類(lèi)裝載時(shí)生成。代碼調(diào)用時(shí)的泛型是完全編譯的,而且可以假設(shè)泛型在類(lèi)型上是安全的,這被稱(chēng)為泛型的具體化。和Java不同,C#不需要插入cast或者類(lèi)型檢查。泛型類(lèi)型和方法可以通過(guò)引用(class、delegate、interface等)和值類(lèi)型(primitive type、struct、enum等)來(lái)創(chuàng)建。

C#中泛型的使用能夠帶來(lái)效率的提高(不需要cast和值類(lèi)型的boxing/unboxing),還能夠提高深層次的安全驗(yàn)證和反映能力。

 
 
 
 
  1. public void AwesomeGenericMethod (T t) where T :  new() 
  2.   T newInstance = new T (); // Causes a type creation error in Java 
  3.   T[] array = new T [0]; // Causes generic array creation error in Java 
  4.   T defaultValue = default(T); 
  5.   Type type = typeof(T); 
  6.   List  list =  new List  (); 
  7. // Generic with same name but a different number of generic type 
  8. public void AwesomeGenericMethod (T t, U u) where T :  new() 

Oracle的Java平臺(tái)總架構(gòu)師Mark Reinhold在Devoxx 2011大會(huì)上曾經(jīng)探討過(guò)給Java添加泛型的具體化問(wèn)題,但這項(xiàng)功能還沒(méi)有規(guī)劃進(jìn)Java的下一個(gè)主要版本中。

告別被檢查異常(checked exception)

Java和C#的異常檢查工作差不多一樣,二者唯一的主要區(qū)別是:Java中包含了checked exception這樣的異常。在Java里你可以在方法聲明中拋出ExceptionType,這樣做可以強(qiáng)迫任何調(diào)用方法的函數(shù)來(lái)處理異常。這個(gè)想法在紙面上說(shuō)說(shuō)很好,但實(shí)際使用中卻很煩人,而且?guī)?lái)了新問(wèn)題。

版本問(wèn)題:在新版本的方法聲明中加入一個(gè)checked exception會(huì)破壞客戶(hù)代碼,就像給一個(gè)接口添加方法一樣。比如在版本1中你創(chuàng)建了一個(gè)foo方法,聲明拋出異常A和B,在版本2中你添加了一些新功能,拋出異常D,這就是一個(gè)破壞性變化,因?yàn)楝F(xiàn)有的調(diào)用程序不能處理這個(gè)異常。

擴(kuò)展性問(wèn)題:在大規(guī)模的應(yīng)用項(xiàng)目中,相互依賴(lài)的工作是非常多的,因此拋出的異常會(huì)多的難以統(tǒng)計(jì),開(kāi)發(fā)者經(jīng)常會(huì)繞開(kāi)掉這個(gè)功能,通過(guò)拋出泛型異?;蛘呤褂每盏腸atch塊。

checked exception背后的思路是了不起的,但是尤其在大項(xiàng)目中,它有點(diǎn)太強(qiáng)迫性了。這就是C#為什么不使用checked exception的原因,其他主流語(yǔ)言也一樣:留給開(kāi)發(fā)者自己處理。

訪問(wèn)器和修改器

Java的訪問(wèn)器和修改器(getAddress、setAddress、isValid等)使用命名慣例。而在C#中,訪問(wèn)器和修改器是內(nèi)置的,自身帶有屬性,不需要再寫(xiě)getter和setter,所有的工作看上去都是直來(lái)直去,即使內(nèi)部并不是這樣的機(jī)制(許多其他語(yǔ)言也是這樣)。

 
 
 
 
  1. class Meme 
  2.   // A private backing field is created by the compiler 
  3.   public string CatchPhrase { get; set;} 
  4.   public string URL { get; set;} 
  5. Meme meme = new Meme(); 
  6. meme.CatchPhrase = "Rick roll'd"; 
  7. meme.URL = "http://www.youtube.com/watch?v=EK2tWVj6lXw"; 
  8. // Equivalent in Java 
  9. class Meme 
  10.   private String catchPhrase; 
  11.   private String url; 
  12.   public String getCatchPhrase() 
  13.   { 
  14.     return catchPhrase; 
  15.   } 
  16.   public void setCatchPhrase(String catchPhrase) 
  17.   { 
  18.     this.catchPhrase = catchPhrase; 
  19.   } 
  20.   public String getUrl() 
  21.   { 
  22.     return url; 
  23.   } 
  24.   public void setUrl(String url) 
  25.   { 
  26.     this.url = url; 
  27.   } 

當(dāng)你聲明一個(gè)屬性為自動(dòng)執(zhí)行時(shí),編譯器會(huì)創(chuàng)建一個(gè)私有的匿名域,只有這個(gè)屬性的get和set訪問(wèn)器可以讀取。這帶來(lái)了兼容性,即使是在類(lèi)的內(nèi)部這個(gè)域也總是通過(guò)訪問(wèn)器使用,這看上去干凈簡(jiǎn)練。

C#中有一類(lèi)訪問(wèn)器是Java中沒(méi)有的:索引器(indexer),它就像帶有參數(shù)的get和set。C#中的collection類(lèi)比如Dictionary(和Java Map相類(lèi)似)使用indexer。

 
 
 
 
  1. var keywordsMapping = new Dictionary(); 
  2. keywordsMapping["super"] = "base"; 
  3. keywordsMapping["boolean"] = "bool"; 
  4. Console.Write("Java => C# : {0} => {1}", "super", keywordsMapping["super"]); 

你可能會(huì)說(shuō),沒(méi)問(wèn)題吧,這不就是寫(xiě)了一個(gè)初始化函數(shù)嗎?

因?yàn)榻?jīng)常要?jiǎng)?chuàng)建對(duì)象,然后初始化,這些可以用構(gòu)造器來(lái)完成,要不然在創(chuàng)建對(duì)象之后你就要調(diào)用不同的set方法。

而對(duì)象的索引器可以在創(chuàng)建對(duì)象時(shí)就把值分配給對(duì)象的各種可以訪問(wèn)的域或?qū)傩?,這樣就不需要調(diào)用構(gòu)造器了。

 
 
 
 
  1. Meme leeroy = new Meme { 
  2.     CatchPhrase = "Leeroy Jenkins", 
  3.     URL = "http://www.youtube.com/watch?v=LkCNJRfSZBU" 
  4. }; 

在collection類(lèi)中也可以使用。

 
 
 
 
  1. List digits = new List { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; 
  2. Dictionary keywordsMapping = new Dictionary() { 
  3.     {"super", "base"}, 
  4.     {"boolean", "bool"}, 
  5.     {"import", "using"} 
  6. }; 

逐字字符串(Verbatim string)

從字符串中把字符分解出來(lái)是非常痛苦的工作,尤其是混合著不同含義的正則表達(dá)式。C#的逐字字符串允許反斜杠、制表符、引號(hào)和換行符作為字符串的一部分,不再需要轉(zhuǎn)義字符。

 
 
 
 
  1. string pattern = @"d{3}-d{3}-d{4}"; 
  2. string input = @"Multiline string 
  3.    325-532-4521"; 
  4. Regex.IsMatch(input, pattern, RegexOptions.Multiline); 

總結(jié)

通過(guò)本文我想說(shuō)C#不僅和Java很相像,而且它能夠讓開(kāi)發(fā)者的生活變得更輕松,能夠?qū)嵲诘臏p輕他們的負(fù)擔(dān)(其他語(yǔ)言也一樣),即使這是一只山寨貓,那么它做的也是相當(dāng)不錯(cuò)。

實(shí)際上Java開(kāi)發(fā)者們也做出了相似的回應(yīng),有些運(yùn)行在JVM上的腳本語(yǔ)言例如Groovy就提供了這里說(shuō)到的大多數(shù)功能,但Java本身還略顯頑固,沒(méi)有做出改變。

原文地址:

http://blog.kalistick.com/java/why-java-folks-should-stop-looking-down-on-c-differences-in-similarities/


文章題目:相同中的不同:Java程序員應(yīng)該停止低看C#
標(biāo)題鏈接:http://www.5511xx.com/article/ccddoid.html