C#与Java的比较

 

节选自《C++、Java/C#之比较》http://dev.firnow.com/course/3_program/c++/cppsl/2008520/117228.html
使用指针,由程序员根据需要分配、访问内存,程序运行时动作明确直接没有额外的处理步骤,程序的执行效率就高,但若程序员忘了释放内存或释放内存的策略不够周全,就会产生不可预知的问题,而且这种问题往往是比较严重。 
不使用指针,并不意味着内存的分配、访问与释放不须处理,只不过是这些工作由编译器生成的通用“内存管理器”完成了,因此程序执行时,必须增加额外的内存管理动作,所以执行效率相对上种方式而言有所下降。由于“内存管理器”的运作是基于业内专业人士制定的比较完善内存管理机制,因而安全程度较高。但实际上,由于内存的分配、访问、使用、释放的情况比较复杂,这种安全性并不是100
%的。也就是说安全的保证是由“另外的人”负责的,这种情况下,一旦出现问题,你无法查清问题所在,或即使你查清问题所在,也无法纠正。 
好了,关于指针,一边是100
%的效率、60%的安全性、100%的自由,一边是60%的效率、99%的安全性、100%枷锁,你选择吧。我想对于“高手”而言,自信也罢、固执也罢,选择指针是他们骨子里自由与冒险精神的决定。 
“是生,是死——这是一个值得考虑的问题。”——但不要丧失了行动的能力。 


下文引自《Java与C#的区别(语言级别)》http://wantsong.javaeye.com/blog/28769

Java与C#的区别(语言级别)
可以到这里详细了解Java与C#的区别,The C# Programming Language 
for Java Developers。 

我将其整理了下,大致列在下面: 

1.         源文件方面。C#可以在一个.cs 文件中。出现多个name sapce(命名空间,有些类似于pacakage),并定义多个类。C#包含有预处理指令。 

2.         数据类型方面。 

a)         C#定义了struct(结构),不能是抽象的,也不能被继承,是值类型的。 

b)        C#没有基本类型的概念,全部是面向对象的类型,int是Int32的简写。 

c)        在Java中const是保留字,final与C#中的const意思相同,C#中还有readonly允许运行时赋初值。 

d)        字符串比较,C#中可以用
=比较值,与Java一样用StringBuffer来减少内存开销。 

3.        运算符方面。C#增加了Checked和Unchecked以绕过编译错误。比如“把一个long付给int32 ,如果高32为零 则不会出错,否则会有溢出错误,unchekced就是告诉编译器不要去管溢出,尽你可能转化” 

4.        分支语句方面。在Java中goto是保留字。C#中switch中的case不会顺序执行,末尾必须有break或者goto关键字。 

5.        循环语句好像没有什么不同的。 

6.        访问修饰符方面。在范围放main,C#增加了internal和protected internal,前者表示只能从当前程序集内可见,即可以在编译时可Assembly的DLL或EXE,类似于JAR;后者表示对当前程序集或者从此包含类继承的类可见。Sealed相当于Java中的final关键字。 

7.        方法方面。与Java相同,只有基本类型通过值传递,其他都是传递引用。不过C#也可以以引用的方式传递基本类型,利用ref关键字。而out关键字有些类似于Oracle存储过程,与ref的区别在于:方法忽略out参数初始值,方法必须为out参数赋值。 

8.        属性方面。Getter和Setter的写法不太一样。 

9.        继承方面。C#增加了base关键字以指向父类。C#中父类方法中具有virtual关键字的才可以被子类重写,重写时还需要声明override。与抽象类相同,abstract关键字也必须被override重写。C#中的接口不能声明常量,接口的属性只是表示Getter或Setter。 

10.     事件。Java中没有(Java通过实现自定义侦听器类执行事件)。C#定义了类似于函数指针的委托来实现事件。 

11.     运算符重载。Java中无。运算符重载必须为类的静态方法,重载==,其他判等操作也必许重载。 

12.     异常方面。与Java非常相似,只是没有throws关键字,无须截获异常(当然要在程序主入口去截)。 

13.     C#增加了索引器,可以象访问数组一样访问类或结构。个人感觉就是少些几个字而已,还造成一定的困扰。 

14.     C#的Attribute要比Java的Annotation强很多。不过加上AOP后,这种动态功能Java也不错了。 

15.     在C#中也可以直接使用指针,开辟或者回收内存,只是要使用两个关键字unsafe和fixed。


引用自《c#,C++,Java比较》http://read.newbooks.com.cn/info/137063.html
1:纯对象导向语言
C# 和 java 都是纯对象导向语言,C
++ 非纯对象导向语言。

2:强制型态检查
C# 和 java 都强制进行型态检查,C
++ 则较宽松。

3:宏
C# 和 java 都不支持宏,C
++ 支持宏。


4:Template
C# 和 java 都不支持 template,C
++ 支持 template。

5:多重继承
C# 和 java 都不支持多重继承,且都支持 
interface,C++ 支持多重继承。

6:指针 
C# 和 java 都不支持指针,C
++ 支持指针。(不过,C# 允许在 unsafe code 内使用指针)

7:内存管理 
C# 和 java 都支持垃圾收集。C
++ 不支持垃圾收集。

8:虚拟机器 
C# 和 java 都需要虚拟机器,C
++ 不需要虚拟机器。Java 的执行档是中间码,叫做 bytecode,透过 java Runtime Environment(即 JRE)来执行;C# 的执行档也是中间码,叫做 managed code,透过 NGWS Runtime 来执行。除了 java,你也可以用其它程序语言(例如 Ada、Python)来作出 bytecode。除了 C#,你也可以用其它程序语言(例如 Visual Basic、C++)来作出 managed code。

9:Namespace
C# 和 java 都支持阶层式的 
namespace,但 C++ 只支持单层的 namespace。Java 的 namespace 称为 package,C# 的 namespace 就称为 namespace。Java 和 C# 都使用「.」当作 namespace 的符号,而 C++ 使用「::」。

10:Platform-Independent Type
C# 和 java 都使用 Platform
-Independent Type,C++ 的 type 会受到平台的影响。

11:使用 Wrapper 包装基本型态
C# 和 java 都支持将基本型态包装成对象,在 java 叫做 wrapper,在 C# 则是叫做 box。

12:boolean != integer
C# 和 java 都不允许把整数当布尔值用,C
++ 则允许。

13:access modifier
C# 和 java 都支持四种等级的 access modifier,包括 
publicprotectedprivatedefault/internal;C++ 只支持 publicprotectedprivate。Java 的 default(不写)指的就是只针对同一个 package 开放,正好就是 C# 的 internal

14:变量初始化
C# 和 java 都规定不可使用未初始化的变量,C
++ 则完全没有这方面的限制。Java 和 C# 的编译器都会主动帮未初始化的 field/data member 设定初始值,C++ 则不然。

15:转型
C# 和 java 都规定基本型态和 reference 型态不能互转。

16:数组边界检查
C# 和 java 都会主动进行数组边界检查,C
++ 则不然

17:呼叫 Native Code
C# 和 java 都支持呼叫 native code。Java 透过 JNI(Java Native Interface);C# 透过 PInvoke(Platform Invocation Service)

18:Metadata
C# 和 java 的中间码都包含有类别的 metadata,而 C 语言则是独立在 header file。

19:中间码指令
C# 的 IL 中间码指令和 java 的 bytecode 指令非常类似,有的甚至一样。

20:例外处理
C# 和 java 都支持 
try/catch/finally,但 C++ 只支持 try/catch。 


较细节,出处未知
c#与java的区别
1.属性: java中定义和访问均要用get和set方法,可以不成对出现。 c#中是真正的属性,定义时get和set必须同时出现,房问时用.号即可。不用get,set 
2.对象索引 就是对象数组 public Story this [int index]
3.C#中,不用任何范围修饰符时,默认的是protect,因而不能在类外被访问. 
4.因为JAVA规定,在一个文件中只能有一个public类,而且这个类的名称必须与文件名一模一样,这是一个区别 
5.在C#中,它是以Main方法来定位入口的.如果一个程序中没有一个名为Main的方法,就会出"找不到入口的错误".不要把Main写成main哟 
6.C#预定义的简单数据类型比Java多。例如,C#有unit,即无符号整数 
7.忘掉Java中的static final修饰符。在C#中,常量可以用const关键词声明 C#的设计者还增加了readonly关键词,readonly域只能通过初始化器或类的构造函数设置 
8.公用类的入口点:c#是可以对Main进行重载(java中是main),允许有int返回值和空参数的Main 
9.在Java中,switch语句只能处理整数。但C#中的switch语句不同,它还能够处理字符变量。请考虑下面用switch语句处理字符串变量的C#代码 
10.C#没有>>>移位操作符 
11.goto关键词: Java不用goto关键词。在C#中,goto允许你转到指定的标签。不过,C#以特别谨慎的态度对待goto,比如它不允许goto转入到语句块的内部。在Java中,你可以用带标签的语句加上break或continue取代C#中的goto。 
12.int[] x = 0123 }int x[] = 0123 }; 但在C#中,只有第一行代码合法,[]不能放到变量名字之后。 
13.与Java不同的是,C#允许为名称空间或者名称空间中的类指定别名: using TheConsole = System.Console; 
14.在Java中,包的名字同时也是实际存在的实体,它决定了放置.java文件的目录结构。在C#中,物理的包和逻辑的名称之间是完全分离的 .NET中包的实体称为程序集(Assembly)。每一个程序集包含一个manifest结构。manifest列举程序集所包含的文件,控制哪些类型和资源被显露到程序集之外,并把对这些类型和资源的引用映射到包含这些类型与资源的文件。程序集是自包含的,一个程序集可以放置到单一的文件之内,也可以分割成多个文件。.NET的这种封装机制解决了DLL文件所面临的问题,即臭名昭著的DLL Hell问题。 
15.在Java中,java.lang包是默认的包,C#中不存在默认的包 
16.C#中的访问修饰符与Java中的基本对应,但多出了一个internal。简而言之,C#有5种类型的可访问性,如下所示: public:成员可以从任何代码访问。 protected:成员只能从派生类访问。 internal:成员只能从同一程序集的内部访问。 protected internal:成员只能从同一程序集内的派生类访问。 private:成员只能在当前类的内部访问。 
17.由于C#中不存在final关键词,如果想要某个类不再被派生,你可以使用sealed关键词 
18.与Java不同,C#中的接口不能包含域(Field)。 另外还要注意,在C#中,接口内的所有方法默认都是公用方法。在Java中,方法声明可以带有public修饰符(即使这并非必要),但在C#中,显式为接口的方法指定public修饰符是非法的。例如,下面的C#接口将产生一个编译错误。 
19.C#中的is操作符与Java中的instanceof操作符一样,两者都可以用来测试某个对象的实例是否属于特定的类型。在Java中没有与C#中的as操作符等价的操作符。as操作符与is操作符非常相似,但它更富有“进取心”:如果类型正确的话,as操作符会尝试把被测试的对象引用转换成目标类型;否则,它把变量引用设置成null。 
20.C#仍旧保留了C++的内存手工管理方法,它适合在速度极端重要的场合使用,而在Java中这是不允许的
21.在C#中,所有的异常都从一个名为Exception的类派生 
22.枚举器即enum类型(java无),把它作为一个变量值的类型使用,从而把变量可能的取值范围限制为枚举器中出现的值。 
23.结构(Struct)与类很相似,而结构是一种值类型,它存储在栈中或者是嵌入式的,结构可以实现接口,可以象类一样拥有成员,但结构不支持继承 
24.属性声明语法的第一部分与域声明很相似,第二部分包括一个set过程和/或一个get过程 
25.传值方式: 在java中简单数据类型的值传参时,都以传值方式; 在c#中如果加ref则会以引用的方式传值(方法内部改变该参数,则外部变量一起跟着变); 加out与ref基本相同,但out不要求参数一定要初始化. 
26.c#保留了指针。unsafe 
27.代理:代理(delegate)可以看作C++或者其他语言中的函数指针 代理用来封装可调用方法。你可以在类里面编写方法并在该方法上创建代理,此后这个代理就可以被传递到第二个方法。这样,第二个方法就可以调用第一个方法。 代理是从公共基类System.Delegate派生的引用类型。定义和使用代理包括三个步骤:声明,创建实例,调用。代理用delegate声明语法声明。


更细致的
C#与JAVA之比较(作者Yesky)
C#、Java之比较 
  很多人说C#是微软用来和Java抗衡的武器,因为二者在很大程度上有着惊人的相似 
,尽管如此,两者不同的地方也很多,所谓“于细微处见差异”。那么两者的相似和区 
别都在什么地方呢?我们从今天开始,会从各个角度来对比C#和Java的特点,希望能对 
正在学习、使用C#的朋友有所帮助。 
1、C#和.NET平台的概貌 
  2000年6月,微软发布C#语言和.NET平台。C#语言是一种强类型的,面向对象的语言 
,它具有语法简单、表达力强的特点,而.NET平台则是构成微软的“.NET计划”的基石 
。 
  .NET平台的核心包括两方面,一方面就是著名的通用语言运行机(Common Language 
Runtime),虽然这个名词起得晦涩了点,不过大家可以拿它和Java的虚拟机来作比较, 
二者完成的任务大致相同;另一方面就是一大堆通用函数库,这些库函数可以被多种语 
言调用,并且通过编译都产生一种共同的中间语言(Intermediate Language),这种语 
言也可以拿Java的字节码来类比,虽然完成的方式有些不一样。 
2、C#和Java 
  下面简单地把C#和Java的相似处列出来,虽然在这里我们重点讨论的是C#和Java的 
不同点,但是了解一下二者的相同之处也是很有必要的。 
  二者都编译成跨平台的、跨语言的代码,并且代码只能在一个受控制的环境中运行 

  自动回收垃圾内存,并且消除了指针(在C#中可以使用指针,不过必须注明unsafe 
关键字) 
  都不需要头文件,所有的代码都被“包(package)”限制在某个范围内,并且因为没 
有头文件,所以消除了类定义的循环依赖 
  所有的类都是从对象派生出来,并且必须使用New关键字分配内存 
  用对象加锁的方式来支持多线程 
  都具有接口(
interface)的概念 
内部类 
  继承类的时候不会以某种特定的访问权限来继承; 
  没有全局函数或者常量,一切必须属于类; 
  数组或者字符串都自带长度计算和边界检查; 
  只使用“.”操作符,没有“
->”和“::”; 
  “
null”、“boolean”和“bool”成为了关键字; 
  任何变量均在使用前进行初始化; 
  不能使用整数来返回到if条件语句中,必须使用布尔值; 
  “Try”模块后可以有“
finally” ;

3. 属性(Property) 
  属性的概念对大家来说应该是很熟悉的,类成员函数可以自由地访问本类中的任何 
属性成员。不过若要从一个类中去访问另一个类中的属性,那就比较麻烦了,所以很多 
时候我们使用Getxxx和Setxxx方法,这样看起来显得极不自然,比如用Java或者C
++,代 
码是这样的: 
  foo.setSize (getSize () 
+ 1); 
  label.getFont().setBold (
true); 
  但是,在C#中,这样的方法被“属性化”了。同样的代码,在C#就变成了: 
  foo.size
++
  label.font.bold 
= true
  可以看出来,C#显然更容易阅读和理解。我们从这个“属性方法”的子程序代码中 
,也可以看到类似情况: 
Java
/C++
public int getSize() 

  
return size; 
}
 
public void setSize (int value) 

  size 
= value; 
}
 
C#: 
public int Size 

 
get{return size;} 
 
set{size = value;} 
}
 
  为了区分这种属性化的方法和类的属性成员,在C#中把属性成员称作“域(field)” 
,而“属性”则成为这种“属性化的方法”专用的名词。顺便说一句,其实这样的属性 
化方法在VB和DELPHI中是经常碰到的,在VB中它也就叫属性。 
  另外,在C#中Get和Set必须成对出现,一种属性不能只有Get而没有Set(在Java和 
C
++中就可以只有Get或者只有Set),C#中这样做的好处在于便于维护,假如要对某种属 
性进行修改,就会同时注意Get和Set方法,同时修改,不会改了这个忘了那个。 
4、对象索引机制(Indexer) 
  C#中引入了对象索引机制。说得明白点,对象索引其实就是对象数组。这里和上一 
节中的属性联系起来讲一下,属性需要隐藏Get和Set方法,而在索引机制中,各个对象 
的Get或者Set方法是暴露出来的。比如下面的例子就比较清楚地说明了这一点。 
public class Skyscraper 

 Story[] stories; 
 
public Story this [int index] 
  
get 
   
return stories [index]; 
  }
 
  
set 
   
if (value != null

    stories [index] 
= value; 
   }
 
  }
 
 }
 
 
}


5. 指代(Delegate) 
  指代这个玩意很特别,它有点象指针,但又不完全是,不过大家还是可以把它理解 
为一种类型安全的、面向对象的指针。(什么是类型安全和面向对象就不用讲了吧?) 
顺便提一句,有很多书上把Delegate翻译成代理,我觉得这样翻不够确切,翻译成“指 
代”更恰当些,道理上吻合,并且还符合它的本来意思——微软本来就是用Delegate来 
“取代指针”,所以叫“指代”,呵呵。 
  说起指代,也许至今Sun还会对它愤愤不已,为什么呢?因为在Sun的标准Java中是 
没有这个东西的,它是微软99年发布的MSVJ
++6添加的“新特性”。为此,两家公司吵得 
不亦乐乎,并且还专门在网上写了大量文章互相攻击,有兴趣的朋友可以去看看(只有 
英文版)。 
http:
//www.Javasoft.com/docs/white/delegates.html 
http://msdn.microsoft.com/visualj/technical/articles/delegates/truth.asp 
  话归正传,指代有什么特点呢?一个明显的特点就是它具有了指针的行为,就好象 
从Java又倒回到了C
++。在C#中,指代完成的功能大概和C++里面的指针,以及Java中的 
接口相当。但是,指代比起C
++的“正宗指针”来又要高明一些,因为它可以同时拥有多 
个方法,相当于C
++里面的指针能同时指向多个函数,并且是类型安全的,这一点体现了 
它的“对象”特性;而比起Java的接口来,指代高明的地方在于它能可以不经过内部类 
就调用函数,或者用少量代码就能调用多种函数,这一点体现了它的“指针”特性。呵 
呵,很有“波粒二象性”的味道吧?指代最重要的应用在于对于事件的处理,下一节我 
们将重点介绍。

6、事件(Event) 
  C#对事件是直接支持的(这个特点也是MSVJ所具有的)。当前很多主流程序语言处 
理事件的方式各不相同,Delphi采用的是函数指针(这在Delphi中的术语是“closure” 
)、Java用改编类来实现、VC用WindowsAPI的消息系统,而C#则直接使用delegate和ev 
ent关键字来解决这个问题。下面让我们来看一个例子,例子中会给大家举出声明、调用 
和处理事件的全过程。 
//首先是指代的声明,它定义了唤醒某个函数的事件信号 
public delegate void ScoreChangeEventHandler (int newScore, ref bool cancel) 

//定义一个产生事件的类 
public class Game 

 
// 注意这里使用了event关键字 
 public event ScoreChangeEventHandler ScoreChange; 
  
int score; 
  
// Score 属性 
  public int Score 
  

   
get 
    
return score; 
   }
 
   
set 
    
if (score != value) 
    

     
bool cancel = false
     ScoreChange (value, 
ref cancel); 
     
if (! cancel) 
     score 
= value; 
    }
 
  }
 
}
 
// 处理事件的类 
public class Referee 

 
public Referee (Game game) 
 

  
// 裁判负责调整比赛中的分数变化 
  game.ScoreChange += new ScoreChangeEventHandler (game_ScoreChange); 
 }
 
 
// 注意这里的函数是怎样和ScoreChangeEventHandler的信号对上号的 
 private void game_ScoreChange (int newScore, ref bool cancel) 
 

  
if (newScore < 100
   System.Console.WriteLine (
"Good Score"); 
  
else 
  

   cancel 
= true
   System.Console.WriteLine (
"No Score can be that high!"); 
  }
 
 }
 
}
 
// 主函数类,用于测试上述特性 
public class GameTest 

 
public static void Main () 
 

  Game game 
= new Game (); 
  Referee referee 
= new Referee (game); 
  game.Score 
= 70
  game.Score 
= 110
 }
 
}
 
  在主函数中,我们创建了一个game对象和一个裁判对象,然后我们通过改变比赛分 
数,来观察裁判对此会有什么响应。 
  请注意,我们的这个系统中,Game对象是感觉不到裁判对象的存在的,Game对象在 
这里只负责产生事件,至于有谁会来倾听这个事件,并为之作出反应,Game对象是不作 
任何表态的。 
  我们注意到,在裁判类的Referee函数中,Game.ScoreChange后面使用了
+=-=操作 
符,这是什么意思呢?回到我们定义ScoreChange的地方,可以发现ScoreChange是用ev 
ent关键字修饰的,那么这里的意思就很明白了:ScoreChange是一个事件,而事件被触 
发后需要相应的事件处理机制,
+=/-=就是为这个事件增加/移除相对应的事件处理程序 
,而且,并不是一个事件只能对应一个处理程序,我们还可以用这两个操作符为同一事 
件增加
/移除数个事件处理程序。怎么样?很方便吧! 
  在实际应用中,和我们上面讲的(竞赛
-裁判)机制很相近的系统就是图形用户界面 
系统了。Game对象可以看作是图形界面上的小零件,而得分事件就相当于用户输入事件 
,而裁判就相当于相应的应用程序,用于处理用户输入。 
  指代机制的首次亮相是在MSVJ里,它是由Anders Hejlsberg发明的,现在又用到了 
C#中。指代用在Java语言中的后果,则直接导致了微软和Sun之间对类和指针的关系产生 
了大量的争论和探讨。有意思的是,Java的发明者James Gosling非常幽默地称呼指代的 
发明者Anders Hejlsberg为“‘函数指针’先生”,因为Anders Hejlsberg总是想方设 
法地把指针变相地往各种语言中放;不过有人在看了Java中大量地使用了各种类后,也 
戏称Java的发明者James Gosling为“‘全都是类’先生”,真是其中滋味,尽在不言中 
啊。

posted on 2010-09-19 11:44 八零未成年 阅读(1013) 评论(1)  编辑 收藏 引用 所属分类: C++DP & OO

评论

# re: C#与Java的比较 2015-02-14 03:00 solq

研究得很细  回复  更多评论   


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


<2024年4月>
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011

导航

统计

常用链接

留言簿

随笔分类

随笔档案

搜索

最新评论

阅读排行榜

评论排行榜