C#和Java在访问静态变量和方法方面的差异
本文关键字:方面 方法 静态 Java 访问 变量 | 更新日期: 2023-09-27 18:19:43
在Java中,静态方法和变量可以通过对象引用访问,就像下面的程序一样,它运行得非常好:
//StaticDemo.java
class StaticVerifier{
private int a,b;
public StaticVerifier(int a,int b){
this.a = a;
this.b = b;
System.out.println("Values are "+this.a+" "+this.b);
}
public static void takeAway(){
System.out.println("This is a static method...");
}
}
public class StaticDemo{
public static void main(String[] args){
StaticVerifier sv = new StaticVerifier(3,4);
sv.takeAway();
}
}
但当我尝试在C#中转换相同的代码时,它不允许对象访问静态方法,并在编译时出错。请参阅下面的代码和相关错误:
//StaticDemo.cs
using System;
public class StaticVerifier{
private int a,b;
public StaticVerifier(int a,int b){
this.a = a;
this.b = b;
Console.WriteLine("Values are "+this.a+" "+this.b);
}
public static void takeAway(){
Console.WriteLine("This is a static method...");
}
}
public class StaticDemo{
public static void Main(string[] args){
StaticVerifier sv = new StaticVerifier(3,4);
sv.takeAway(); // here, unable to access static methods, but can use classname rather than objectname !
}
}
Errors:
StaticDemo.cs(17,3): error CS0176: Member 'StaticVerifier.takeAway()' cannot be
accessed with an instance reference; qualify it with a type name instead
StaticDemo.cs(10,21): (Location of symbol related to previous error)
有人能告诉我为什么C#和Java没有这种可访问性,尽管它们都是基于面向对象的范式的吗?(我的主要意思是"为什么供应商会这么做?")
通过实例引用访问静态成员是Java的一个怪癖,与面向对象无关。
正确的方法(在C#和Java中)是通过类引用StaticVerifier.takeAway()
访问takeAway
。Java允许使用实例引用,但这也是一个怪癖,我相信只有Java才有这个怪癖。
Java的这种怪癖可能非常令人困惑。例如:
public class Example {
public static final void main(String[] args) {
Example e = null;
e.staticMethod();
}
static void staticMethod() {
System.out.println("staticMethod");
}
}
人们可能会认为NullPointerException
会失败。但事实并非如此,因为staticMethod
是静态的,所以不需要实例来调用它,所以e
是null
这一事实无关紧要。
通过实例引用访问static还会导致生成不必要的字节码。e.staticMethod();
导致:
2:aload_13:爆裂4:invokestatic#2//方法static方法:()V
例如e
的内容被加载然后被弹出。但Example.staticMethod();
只是生成
2:invokestatic#2//方法static方法:()V
这并不重要,JVM中的优化器可能会修复它,但是。。。
在Java中,调用
sv.takeAway();
实际编译为
StaticVerifier.takeAway()
您可以通过调用javap -c StaticVerifier.class
进行检查。
如果您在实例上调用静态方法,一个好的IDE会发出警告。所以C#在这方面更严格。
因为在Java中,当您通过对象引用访问静态方法时,sv.takeAway()
实际上意味着StaticVerifier.takeAway()
,这有点令人困惑(有趣的是,sv
可以是null
,一切都会很好地工作)。
在C#中,他们决定不在语言中包含这种混淆,并且只有一种方法可以访问静态信息,例如StaticVerifier.takeAway()