本文是 从 C# 到 Java 系列的文章。此系列文章是为了方便从 C# 转到 Java 平台的工程师快速学习新的语言和平台。整个系列的目录请点击此处浏览。
这篇文章从基础的语言机制、语法层面来分析 C# 和 Java 的不同。部分与虚拟机(CLR | JVM)有关的不同会放在相关的另一篇里,详见总目录。
Java
中的方法和变量,无论是否为public
,都要以小写字母开头,其余与 C#
大体相当。
下面的词汇,在 Java
和 C#
中是 同义
或 近义
的:
typeof
关键词,Java 中使用 .class
,如 String.class
;C# 也可以使用对象实例的 GetType
方法,Java 中对应的是 getClass
方法。参考链接;Type
类型,Java 则为 Class
类型。参考链接。;const
(编译时常量)和 readonly
(运行时常量)在 Java
中都是 final
,同时还代表了一个类不能被继承(等同于 C#
的 sealed
)。native
关键字(声明使用 native 实现的代码)类似于 C# 中的 extern
(当声明非托管的外部方法,如动态链接库时使用)。string
与 String
:在 Java 只有后者,在 C# 中前后两者是同义词。synchronized
等同于 C# 语句块中的 lock
,以及 方法体上的特性MethodImplOptions.Synchronized
。transient
(短暂)等同于 C# 的 NonSerializableAttribute
,代表在序列化中跳过。...
操作符等同于 C# 的 params
。例如:String... args
,则 args 为一个所有参数组成的数组。Java
的值类型(Value Types)仅限于原生类型,如 int
、boolen
等。Java
不允许自定义值类型,即 Java
不存在 C# 中的 struct
。
值类型
的作用可以从以下几个方面来考虑:
struct
类型有助于减少 GC、减少内存使用、提高性能,但 Java
强大的虚拟机 JVM
通过优化部分缓解了这个问题。null
,且通过传值方式赋值。但是,由于 C# 中的值类型通过传值类型赋值造成了意外错误的可能(例如用类似类的方式在杯传递后的值类型中修改成员,试图影响到原有的值),使用值类型要警惕。
值类型在 Java
中不继承于 Object,但 C# 中却继承,这是通过自动装箱实现的。Java 的值类型可以通过装箱变为类实例,比如:
int
=> Integer
float
=> Float
byte
=> Byte
Java
具体的数据类型方面的内容,可以参考本系列文章中的另一篇:数据结构(文章末尾有目录导航)。
Java
支持泛型,但其支持的方式和 .NET
差别比较大。Java
的泛型使用 类型擦除
实现。所以,你虽然可以设置某个方法或类有一个类型参数 T
,但是你在其实现内部却无法获知与该类型的任何信息,解决方法就是使用一个补偿的 class
类型(类似于 C# 中的 Type
类型)参数手工传递数据类型。
有关 Java 泛型的类型擦除,请参考链接
C# 中的委托(delegate
)用于指向固定某个方法原型(一系列参数、某种返回值)的指针(姑且这么叫吧)。Java
中没有 delegate
的概念。
Java 中一般通过接口来实现类似委托的效果。
例如,C#
中假如有下面的定义:
// 定义委托 public delegate void onClickListener(View v); // 定义委托的实现 public void listener(View v) { // foo } // 使用委托 onClickListener = listener; onClickListener(this);
在 Java 中可以这样实现。先定义一个接口:
public interface OnClickListener { void onClick(View v); }
然后,使用这个接口来存储一个匿名类
,其中带有具体的实现,例如:
OnClickListener listener = new OnClickListener() { @Override void onClick(View v) { // 在此书写代码 } }; // 调用接口 listener.onClick(someView);
除了使用匿名类,也可以让某个命名类继承此接口:
public class TestClass implements OnClickListener { void OnClick(View v) { // 在此书写代码 } void init() { OnClickListener listener = this; // 调用接口 listener.onClick(someView); } }
C# 支持事件(event
),其内部是通过委托来实现的。Java 中没有事件的概念。
一般来说,用于事件或委托的情况,Java 会使用接口
来实现。
例如,C# 中的事件:
public event EventHandler SomeEvent; // 事件的发出者 // 事件监听 someInstance.SomeEvent += (sender, args) => { /* xxx */ };
大约等价于 Java
中的方法:
// 先定义接口 public interface SomeEventListener { void onEvent(int arg); } // 搞一个东西用来存储接口的具体实现对象 private ArrayListsomeEventListeners = new ArrayList<>(); // 在要产生事件的类中,添加一对方法用于监听或取消监听 public void addSomeEventListener(SomeEventListener listener) { someEventListeners.add(listener); } public void removeSomeEventListener(SomeEventListener listener) { someEventListeners.remove(listener); } // 触发事件 for (int i = 0; i < someEventListeners,size(); ++i) { someEventListeners.get(i).onEvent(5); } // 事件监听者,使用 Java8 中才支持的 Lambd 表达式 someInstance.addSomeEventListener(() -> { /* xxx */ }); // 事件监听者,使用 Java7 以前版本的 匿名类 someInstance.addSomeEventListener(new SomeEventListener() { @Override void onEvent(int arg) { // 代码逻辑 } });
也可以参考这篇文章。
本文是 从 C# 到 Java 系列的文章。此系列文章是为了方便从 C# 转到 Java 平台的工程师快速学习新的语言和平台。整个系列的目录请点击此处浏览。
转载请注明转自: 宁心勉学,慎思笃行 , 本文固定链接: C# 与 Java 语言机制与语法的异同
from: https://ceeji.net/blog/from-csharp-to-java-lang/