C#和Java作为独立发展的两种程序设计语言,其实有很多相似的地方;当然,其中还是有一些不同的点的;假如一个熟悉C#但不清楚java的程序员去写java程序,其实没有多大困难,只是如果清楚了C#和Java中的一些不同的点,应该可以更快的从C#过渡到Java的。
本文主要是列举了笔者在学习Java过程中和C#比较的一些异同。希望可以给同样从C#转向Java的开发人员提供一些信息。
IBM的开发者网站提供了一个不错的java入门系列,对于初学者来说不妨一看。
https://www.ibm.com/developerworks/cn/java/intro-to-java-course/index.html
另外wiki中其实也已经有一些详实的对于java和C#的比较,可以参看
https://en.wikipedia.org/wiki/Comparison_of_C_Sharp_and_Java
Namespace(C#) vs Package(java)
C#和java都是面向对象的编程语言;在源代码的层面,C#的组织结构是命名空间=>类=>方法/变量/常量,而Java稍有不同,用package代替了C#中的namespace,但是所起的作用是类似的。
同样的,当一个namespace或者package中需要用到其他的命名空间下的类时, C#通过using指定上下文可以访问的namespace,而Java通过import导入package来达到同样的目的。
代码示例
Java
packagehello.world;import java.lang.*;public classHelloWorld {private static final int CONSTINT = 100;privateString variable;public voidmethod(){}public static voidmain(String[] args) {
System.out.println("Hello World!");
}
}
C#
usingSystem;namespaceHello.World
{public classHelloWorld
{private const int CONSTINT = 100;private stringvariable;public voidMehtod() { }static void Main(string[] args)
{
System.Console.WriteLine("Hello World!");
}
}
}
访问限定修饰符
C#和Java中,对类型、方法、变量等都可以指定访问限制修饰,来达到封装、继承等等目的。
Java中的访问限定修饰符的各个访问限定如下,这个包就是package
public
可由任何类调用
protected
仅能由同一个包中的类或任何子类调用
无修饰符
由同一个包内的任何类调用
private
仅能由定义它的类调用
C#中的访问限定描述如下,这个里面有一个程序集assembly的概念,和namespace不太一样。
public
可由任何类调用
protected
仅可以被所定义的类型或者其嵌套类型或者其派生类型调用
internal
仅可以被程序集中的类访问
protected internal
仅可以被所定义类型、派生类型以及任何定义在同一程序集中的类访问
private
仅能由定义它的类调用
无修饰符
同internal修饰符
属性
C#有Property的概念,通过简单的get/set就可以定义public属性;C#中的属性本质上就是两个方法,一个setter,一个getter, 只是C#在语言层面提供了友好的支持。
Java就没有这种语言层面的支持,如果想实现同样的功能,必须首先定义变量,然后定义一个Set方法,一个get方法;当然现在很多IDE插件可以帮助做第二步自动生成这两个方法。
示例如下
C#
namespaceHello.World
{public classPerson
{public int Age { get; set; }
}
}
Java
packagehello.world;public classPerson {private intage;public intgetAge() {returnage;
}public void setAge(intage) {this.age =age;
}
}
Foreach
带有迭代器的类型,都可以使用foreach语法来比较优雅的替换for循环。Java和C#的语法略有不同。
代码示例如下
C#
namespaceHello.World
{public classHelloWorld
{static void Main(string[] args)
{foreach (var str inargs)
{
System.Console.WriteLine("Hello World!" +str);
}
}
}
}
Java
packagehello.world;public classHelloWorld {public static voidmain(String[] args) {for(String str : args){
System.out.println("Hello World!" +str);
}
}
}
这里顺便提一下的是,Java中没有类似C#中万能类型var这种定义方式了,所有变量必须要显示的写清楚定义类型,这个可能会给写惯了C#的同学带来点不适应。
集合
相比于C#, Java内置的集合功能稍显薄弱,在使用便捷上不如C#。
Java中只有基本的数组类型支持原语类型(int/long/boolean/char etc), 而其他的集合比如List,Map等只能包含对象类型。而在C#中,所有集合都可以同时支持值类型和引用类型。
C#中,对集合中的元素操作可以使用lamda表达式以及linq的方式,对集合中的每个元素进行操作,选择,过滤,转换等等,非常方便。而在Java中,直到java 1.8之后,才支持在集合类型后面,借助类似lamda表达式的方式访问操作集合中的每个元素,并且内置的功能方法非常少。
一些代码示例如下,可以看到,使用C#代码精简不少,并且有不少内置方法可用(如下代码不考虑性能开销,只是纯粹展示一下C#中对集合操作的各种可能性)。
C#
usingSystem.Collections.Generic;usingSystem.Linq;namespaceHello.World
{public classHelloWorld
{static void Main(string[] args)
{var persons = new List();
persons.Add(new Person() { Age = 21});
persons.Add(new Person() { Age = 19});
persons.Where(p=> p.Age > 20).Select(p => p.Age).ToList().ForEach(p => System.Console.WriteLine("Age-{0}", p));
}
}
}
Java
packagehello.world;importjava.util.ArrayList;importjava.util.List;public classHelloWorld {public static voidmain(String[] args) {
List persons = new ArrayList();
Person p1= newPerson();
p1.setAge(21);
persons.add(p1);
Person p2= newPerson();
p2.setAge(19);
persons.add(p2);
persons.forEach(p->{if (p.getAge() > 20) {
System.out.println(String.format("Age-%s", p.getAge()));
}
});
}
}
继承和多态
C#和Java都很好的支持面向对象编程,只是在具体编码上稍微有些不一样。
主要在两点,子类构造的时候对父类的构造;重写。
构造的传值这块,C#把调用父类的构造方法移出到函数外面调用,以示区别,个人觉得这个比较人性化。
重写这里,Java父类中的任何方法都可以被重写,只要加上@Override的注解;而C#中需要在父类可能被重写的方法加上virtual关键字,后续子类重写时,在使用关键字override;感觉C#更加严谨一些。
另外,C#和Java中限定一个类不能被继承的关键字也不一样,C#使用sealed,Java是final。
代码示例如下
C#
namespaceHello.World
{public classPerson
{public virtual voiddoAction()
{
System.Console.WriteLine("Person");
}
}public classEmployee : Person
{publicEmployee()
:base()
{
}public override voiddoAction()
{
System.Console.WriteLine("Employee");
}
}
}namespaceHello.World
{public classHelloWorld
{static void Main(string[] args)
{
Person p= newEmployee();
p.doAction();
}
}
}
Java
packagehello.world;public classPerson {public voiddoAction(){
System.out.println("Person");
}
}public class Employee extendsPerson{publicEmployee(){super();
}
@Overridepublic voiddoAction(){
System.out.println("Employee");
}
}public classHelloWorld {public static voidmain(String[] args) {
Person p= newEmployee();
p.doAction();
}
}