簡體   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