列挙型の匿名の実装では、引数を持つ列挙型のプライベート静的メソッドToStringを参照することはできません

Fimgd:

このコード例を考えると...

package example;

public class Main {
    public static void main(String[] args) {
        System.out.println(MyEnum.X.getValue());
    }

    private enum MyEnum {
        X(){
            @Override
            String getValue() {
                return toString("XYZ"); //error here
            }
        };

        abstract String getValue();

        private static String toString(String output) {
            return output;
        }
    }
}

次のコンパイラエラーが生成されます。

Error:(12, 40) java: method toString in class java.lang.Enum<E> cannot be applied to given types;
  required: no arguments
  found: java.lang.String
  reason: actual and formal argument lists differ in length

IntelliJのは、別の問題が付属していますtoStringからtoString("XYZ")赤で下線が引かれ、メッセージは「メイク「MyEnumを解決して、示されている「『のtoString(java.lang.Stringで)』 『example.Main.MyEnum』内の専用アクセスを持っています」 .toString」パッケージプライベート」。

私には奇妙な何、以下の修正のいずれかのこの問題のことです。

  • 列挙型の参照を経由してメソッドを呼び出します:X.toString("XYZ")
  • クラス参照を経由してメソッドを呼び出します:MyEnum.toString("XYZ")
  • スーパー経由でメソッドを呼び出します:super.toString("XYZ")(ただし、this.toString("XYZ")動作しません)
  • メソッドパッケージプライベートまたはパブリックを作ります
  • メソッドの命名「toString2」

さて、任意の生産コードのために、私はおそらく他の(私はそれをどうしたいものにより説明おそらく何かを)メソッドの何かに名前を付け、上に移動、それでも私は左を思ったんだけど、なぜこれが起こるんだろうか?そして、なぜIntelliJのとjavac異なるからエラーメッセージがありますか?

この質問は、おそらくに似ているプライベート変数と非静的フィールドmemberVariableへの静的参照を作成することはできませんが、私はそれが完全には問題が説明していない感じ-なぜ仕事の名前を変更しませんの?

マイケル:

まず、この問題は、列挙型に固有ではありません。これは、任意の内部クラスに適用されます。私は内部クラスと匿名内部クラスの両方で同じ問題を示し列挙し、削除するためにあなたの例をリファクタリングしています。

class Main {
    public static void main(String[] args) {
        Main main = new Main() {
            {
                System.out.println(toString("XYZ")); // same error
            }  
        };
    }

    class Foo {
        {
            System.out.println(toString("XYZ")); // same error
        }
    }

    private static String toString(String output) {
        return output;
    }
}

JLSで説明され、ここで

例6.5.7.1-1。シンプルなメソッド名

次のプログラムは、呼び出すメソッドを決定する際にスコープの役割を示しています。

class Super {
    void f2(String s)       {}
    void f3(String s)       {}
    void f3(int i1, int i2) {}
}

class Test {
    void f1(int i) {}
    void f2(int i) {}
    void f3(int i) {}

    void m() {
        new Super() {
            {
                f1(0);  // OK, resolves to Test.f1(int)
                f2(0);  // compile-time error
                f3(0);  // compile-time error
            }
        };
    }
} 

呼び出しのためにf1(0)、F1という名前の1つの方法だけではスコープ内にあります。これは、方法であって、Test.f1(int)その宣言匿名クラス宣言を含む試験体全体範囲内にあります。 §15.12.1匿名クラスの宣言は、という名前のメンバーを持っていないので、クラスTestで検索することを選択しましたf1結局、Test.f1(int)解決されます。

呼び出しのためにf2(0)、という2つの方法がf2有効範囲内にあります。まず、メソッドの宣言は、Super.f2(String)匿名のクラス宣言全体の範囲です。第二に、メソッドの宣言は、 Test.f2(int)匿名のクラス宣言を含む試験体全体範囲内にあります。(それぞれが宣言されている点で、他の範囲ではないため、どちらの宣言は、他の影がある。注)§15.12.1選択し、それが名前のメンバを持っているのでクラススーパーで検索しますf2しかし、Super.f2(String)には適用されません f2(0)ので、コンパイル時エラーが発生します。クラスがあることに注意してくださいTest検索されません。

呼び出しのためにf3(0)、という3つの方法がf3有効範囲内にあります。第一及び第二の、メソッドの宣言Super.f3(String)Super.f3(int,int)匿名クラス宣言全体範囲内にあります。第三に、メソッドの宣言は、Test.f3(int)匿名のクラス宣言を含む試験体全体範囲内にあります。§15.12.1クラスで検索することを選択したSuperことが名前のメンバーを持っているのでf3しかし、Super.f3(String)Super.f3(int,int)には適用されませんf3(0)コンパイル時エラーが発生するので、。クラスがあることに注意してくださいTest検索されません。

字句的に取り囲む範囲が「くしのルール」(と呼ばれる前に、ネストされたクラスのスーパークラス階層を検索するように選択する§15.12.1)。

おすすめ

転載: http://43.154.161.224:23101/article/api/json?id=17193&siteId=1