1. 静态构造函数
C#中有静态构造函数, Java中没有静态构造函数。其实Java中有一个类似静态构造函数的东东,称作静态初始化,或者静态代码块,可以通过这样的代码实现相同的功能:
但是Java中静态代码块和C#静态构造函数还是不一样的。C#中静态构造函数在其他静态成员初始化后再执行,而java中静态代码块和其他静态成员谁在先谁就先执行。
1 class Parent{ 2 public static StaticVariable staticVariable = new StaticVariable("Parent - Static Variable1"); 3 public StaticVariable inStaticVariable = new StaticVariable("Parent - Instant Variable1"); 4 5 static 6 { 7 System.out.println("Parent - Static block/constructor"); 8 System.out.println(staticVariable == null); 9 //System.out.println(staticVariable2 == null); not working because staticVariable2 is not defined 10 staticVariable2 = new StaticVariable("Parent - Static Variable2 - Static block"); 11 } 12 13 { 14 System.out.println("Parent - Initializer Block"); 15 } 16 17 public static StaticVariable staticVariable2 = new StaticVariable("Parent - Static Variable2"); 18 public StaticVariable inStaticVariable2 = new StaticVariable("Parent - Instant Variable2"); 19 20 public Parent() 21 { 22 System.out.println("Parent - Instance Constructor"); 23 } 24 }
1 class StaticDemo 2 { 3 static int i = 1; 4 5 static StaticDemo() 6 { 7 Console.WriteLine(i); 8 Console.WriteLine(j); 9 } 10 11 public static void Execute() 12 { 13 } 14 15 static int j = 1; 16 }
2常量
Java中声明(实例/类)常量使用关键词(final/static final)。C#中声明(实例/类)常量使用关键词(readonly/const 或者 readonly static).
C#中必须使用类名去访问类层级的变量。Java中可以使用实例去访问类层级的变量,但是编译时会有警告。
Java Code and C# Code
1 class ParentDef{ 2 public static final String STATICVALUE_STRING="Parent Static Variable"; 3 public String valueString="Parent Instant Variable"; 4 } 5 6 class ChildRef extends ParentDef{ 7 public static final String STATICVALUE_STRING="Child Static Variable"; 8 public String valueString="Child Instant Variable"; 9 } 10 11 public class BasicDemo { 12 public static void main(String[] args) { 13 //Child child = new Child(); 14 15 ParentDef pdf = new ParentDef(); 16 ParentDef pcdf = new ChildRef(); 17 ChildRef cdf = new ChildRef(); 18 System.out.println("V1"); 19 System.out.println(pdf.STATICVALUE_STRING); 20 System.out.println(pdf.valueString); 21 22 System.out.println("V2"); 23 System.out.println(pcdf.STATICVALUE_STRING); 24 System.out.println(pcdf.valueString); 25 26 System.out.println("V3"); 27 System.out.println(cdf.STATICVALUE_STRING); 28 System.out.println(cdf.valueString); 29 30 } 31 32 }
1 class InheritenceDemo 2 { 3 public static void Execute() 4 { 5 ParentDef pdf = new ParentDef(); 6 ParentDef pc = new ChildDef(); 7 ChildDef cdf = new ChildDef(); 8 9 10 Console.WriteLine("V1"); 11 Console.WriteLine(pdf.value); 12 13 14 Console.WriteLine("V2"); 15 Console.WriteLine(pc.value); 16 17 Console.WriteLine("V3"); 18 Console.WriteLine(cdf.value); 19 Console.WriteLine(cdf.READONLYSTRING); 20 21 } 22 } 23 24 class ParentDef 25 { 26 public const string Const_String = "Parent Const Varialbe"; 27 public static string STATICVALUE_STRING = "Parent Static Variable"; 28 public string value = "Parent Instant Variable"; 29 } 30 31 class ChildDef:ParentDef 32 { 33 public readonly string READONLYSTRING="Child readonly variable"; 34 public readonly static string READONLYSTATICSTRING = "Child readonly static variable"; 35 public static string STATICVALUE_STRING = "Child Static Variable"; 36 public string value = "Child Instant Variable"; 37 38 public ChildDef() 39 { 40 READONLYSTRING = "NEW Child readonly variable"; 41 //READONLYSTATICSTRING = "NEW Child readonly static variable"; ERROR as satatic readonly variable can not be reassianged in instant constructor 42 } 43 }
3参数传递
C#中有ref关键词用来按引用传递参数。Java则没有,无法真正按引用传递参数。Java总是采用按值调用。方法得到的是所有参数值的一个拷贝,特别的,方法不能修改传递给它的任何参数变量的内容。
(1):“在Java里面参数传递都是按值传递”这句话的意思是:按值传递是传递的值的拷贝,按引用传递其实传递的是引用的地址值,所以统称按值传递。
(2):在Java里面只有基本类型和按照下面这种定义方式的String是按值传递,其它的都是按引用传递。就是直接使用双引号定义字符串方式:String str = “Java”;
C# code
class RefExample { static void Method(ref int i) { i = 44; } static void Main() { int val = 0; Method(ref val); // val is now 44 } }
4虚函数
C#中普通成员函数加上virtual关键字就成为虚函数.
Java中其实没有虚函数的概念,它的普通函数就相当于C#的虚函数,动态绑定是Java的默认行为。如果Java中不希望某个函数具有虚函数特性,可以加上final关键字变成非虚函数.
5空接口
在Java和C#中空接口都是合法的。都可以定义空接口。空接口还是很奇怪的存在,个人的理解是空接口仅做标记使用,无其他含义。如果你只需要在运行时区分这些类型,一个更佳的解决方式是使用自定义属性(attribute)。如果你希望在编译时区分这些类型,就只好使用空接口了。 而JDK中定义的很多空接口很多都是前者,个人认为这是一种不良的设计,反观CLR,我们则很难找到一个空接口。 所以.Net的设计在这点上来看跟合理点。
JDK中定义的空接口
java.io.Serializable;
java.lang.Cloneable
java.lang.annotation.Annotation;
java.rmi.Remote;
java.util.RandomAccess;
6Delegate 和 Event
Java欠缺C#中的事件功能,java中没有delegate这种用法。在java中实现事件功能其实就是通过实现EventListener接口实现观察者模式。C#则是通过EventHandler的实例来实现事件的功能。
class EventDemo { public static void RunDemo() { SMS sms = new SMS(); SmsReceiver r = new SmsReceiver(sms); sms.SendSms("188288388","Hello world"); } } public class SMS { public EventHandler<SmsEventArgs> SmsEvent = (o, e) => { }; public EventHandler SmsEvent2; protected virtual void OnSmsEvent(SmsEventArgs e) { //EventHandler<SmsEventArgs> handler = this.SmsEvent; //if (handler != null) //{ // handler(this, e); //} this.SmsEvent(this, e); } protected virtual void OnSmsEvent2() { EventHandler handler = this.SmsEvent2; if (handler != null) { handler(this,null); } } public void SendSms(string phone, string message) { SmsEventArgs e = new SmsEventArgs(); e.Message = message; e.ToPhone = phone; OnSmsEvent(e); } } public class SmsEventArgs:EventArgs { public string ToPhone { get; set; } public string Message { get; set; } } public class SmsReceiver { public SmsReceiver(SMS sms) { sms.SmsEvent += new EventHandler<SmsEventArgs>(sms_SmsEvent); } void sms_SmsEvent(object sender, SmsEventArgs e) { Console.WriteLine(e.ToPhone + ":" + e.Message); } }
public class AskEvent extends EventObject { private static final long serialVersionUID = 1L; private Object Evnetsource; private String name; public Object getEvnetsource() { return Evnetsource; } public String getName() { return name; } public AskEvent(Object source,String name) { super(source); Evnetsource = source; this.name = name; } } public interface Listener extends EventListener { public void listen(AskEvent ae); } public class Ask { private Listener l ; private List<String> names = new ArrayList<String>(); public void addListener(Listener l){ this.l = l; } public void addName(String name){ names.add(name); } public void setFlag(boolean flag){ if(flag){ if(names.size()==0) System.out.println("Input Name!!!"); for(int i = 0;i<names.size();i++){ l.listen(new AskEvent(this,names.get(i))); } names.clear(); } } } public class EventTest { public static void main(String[] args) { System.out.println("START"); Scanner scan = new Scanner(System.in); Ask ask = new Ask(); ask.addListener(new Listener(){ public void listen(AskEvent ae) { if(ae.getName().equals("a")) System.out.println(ae.getName() + "good man"); else System.out.println(ae.getName() + "bad man"); } }); while(true){ System.out.print("input name:"); final String name = scan.nextLine(); if(name.equals("exit")) break; if(name.equals("print")) { ask.setFlag(true); continue; } ask.addName(name); } System.out.println("OVER"); } }
7Exception
Java中Checked Exception是必须要被try_catch捕获,编译器会强制检查的。在C#中是否捕获Exception并不是由编译器强制的。