簡體   English   中英

在Java中,我如何顯式引用`this`類的靜態成員?

[英]In Java, how do I refer explicitly to a static member of the class of `this`?

在Java中,如何顯式引用this的靜態成員?

我想明確地引用靜態成員以獲得可讀性,但是不要使用文字類名來尊重重寫該值的子類。

一個人為的例子:

class Flying {
   static final String label = "A Flying Superhero";
   String exclamation() {
      return "Look! Up in the sky! It’s a bird! It’s a plane! It’s "+(WHAT GOES HERE?)+"!";
   }
}

class Superman extends Flying {
   static final String label = "Superman";
}
class Howard extends Flying {
   static final String label = "Howard the Duck";
}

請注意,我想避免單獨使用label ,因為它的含義可能不明確; 我希望讀者立即知道它是一個靜態成員,就像他們從Flying.label ,但沒有命名基類。

(在激發這個問題的情況下,靜態成員也是最終的,但我認為這不會影響你如何引用它。)


編輯 :這是一個可能更具說服力的案例。 我想在超類中實現main ,並讓它創建並使用被調用的子類的實例。

class Super
   public static void main( String[] args ) {
      Super instance = new (?WHAT GOES HERE?)( /*...*/ );
      instance.use();
   }
}

class Sub extends Super {
   void use() {
      /* ... */
   }
}

當在Sub上啟動jvm時,我希望它使用相同的main實現,但是使用子類的實例。

這種情況的不同之處在於上下文是靜態的,要訪問的靜態成員是構造函數。

(這是在建模和模擬的研究生課程中進行的家庭作業;超類是一個模型,不同的場景被實現為子類。)

為了澄清這個問題 ,我認為需要做三件事:

  • 在靜態方法的調用中,獲取調用該方法的Class(我還沒有找到任何內容)
  • 給定一個類,訪問該類的靜態成員(可能使用aClass.getDeclaredField ?)
  • 給定一個類,構造該類的新實例(可能使用aClass.getConstructors ?)

結論

在讀到答案之前,我沒有意識到我試圖做一些與Java方式相反的事情。 顯然我已經習慣了更多動態語言。 (感覺我被JavaScript寵壞了似乎是錯誤的。)

這個架構主要是由我正在使用的框架提供的GUI激發的,它為您提供了一個類選擇器,然后是一個UI,用於與您選擇的類的實例進行交互。 這使得使用不同場景的便捷方式可以為每個場景創建一個類。

對於僅限於訪問靜態成員的原始情況,暫時使用文字類名稱就足夠了。

對於涉及實例化的編輯案例,我將實例化留在子類中並將實例傳遞給超類的方法,如下所示:

class Model {
   public static void run( Model m ) {
      /* ... */
   }
}

class Scenario extends Model {
   public static void main( String[] args ) {
      Model.run( new Scenario( /*...*/ ) );
   }
}

將來,我會盡量避免將某些圖書館引入與語言功能沖突的領域。

你不能覆蓋變量,相反,你需要提供一個方法,例如......

class Flying {

    private final String label = "A Flying Superhero";

    String exclamation() {
        return "Look! Up in the sky! It’s a bird! It’s a plane! It’s " + getLabel() + "!";
    }

    public String getLabel() {
        return label;
    }
}

class Superman extends Flying {

    private final String label = "Superman";
    @Override
    public String getLabel() {
        return label;
    }

}

class Howard extends Flying {

    private final String label = "Howard the Duck";
    @Override
    public String getLabel() {
        return label;
    }
}

子類不繼承靜態成員。 在你的新例子中, main可以像Sub.main(args);一樣被Sub Sub.main(args); 但它總是屬於Super 您甚至可以檢查堆棧跟蹤,確認它是否在Super上調用。

  • 在靜態方法的調用中,獲取調用該方法的Class(我還沒有找到任何內容)

這是不可能做到的。

  • 給定一個類,訪問該類的靜態成員(可能使用aClass.getDeclaredField ?)

這可以做到,但如果你只使用常規繼承,那么解決一個非常簡單的問題是一種非常麻煩的方法。

  • 給定一個類,構造該類的新實例(可能使用aClass.getConstructors ?)

這可以做到並且不時有用。 現在使用Java 8 Supplier不太有用,例如SomeClass::new

靜態是在Java中處理這種問題的錯誤方法。 常規繼承可以讓您輕松地完成這些工作。

class InterfacesExample {
    public static void main(String[] args) {
        @SuppressWarnings("unchecked") // Arrays#asList
        List<Class<? extends Printer>> classes = Arrays.asList(
            FruitPrinter.class,
            TreePrinter.class
        );

        for(Class<? extends Printer> cls : classes) {
            try {
                Constructor<? extends Printer> ctor = cls.getDeclaredConstructor();
                Printer p = ctor.newInstance();
                p.print();
            } catch(Exception e) {
                System.err.println(e);
            }
        }
    }
}

interface Printer {
    void print();
}

class FruitPrinter implements Printer {
    @Override
    public void print() {
        System.out.println("Apple, Banana, Plum, Pear");
    }
}

class TreePrinter implements Printer {
    @Override
    public void print() {
        System.out.println("Oak, Maple, Elm, Willow");
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM