7

メソッドJunit4を静的にインポートするテストケースがあります。org.junit.Assert.assertEquals

import static org.junit.Assert.assertEquals;

このクラスでは、equalsを実装していない(また、実装に苦労している)いくつかの複雑な内部クラスをアサートするためのユーティリティメソッドを作成しました。

private void assertEquals(MyObj o1, MyObj o2)
{
    assertEquals(o1.getSomething(), o2.getSomething());
    assertEquals(o1.getSomethingElse(), o2.getSomethingElse());
    ...
}

インポートしているメソッドを「オーバーロード」しているようにコードが動作することを期待していましたが、静的にインポートされたメソッドassertEqualsを非静的なプライベートメソッドが隠しているようです。また、メソッドをpublicand static(すべての順列)に変えようとしましたが、成功しませんでした。名前を変更する必要がありました。

それがこのように動作する理由は何ですか?ドキュメントでこの動作への参照を見つけることができませんでした。

4

4 に答える 4

3

あなたが観察したのはシャドウイングと呼ばれています。Javaの2つのタイプが同じ単純な名前を持つ場合、一方が他方をシャドウイングします。その場合、シャドウタイプは単純な名前では使用できません。

最も一般的なタイプのシャドウイングは、フィールドを非表示にするパラメーターです。通常、セッターコードは次のようになりますsetMyInt(int myInt) {this.myInt = myInt; }

次に、関連するドキュメントを読みましょう。

static-import-on-demand宣言によって、他の宣言がシャドウされることはありません。

これは、静的インポートオンデマンドが常に最後に来ることを示しているため、インポートオンデマンド宣言と同じ単純な名前のタイプは、常に静的インポートをシャドウ(非表示)にします。

于 2011-07-06T12:52:22.810 に答える
1

オーバーロードと上書きは、継承ツリーで機能します。ただし、静的インポートは継承を構築しません。

独自のassertEqualsメソッドでjunitのassertEqualsを使用する場合は、それをclassName(Assert.assertEqualsなど)で修飾する必要があります。

org.junit.Assertの非静的インポートを使用します。

于 2011-07-06T12:15:31.660 に答える
0

意味あり。javacがあなたが望むことをするなら、それはassertEquals(MyObj, MyObj)今日あなたのメソッドを選びます。明日org.junit.Assertが独自のassertEquals(MyObj, MyObj)メソッドを追加した場合はどうなりますか?呼び出しの意味は、assertEquals(mo1,mo2)知らないうちに劇的に変化しました。

問題は名前の意味ですassertEquals。Javacは、これがのメソッドの名前であると判断する必要がありorg.junit.Assertます。その後、メソッドのオーバーロード解決を実行できます。org.junit.Assert名前が付いているすべてのメソッドを調べてassertEquals、最も適切なメソッドを選択します。

javaは複数のクラスからのメソッドのオーバーロードを処理できると考えられますが、最初の段落が示すように、呼び出しているメソッドの開発者に大きな不確実性をもたらします。これらのクラスは無関係であるため、メソッドのセマンティクスは大きく異なる可能性があります。

コンパイル時に、メソッドがどのクラスに属しているかが開発者に間違いなくある場合でも、クラスが明日メソッドをオーバーロードして、呼び出されるターゲットメソッドを変更する可能性があります。ただし、それは同じクラスによって行われるため、責任を負うことができます。たとえばorg.junit.Assert、新しいメソッドを追加することを決定した場合assertEquals(MyObj, MyObj)、の以前の呼び出しの一部assertEquals(Object,Object)が新しいメソッドに再ルーティングされることに注意する必要があります。また、呼び出しサイトを壊すようなセマンティクスの変更がないことを確認する必要があります。

于 2011-07-06T21:04:45.770 に答える
0

あなたはメソッドの隠蔽に出くわしまし。そこでは、ローカルメソッドの存在が別のクラス(多くの場合スーパークラス)からメソッドを「隠蔽」します。

メソッドを静的にインポートすることは、構文的には可能ですが、どういうわけか「間違っている」と常に感じていました。

スタイルとして、クラスをインポートTheirClass.method()してコードで使用することを好みます。そうすることで、メソッドがローカルメソッドではないことが明確になり、優れたコードの特徴の1つは明確さです。

私はあなたをお勧めしimport org.junit.Assert、使用しますAssert.assertEquals(...)

于 2011-07-06T12:48:59.313 に答える