首页 > 代码库 > C#和Java之比较(语法篇)

C#和Java之比较(语法篇)

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

package hello.world; 
import java.lang.*;

public class HelloWorld {
    private static final int CONSTINT = 100;
    private String variable;
    public void method(){}
    public static void main(String[] args) {
        System.out.println("Hello World!");
    }
}

 

C#

using System;
namespace Hello.World
{ 
   public class HelloWorld
    {
        private const int CONSTINT = 100;
        private string variable;
        public void Mehtod() { }
        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#

namespace Hello.World
{
    public class Person
    {
        public int Age { get; set; }
    }
}

 

Java

package hello.world;

public class Person {
    
    private int age;

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

 

Foreach

带有迭代器的类型,都可以使用foreach语法来比较优雅的替换for循环。Java和C#的语法略有不同。

代码示例如下

C#

namespace Hello.World
{ 
   public class HelloWorld
    {
        static void Main(string[] args)
        {
            foreach (var str in args) 
            {
                System.Console.WriteLine("Hello World!" + str);
            } 
        }
    }
}

 

Java

package hello.world; 

public class HelloWorld {
public static void main(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#

using System.Collections.Generic;
using System.Linq;
namespace Hello.World
{ 
   public class HelloWorld
    {
        static void Main(string[] args)
        {
            var persons = new List<Person>();
            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

package hello.world;

import java.util.ArrayList;
import java.util.List;

public class HelloWorld {

    public static void main(String[] args) {

        List<Person> persons = new ArrayList<Person>();
        Person p1 = new Person();
        p1.setAge(21);
        persons.add(p1);
        Person p2 = new Person();
        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#

namespace Hello.World
{
    public class Person
    {
        public virtual void doAction() 
        {
            System.Console.WriteLine("Person");
        }
    }

    public class Employee : Person
    {
        public Employee()
            : base()
        { 
        }

        public override void doAction()
        {
            System.Console.WriteLine("Employee");
        }
    }
}


namespace Hello.World
{ 
   public class HelloWorld
    {
        static void Main(string[] args)
        {
            Person p = new Employee();
            p.doAction();
        }
    }
}

 

Java

package hello.world;

public class Person {
        
    public void doAction(){
        System.out.println("Person");
    }

}

public class Employee extends Person{
    
    public Employee(){
        super();
    }
    
    @Override
    public void doAction(){
        System.out.println("Employee");
    }

}

    public class HelloWorld {
    
        public static void main(String[] args) {
    
            Person p = new Employee();
            p.doAction();
        }
}

 

C#和Java之比较(语法篇)