5

OK、JLS スペシャリスト向けの非常に興味深い Java 7 言語パズルがあります。次のコードは、javac でも Eclipse でもコンパイルされません。

package com.example;

public class X {
    public static X com = new X();

    public void x() {
        System.out.println(com.example.X.com);
        // cannot find symbol  ^^^^^^^
    }
}

メンバーが 内からのパッケージcomへのアクセスを完全にブロックしているように見えます。ただし、これは完全には適用されません。たとえば、次のように動作します。com.*X

public void x() {
    System.out.println(com.example.X.class);
}

私の質問:

  • この行動はJLSからどのように正当化されますか?
  • この問題を回避するにはどうすればよいですか

これは、完全な修飾com.example.Xが必要で、comメンバーの名前を変更できない、生成されたコードの実際の問題を簡略化したものにすぎないことに注意してください。

更新:実際には、次のような同様の問題である可能性があると思います: Javaで「equals」メソッドを「静的インポート」できないのはなぜですか?

4

3 に答える 3

8

これは隠蔽と呼ばれます (jls-6.4.2)。

単純な名前は、変数、型、またはパッケージの名前として解釈される可能性があるコンテキストで発生する可能性があります。このような状況では、§6.5 の規則は、変数が型より優先して選択され、型がパッケージより優先して選択されることを指定します。したがって、可視型またはパッケージ宣言を単純な名前で参照できない場合があります。そのような宣言は隠されていると言います。

于 2013-10-16T14:58:43.747 に答える
1

この問題を回避するにはどうすればよいですか?

ここで完全修飾クラス名を使用すると問題が発生する可能性があります。一般に、パッケージ名と変数名はどちらも小文字で始まるため、衝突する可能性があるためです。ただし、クラスの静的メンバーへの参照を取得するために完全修飾クラス名を使用する必要はありません。クラス名だけで修飾して参照できます。クラス名は大文字で始まる必要があるため、パッケージ名や変数と衝突することはありません。(また、完全修飾クラス名を使用して任意のクラスを問題なくインポートできます。これは、インポート ステートメントが変数名とパッケージ名を混同することがないためです。)

public void x() {
    // System.out.println(com.example.X.com);
    // cannot find symbol     ^^^^^^^

    System.out.println(X.com);  // Works fine
}
于 2016-04-28T16:04:33.373 に答える
1

属性 com.example.X.com は静的ではないため、X クラスを介して静的にアクセスすることはできません。X のインスタンスを介してのみアクセスできます。

それ以上に、X をインスタンス化するたびに、新しい X が生成されます。ここでメモリの爆発を予測できます。

非常に悪いコード:)

于 2013-10-16T14:57:41.580 に答える