JavaジェネリックT対オブジェクト


127

次の2つのメソッド宣言の違いは何ですか。

public Object doSomething(Object obj) {....}

public <T> T doSomething(T t) {....}

一方でできる/できることはありますか?このサイトの他の場所でこの質問を見つけることができませんでした。

回答:


112

コンテキストから分離-違いはありません。両方tobj、のメソッドのみを呼び出すことができますObject

しかし、コンテキスト付き-一般的なクラスがある場合:

MyClass<Foo> my = new MyClass<Foo>();
Foo foo = new Foo();

次に:

Foo newFoo = my.doSomething(foo);

オブジェクトと同じコード

Foo newFoo = (Foo) my.doSomething(foo);

2つの利点:

  • キャストする必要はありません(コンパイラーはこれを非表示にします)
  • 機能する時間安全性をコンパイルします。Objectバージョンが使用されている場合、メソッドが常にを返すかどうかはわかりませんFoo。が返された場合はBarClassCastException実行時にがあります。

14

ここでの違いは、最初の例では、呼び出し元がObjectインスタンス(任意のクラス)を渡す必要があることを指定し、別のObject(同じタイプのクラスではない任意のクラス)を返すことです。

2番目の例では、返されるタイプは、クラスが定義されたときに指定されたタイプと同じタイプになります。

Example ex = new Example<Integer>();

ここでは、クラスまたはメソッドにより多くの制約を適用できるT型を指定します。たとえば、LinkedList<Integer>またはLinkedList<Example>をインスタンス化でき、これらのメソッドの1つを呼び出すと、IntegerまたはExampleインスタンスが返されることがわかります。

ここでの主な目標は、型キャストに依存せずに、クラスが操作するオブジェクトのタイプを呼び出しコードで指定できるようにすることです。

OracleのJava Generics *を参照してください。

*リンクを更新しました。


13

違いは、ジェネリックメソッドではキャストする必要がなく、間違った場合にコンパイルエラーが発生することです。

public class App {

    public static void main(String[] args) {

        String s = process("vv");
        String b = process(new Object()); // Compilation error
    }

    public static <T> T process(T val) {

        return val;
    }
}

オブジェクトを使用すると、常にキャストする必要があり、間違ったときにエラーが発生しません。

public class App {

    public static void main(String[] args) {

        String s = (String)process("vv");
        String b = (String)process(new Object());
    }

    public static Object process(Object val) {

        return val;
    }
}

アンドロイド6以降、オブジェクトをキャストする必要がないことも言及したように
John Lord

2

追加のクラスキャストを行う必要はありません。最初のケースでは、常にクラスにキャストする必要があるjava.lang.Objectクラスのオブジェクトを取得します。2番目のケースでは、Tは一般的な署名で定義されたクラスに置き換えられ、クラスのキャストは必要ありません。


2

実行時には何もしません。しかし、コンパイル時に2番目は型チェックを実行して、パラメーターの型と戻り値の型がTが解決する型と一致する(またはそのサブタイプである)ことを確認します(最初の例も型チェックを行いますが、すべてのオブジェクトはオブジェクトのサブタイプなので、すべてのタイプが受け入れられます)。


2

Tはジェネリック型です。つまり、実行時に任意の適格オブジェクトで置き換えることができます。このようなメソッドは次のように呼び出すことができます。

String response = doSomething("hello world");

または

MyObject response = doSomething(new MyObject());

または

Integer response = doSomething(31);

ご覧のとおり、ここにはポリモーフィズムがあります。

ただし、Objectを返すように宣言されている場合は、キャストを入力しない限り、これを行うことはできません。


<T>オートボクシングがないと言えますか?
SMUsamaShah 2018

0

最初のケースでは、egstring型のパラメータを取り、foo型を返します。2番目のケースでは、タイプfooのパラメーターを取り、タイプfooのオブジェクトを返します。


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.