Java静的汎用メソッド


JavaはJDK 5に汎用型を導入し、使いやすくなりました.以下は一般的な汎用型の使用です.
List list = new ArrayList();

汎用メソッドの使用
コレクションで使用できるだけでなく、クラス、インタフェース、メソッドを定義する際にもよく使用されますが、汎用メソッドで使用されるシーンはあまり多くありません.次に、2つの数の最大数を求める実装から、汎用クラスと汎用メソッドの簡単な使用を見てみましょう.
汎用クラス(インタフェース)
package me.codeboy.test;

/**
 * generic test
 * Created by yuedong on 9/12/16.
 */
public class MathTest {

    public static void main(String[] args) {
        MathTest mathTest1 = new MathTest();
        MathTest mathTest2 = new MathTest();
        System.out.println(mathTest1.max(1, 2));
        System.out.println(mathTest2.max(2.0, 3.0));
    }

    private T max(T t1, T t2) {
        return t1.compareTo(t2) > 0 ? t1 : t2;
    }
}

汎用メソッド
/**
 * generic test
 * Created by yuedong on 9/12/16.
 */
public class MathTest {

    public static void main(String[] args) {
        MathTest mathTest = new MathTest();
        System.out.println(mathTest.max(1, 2));
        System.out.println(mathTest.max(2.0, 3.0));
    }

    private  T max(T t1, T t2) {
        return t1.compareTo(t2) > 0 ? t1 : t2;
    }
}

静的汎用メソッド
/**
 * generic test
 * Created by yuedong on 9/12/16.
 */
public class MathTest {

    public static void main(String[] args) {
        System.out.println(max(1, 2));
        System.out.println(max(2.0, 3.0));
    }

    private static  T max(T t1, T t2) {
        return t1.compareTo(t2) > 0 ? t1 : t2;
    }
}


汎用メソッドの長所と短所
利点は明らかで、コードが簡潔になったこと、あるいは普通の汎用型よりも簡潔と言える.ネット上にはAndroidで頻繁に使われている一節がある.  findViewById  メソッドの静的汎用メソッド実装は、最も強力なAndroidコードを見たことがあると言われていますが、物事には両面性があり、静的汎用メソッドにも欠点があります.コードを見てみましょう.
import java.util.ArrayList;
import java.util.List;

/**
 * test entry
 * Created by yuedong on 9/10/16.
 */
public class Test {

    public static void main(String[] args) {
        List list = new ArrayList<>();
        list.add("test");

        //    
        ArrayList result1 = (ArrayList) list;

        //      
        String result2 = convert(list);
    }

    private static  T convert(Object a) {
        return (T) a;
    }
}

上記のコードは コンパイルが通過し、異常が実行されるのは、なぜこのような現象が発生するのでしょうか.これはJavaの汎用メソッドが擬似汎用に属し,コンパイル時にタイプ消去が行われるためである.通常の汎用メソッドではクラス構築時に対応するタイプが明確に定められているが,静的汎用メソッドではタイプが直接推測できず,明確なタイプが欠け,最終的にタイプ転化異常をもたらす.
Exception in thread "main" java.lang.ClassCastException: java.util.ArrayList cannot be cast to java.lang.String

原理の探求
以上の結果を見て、汎用メソッドがタイプ消去後に最終的に何に変換されたのかを知りたくなりました.上記の静的汎用メソッドを逆コンパイルしてコンパイルしたclassファイルは以下の通りです.
Compiled from "Test.java"
public class Test {
  public Test();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: new           #2                  // class java/util/ArrayList
       3: dup
       4: invokespecial #3                  // Method java/util/ArrayList."":()V
       7: astore_1
       8: aload_1
       9: ldc           #4                  // String test
      11: invokeinterface #5,  2            // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
      16: pop
      17: aload_1
      18: checkcast     #2                  // class java/util/ArrayList
      21: astore_2
      22: aload_1
      23: invokestatic  #6                  // Method convert:(Ljava/lang/Object;)Ljava/lang/Object;
      26: checkcast     #7                  // class java/lang/String
      29: astore_3
      30: return
}

convert関数の最終変換後の対応するバイトコードは  Method convert:(Ljava/lang/Object;)Ljava/lang/Object;  パラメータはObjectタイプで、戻りもObjectタイプで、次の  checkcast  操作中、  List  および  String  タイプが違うので、異常を投げ出しました.
    private static  T convert(Object a) {
        return (T) a;
    }

上記のコードに対して逆コンパイル後対応  Method convert:(Ljava/lang/Object;)Ljava/util/List;  で、このときパラメータがObjectタイプであり、Listタイプとして返されることがわかります.
小結
Javaの汎用は擬似汎用ですが、汎用はコードをより簡潔にすることができ、使用しているだけです.   および   タイプ変換に特に注意する必要があります.
もっと多くの文章は小太り軒を訪問してください.