繁体   English   中英

与.Net不同,为什么Java中的实例可以访问静态成员

[英]Unlike .Net Why the static member can be accessed by the instance in Java

所有,与C#不同,我发现Java中的实例可以访问静态成员。 好的,我对此没有任何意义。 但是实际上它会引起问题。 让我用一个例子来解释。

假设我们已经有两个类。

public class A
{
     public void m1()
     {   
         ...
     } 
} 

publc class B
{
     public void m2()
     {
         A a= new A();
         a.m1();
     }
}

该类已被编译和部署。 它总是可以正常工作。 但是出于某种原因。 有人如下更改A类。

    public class A
    {
         public static void m1()
         {   
             ...
         } 
    }

所以他只是编译了A并部署了它。 B类不需要更改。 因为代码是相同的。 如果没有编译B类,将会发生异常。

Exception in thread "main" java.lang.IncompatibleClassChangeError: 
Expecting non-static method A.main() at B.main(b.java:34)

尽管从实例变量调用静态成员时没有意义。 但是Java允许我们这样做。 我只是不明白为什么Java允许它? 谢谢。

您必须区分源代码和字节代码。

在源代码中,不幸的是Java允许通过实例引用访问静态成员。 因此,您可以轻松地编写a.m1() ,其中a是变量(如您的示例所示)。 但是,这是非常糟糕的样式,因此不建议使用。

静态绑定在编译时解析。 因此,编译器将对类的引用直接将对静态成员的访问写到字节码中。 因此,在分析结果字节码时,您将再也找不到实例引用(关于静态成员)。

而这种区别就是您例外的原因。 类B的字节代码仍然包含对动态链接方法的调用,该调用在类A的字节代码中根本不存在。结果:异常。

您之所以不能使用C#,是因为语言设计师认为这是一种不好的做法,并且可能使人们感到困惑。

以以下Java示例为例:

class A {
    public static void Foo() {
        System.out.println("A::foo");
    }
    public void Bar() {
        System.out.println("A::bar");
    }
}

class B extends A {
    public static void Foo() {
        System.out.println("B::foo");
    }
    public void Bar() {
        System.out.println("B::bar");
    }
}

public static void main(String[] args) {
    A a = new B();
    a.foo();  // A::foo
    a.bar();  // B::bar
    a = null; // Oh-oh
    a.foo();  // A::foo
}

如您所见,即使将a设置为null您仍然可以使用实例变量来调用静态方法。 对于新手程序员和星期一的早晨,这看起来非常混乱。 从我收集到的信息来看,大多数Java开发人员也反对这种做法。

我对Java的当前状态或前进方向并不熟悉。 这很可能只是几年前允许的,但是很难删除,因为它可能会破坏许多现有应用程序。

据我了解,您的问题是“为什么”? 对? 基本上,对于代码演化,应允许进行此类更改。

实际上,您所做的更改被称为二进制不兼容更改。 Java语言规范明确列出了这种不兼容的更改,可能会破坏代码。 是的,这是二进制不兼容的更改,但是编译器无法知道是否有任何正在使用它的客户端应用程序对吗? 因此,它最多会给您一个警告,作为Java开发人员,您应该知道这种二进制不兼容的更改及其影响。 作为代码的编写者,您知道您的代码可能会被其他库使用,并且应该阻止您对代码库进行此类不兼容的更改(否则将破坏客户端库)。 Java编译器没有办法知道这个权利吗? 因此,java允许您更改方法定义,因为这对于代码演化绝对是必不可少的,并且还因为编译器不知道代码的分布和使用方式。 我希望我能解释允许对Java代码进行这种不兼容更改的原因。 欲了解更多信息,请点击这里

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM