2

私の知る限り、同じ呼び出しシグネチャを持つメソッドを持つことはできません。でも:

$ javap -public java.time.LocalTime  | grep "minus" | grep "Temporal" | grep -v "long"
    public java.time.LocalTime minus(java.time.temporal.TemporalAmount);
    public java.time.temporal.Temporal minus(java.time.temporal.TemporalAmount);

これらは、同じ呼び出しシグネチャを持つ複数のメソッドを明確に示しています。

  1. Java は関数呼び出しをどのように解決しますか?
  2. なぜ複数の機能があるのですか?

編集:関連するビットのみを保持することにより、質問を簡素化しました。

4

3 に答える 3

7

これは、Java が共変の戻り値の型を実装する方法によるものです。署名付きjava.time.LocalTimeのメソッドがありますminus

LocalTime minus(TemporalAmount amountToSubtract)

java.time.temporal.Temporalしかし、このメソッドは署名付きのインターフェースメソッドを実装しています

Temporal minus(TemporalAmount amount)

これは、共変の戻り値の型付けにより許可されますが、メソッド ルックアップの動作方法により、 を返すメソッドを実行時にルックアップしても、 を返すTemporalメソッドが見つかりませんLocalTime。したがって、コンパイラは、同じ署名を持つ通常禁止されているメソッドを作成しますが、Temporal. このメソッドは、 を返すバージョンを呼び出しますLocalTime。実行時に、戻り値の型を必要とする呼び出しTemporalはブリッジ メソッドを見つけ、すべてがうまくいきます。

このブリッジ メソッドは通常は表示されませんが、javap出力に表示されるため、現在の混乱につながっています。

ソース: http://www.artima.com/weblogs/viewpost.jsp?thread=354443

以下javap -cは、 のブリッジ メソッドの 1 つを逆アセンブリしたものでStringBuilder、同じシグネチャでより具体的な戻り値の型を使用してメソッドを呼び出す方法を示しています。

  public java.lang.Appendable append(java.lang.CharSequence) throws java.io.IOException;
    Code:
       0: aload_0       
       1: aload_1       
       2: invokevirtual #6                  // Method append:(Ljava/lang/CharSequence;)Ljava/lang/StringBuilder;
       5: areturn       
于 2016-07-21T05:23:26.200 に答える
2

Java では、同じ名前と署名を持つ同じクラスまたはインターフェイスの 2 つのメソッドを禁止しています

ただし、2 つの異なるクラス、インターフェイス、または列挙型が同じメソッド シグネチャを持つことができます。たとえば、これは有効です。

public java.time.LocalTime minus(long, java.time.temporal.TemporalUnit);
public java.time.temporal.Temporal minus(long, java.time.temporal.TemporalUnit);

1 つのminusメソッドはLocalTimeクラスに属し、もう 1 つはTemporalインターフェイスに属します。LocalTimeが実装されTemporalているため、これら 2 つの署名が一致する必要があります。そうしないと、コントラクトが満たされないため、コンパイル エラーが発生します。

于 2016-07-21T04:58:55.970 に答える