150

メソッドの静的インポートは良い考えではなかったというレビューコメントを受け取りました。静的インポートは、ほとんど静的メソッドを持つDAクラスからのメソッドでした。したがって、ビジネスロジックの途中で、現在のクラスに属しているように見えるdaアクティビティがありました。

import static some.package.DA.*;
class BusinessObject {
  void someMethod() {
    ....
    save(this);
  }
} 

レビューアは私がコードを変更することに熱心ではなく、私は変更しませんでしたが、私は彼にある程度同意します。静的インポートを行わなかった理由の1つは、メソッドが定義された場所が混乱していたことです。現在のクラスにもスーパークラスにもなかったため、定義を特定するのに時間がかかりすぎました(Webベースのレビューシステムにはクリック可能機能がありません)。 IDEのようなリンク:-)これはそれほど重要ではないと思います。静的インポートはまだ非常に新しく、すぐにそれらを見つけることに慣れます。

しかし、私が同意するもう1つの理由は、修飾されていないメソッド呼び出しが現在のオブジェクトに属しているようであり、コンテキストをジャンプしてはならないということです。しかし、それが本当に属していれば、そのスーパークラスを拡張することは理にかなっています。

では、静的インポートメソッドが意味をなすのはいつですか?いつやったの?修飾されていない呼び出しの外観は気に入りましたか?

編集:一般的な意見は、誰も現在のクラスのメソッドと混同しない場合は、静的インポートメソッドであるようです。たとえば、java.lang.Mathおよびjava.awt.Colorのメソッド。しかし、absとgetAlphaがあいまいでない場合、readEmployeeがなぜであるかわかりません。多くのプログラミングの選択肢と同様に、これも個人的な好みだと思います。

4

16 に答える 16

163

これは、機能をリリースしたときの Sun のガイドからのものです (原文で強調)。

では、いつ静的インポートを使用する必要がありますか? とても控えめに!定数のローカル コピーを宣言したり、継承を悪用したくなる場合 (定数インターフェイス アンチパターン) にのみ使用してください。... 静的インポート機能を使いすぎると、インポートしたすべての静的メンバーで名前空間が汚染され、プログラムが判読不能になり、保守できなくなる可能性があります。コードの読者 (コードを書いてから数か月後のあなたを含む) は、静的メンバーがどのクラスから来ているのかわかりません。クラスからすべての静的メンバーをインポートすると、読みやすさが特に損なわれる可能性があります。必要なメンバーが 1 つまたは 2 つだけの場合は、個別にインポートします。

( https://docs.oracle.com/javase/8/docs/technotes/guides/language/static-import.html )

特に強調したいのは、次の 2 つの部分です。

  • 「継承を悪用する」誘惑に駆られた場合にのみ、静的インポートを使用してください。この場合、 BusinessObject を使用したくなりますextend some.package.DAか? もしそうなら、静的インポートはこれを処理するよりクリーンな方法かもしれません。を拡張することを夢にも思わなかった場合some.package.DA、これはおそらく静的インポートの不適切な使用です。入力時に数文字を節約するためだけに使用しないでください。
  • 個々のメンバーをインポートします。import static some.package.DA.saveの代わりに言ってDA.*ください。これにより、このインポートされたメソッドがどこから来ているのかを簡単に見つけることができます。

個人的には、私はこの言語機能をめったに使用したことがなく、ほとんど常に定数または列挙型でのみ使用し、メソッドでは使用しませんでした。私にとって、トレードオフはほとんど価値がありません。

于 2009-01-07T17:01:59.613 に答える
67

静的インポートのもう 1 つの妥当な使用法は、JUnit 4 です。以前のバージョンの JUnit メソッドassertEqualsfailは、テスト クラス extended から継承されていましたjunit.framework.TestCase

// old way
import junit.framework.TestCase;

public class MyTestClass extends TestCase {
    public void myMethodTest() {
        assertEquals("foo", "bar");
    }
}

JUnit 4 では、テスト クラスを拡張する必要がなくなり、TestCase代わりにアノテーションを使用できるようになりました。その後、アサート メソッドを静的にインポートできますorg.junit.Assert

// new way
import static org.junit.Assert.assertEquals;

public class MyTestClass {
    @Test public void myMethodTest() {
        assertEquals("foo", "bar");
        // instead of
        Assert.assertEquals("foo", "bar");
    }
}

JUnitドキュメントはこのように使用します。

于 2009-01-07T18:32:14.983 に答える
30

アイテム19の最後にあるEffective Java、Second Editionでは、ユーティリティクラスの定数を頻繁に使用している場合は、静的インポートを使用できると述べています。この原則は、定数とメソッドの両方の静的インポートに適用されると思います。

import static com.example.UtilityClassWithFrequentlyUsedMethods.myMethod;

public class MyClass {
    public void doSomething() {
        int foo = UtilityClassWithFrequentlyUsedMethods.myMethod();
        // Can be written less verbosely as
        int bar = myMethod();
    }
}

これには長所と短所があります。メソッドが定義されている場所に関する即時の情報が失われるという犠牲を払って、コードが少し読みやすくなります。ただし、優れた IDE では定義に移動できるため、これはあまり問題になりません。

インポートしたファイルの内容を何度も何度も使用している場合にのみ、これを慎重に使用する必要があります。

編集:この質問が参照しているものであるため、メソッドに固有のものになるように更新されました。この原則は、インポートされるもの (定数またはメソッド) に関係なく適用されます。

于 2009-01-07T18:20:53.150 に答える
21

Arraysや などの utils クラスを使用する場合、静的インポートは冗長なクラス名を削除するのに非常に便利だと思いますAssertions

理由はわかりませんが、Rossは参照しているドキュメントでこれに言及している最後の文をスキップしました。

適切に使用すると、静的インポートを使用すると、クラス名の繰り返しのボイラープレートが削除されるため、プログラムが読みやすくなります。

基本的にこのブログからコピー: https://medium.com/alphadev-thoughts/static-imports-are-great-but-underused-e805ba9b279f

たとえば、次のようになります。

テストでのアサーション

これは、私たち全員が同意すると思う最も明白なケースです

Assertions.assertThat(1).isEqualTo(2);

// Use static import instead
assertThat(1).isEqualTo(2);

Utils クラスと列挙型

utils クラスを使用する場合、多くの場合、クラス名を削除してコードを読みやすくすることができます。

List<Integer> numbers = Arrays.asList(1, 2, 3);

// asList method name is enough information
List<Integer> numbers = asList(1, 2, 3);

java.time パッケージには、使用すべきいくつかのケースがあります

// Get next Friday from now, quite annoying to read
LocalDate.now().with(TemporalAdjusters.next(DayOfWeek.FRIDAY));

// More concise and easier to read
LocalDate.now().with(next(FRIDAY));

使用しない場合の例

// Ok this is an Optional
Optional.of("hello world");

// I have no idea what this is 
of("hello world");
于 2018-03-01T07:11:08.253 に答える
17

読みやすさの観点から問題がある可能性があり、慎重に使用する必要があることに同意します。しかし、一般的な静的メソッドを使用すると、実際には読みやすさを向上させることができます。たとえば、JUnit テスト クラスでは、 のようなメソッドassertEqualsがどこから来たのかは明らかです。からのメソッドについても同様ですjava.lang.Math

于 2009-01-07T15:57:13.423 に答える
12

カラーでよく使います。

static import java.awt.Color.*;

色が他のものと混同されることはほとんどありません。

于 2009-01-07T16:35:07.887 に答える
5

Java で OpenGL を使用する場合は、静的インポートの使用をお勧めします。これは、 「ユーティリティ クラスの定数を多用する」カテゴリに分類されるユース ケースです。

それを考慮してください

import static android.opengl.GLES20.*;

元の C コードを移植して、次のような読みやすいものを書くことができます。

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glUniform1i(samplerUniform, 0);
glBindBuffer(GL_ARRAY_BUFFER, vtxBuffer);
glVertexAttribPointer(vtxAttrib, 3, GL_FLOAT, false, 0, 0);

その一般的な広範な醜さの代わりに:

GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texture);
GLES20.glUniform1i(samplerUniform, 0);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vtxBuffer);
GLES20.glVertexAttribPointer(vtxAttrib, 3, GLES20.GL_FLOAT, false, 0, 0);
于 2016-03-19T23:24:53.643 に答える
3

数学の重いコードを C/C++ から Java に移植するときは、「import static java.lang.Math.*」を使用します。数学メソッドは 1 対 1 でマップされ、クラス名修飾なしで移植されたコードの比較が容易になります。

于 2014-10-30T16:37:04.727 に答える
2

静的インポートは、先ほど述べた問題のために、私がこれまで使用したことがなく、使用する予定もないJavaの唯一の「新しい」機能です。

于 2009-01-07T15:48:56.047 に答える
1

これらは、特に多数のインポートされたメソッドが呼び出され、ローカル メソッドとインポートされたメソッドの区別が明確な場合に、言い回しを減らすのに役立ちます。

一例: java.lang.Math への複数の参照を含むコード

別:すべての参照の前にクラス名を追加すると、構築中の構造が隠されるXML ビルダー クラス

于 2009-01-07T15:57:48.010 に答える
1

IMO 静的インポートは非​​常に優れた機能です。静的インポートに大きく依存すると、コードが判読不能になり、静的メソッドまたは属性がどのクラスに属しているかを理解するのが難しくなることは絶対に真実です。ただし、私の経験では、特にUtilいくつかの静的メソッドと属性を提供するクラスを設計するときに使用できる機能になります。静的インポートを提供するたびに発生するあいまいさは、コード標準を確立することで回避できます。会社での私の経験では、このアプローチは受け入れられ、コードがよりクリーンで理解しやすくなります。_できれば、静的メソッドと静的属性の前に文字を挿入します(どういうわけかCから採用されました). このアプローチは明らかに Java の命名基準に違反していますが、コードを明確にしています。たとえば、AngleUtils クラスがあるとします。

public class AngleUtils {

    public static final float _ZERO = 0.0f;
    public static final float _PI   = 3.14f;

    public static float _angleDiff(float angle1, float angle2){

    }

    public static float _addAngle(float target, float dest){

    }
}

この場合、静的インポートは明快さを提供し、コード構造はよりエレガントに見えます:

import static AngleUtils.*;

public class TestClass{

    public void testAngles(){

        float initialAngle = _ZERO;
        float angle1, angle2;
        _addAngle(angle1, angle2);
    }
}

どのメソッドまたは属性が静的インポートに由来するかを誰かがすぐに知ることができ、それが属するクラスの情報を隠します。モジュールの不可欠な部分であり、静的メソッドと非静的メソッドを提供するクラスに静的インポートを使用することはお勧めしません。これらの場合、どのクラスが特定の静的機能を提供するかを知ることが重要であるためです。

于 2014-08-25T16:16:21.693 に答える
-1

次の場合に使用する必要があります。

  • switch列挙値を持つステートメントを使用したい
  • コードを理解しにくくしたい
于 2009-01-07T17:42:38.750 に答える
-5

できるときはいつでもそれらを使用します。忘れた場合に思い出させるIntelliJセットアップがあります。完全修飾パッケージ名よりもきれいに見えると思います。

于 2009-01-07T16:22:54.120 に答える