web-dev-qa-db-ja.com

内部クラスをインスタンス化するための奇妙な構文

この段階で、Javaで根本的に新しい構文に遭遇するとは想像もしていませんでしたが、見よ、私は何かに遭遇しただけです。

正確なコンテキストと以下のコードが行うべきことはまったく関係ありません-ある種のコンテキストを与えるためだけにあります。

IT Mill Toolkitでイベントを総合的に作成しようとしているので、次のような行を作成しました。

buttonClick(new Button.ClickEvent(button));

しかし、Eclipseは次のエラーメッセージを表示します。

Button型の囲んでいるインスタンスにアクセスできません。 Buttonタイプのインスタンスで割り当てを修飾する必要があります(例:x.new A()ここで、xはButtonのインスタンスです)。

上記の行を次のように書き直すと、もう文句はありません。

buttonClick(button.new ClickEvent(button)); // button instanceof Button

だから、私の質問は次のとおりです:後者の構文は正確には何を意味し、最初のスニペットが機能しないのはなぜですか? Java不満は何ですか、そしてそれは何ですか? 2番目のバージョンでやっていますか?

背景情報:ButtonButton.ClickEventはどちらも非抽象パブリッククラスです。

42
Henrik Paul

内部クラス(Button.ClickEventなど)には、外部クラス(Button)のインスタンスへの参照が必要です。

この構文は、外部クラス参照がbuttonの値に設定されたButton.ClickEventの新しいインスタンスを作成します。

ここに例があります-カプセル化の欠如などを無視してください、それはデモンストレーションの目的のためだけです:

class Outer
{
    String name;

    class Inner
    {
        void sayHi()
        {
            System.out.println("Outer name = " + name);
        }
    }
}

public class Test
{
    public static void main(String[] args)
    {
        Outer outer = new Outer();
        outer.name = "Fred";

        Outer.Inner inner = outer.new Inner();
        inner.sayHi();
    }
}

内部クラスとそれを囲むインスタンスの詳細については、 仕様のセクション8.1. を参照してください。

71
Jon Skeet

Button.ClickEventは非静的内部クラスであるため、このクラスのインスタンスはButtonのインスタンスに囲まれてのみ存在できます。

2番目のコード例では、Buttonのインスタンスがあり、このButtonインスタンスで囲まれたClickEventのインスタンスを作成します...

10
pgras

Javaの非静的内部クラスには、宣言されている外部クラスのインスタンスを指す非表示の参照が含まれています。したがって、最初に表示されたエラーメッセージは、作成できないことを示しています。アタッチする外部クラスのインスタンスも指定せずに、内部クラスの新しいインスタンス。

おそらく、これまで構文を見たことがない理由は、内部クラスが外部クラスのメソッドに割り当てられることが多く、コンパイラがこれを自動的に処理するためです。

9

このめったに使用されない機能で自分や他のプログラマーを混乱させないように、内部クラスをいつでも静的にすることができます。

外部クラスへの参照が必要な場合は、コンストラクターで明示的に渡すことができます。

3
starblue

実際にそれを行うことができます、しかしあなたは宣言する必要がありますClickEvent as staticButton内で、そしてあなたはすべきではありません悪行税を使用しても問題ありません:

_buttonClick(new Button.ClickEvent(button));
_

基本的に、staticは、クラスClickEventButtonの特定のインスタンス(つまり、new Button())ではなく、クラスButtonに直接属します。


@Jon Skeetの例に続いて:

_// Button.Java
class Button
{

    public static class ClickEvent
    {
        public ClickEvent(Button b)
        {
            System.out.println("Instance: " + this.toString());
        }
    }
}

// Test.Java
public class Test
{
    public static void main(String[] args)
    {
        Button button = new Button();
        buttonClick(new Button.ClickEvent(button));
    }

    public static void buttonClick (Button.ClickEvent ce) {
    }
}
_
1
toto_tico