下面这个程序中T 类型不是被擦除了吗?为什么使用get ( ) 方法不需要类型装换? (不适用泛型的简单代码就需要加(String) 来实现类型转换)
擦除知识点在实际编程中体现的多吗?
代码如下:
public class GenericHolder<T> {
private T obj;
public void set(T obj) { this.obj = obj; }
public T get() { return obj; }
public static void main(String[] args) {
GenericHolder<String> holder =
new GenericHolder<String>();
holder.set("Item");
String s = holder.get();
}
}
public class SimpleHolder {
private Object obj;
public void set(Object obj) { this.obj = obj; }
public Object get() { return obj; }
public static void main(String[] args) {
SimpleHolder holder = new SimpleHolder();
holder.set("Item");
String s = (String)holder.get();
}
}
消去は、実行時にジェネリック クラス内でジェネリック パラメータに関する情報を取得できないことを意味します。境界が指定されている場合、ジェネリック変数の実際の型は境界を指定しません。つまり、obj の実際の実行時の型は Object です。get() メソッドを使用するときに強制的な型変換が必要ないのは、私の記憶が正しければ、コンパイラが変換コードを生成するためです。処理後の状況は、例 2 の main メソッドの
String s = (String)holder.get()
と似ています。詳細については、作者は javap を使用して逆コンパイルして表示できます。2番目の質問ですが、これはソースコードを読むか読まないかと同じだと思いますが、読まなくてもプログラミングには影響しません。しかし、読んでみると非常に影響を受けることがわかります。簡単に書きます。私はまだ学生なので、実際には状況がわかりませんが、少し意見を述べます〜
ジェネリックはソース コードにのみ反映され、コンパイル後は後者の例と同等になります。したがって、public void test(List list) および public void test(List list) はオーバーロードできません。
消去は、Java ファイルがクラス ファイルにコンパイルされるとき、コンパイル中に行われます。 Java のジェネリックスは、一種の構文糖衣とみなすことができ、Java コードを記述する際に安全かつ便利になります。
Erasure は実際の作業では使用されません。Erasure は、コンパイル時の汎用構文シュガーの解釈アクションとして考えることができます。
ジェネリック クラス T new を使用する場合、T は String として指定され、そのメンバー変数も String になります。ただし、別のクラスのメンバーは Object であり、new
は必要ありません。指定されているため、変換が必要です。
消去は実際の作業では通常使用しません。
1. まず、消去とは、汎用タグが Javac コンパイラーに渡されて実行および機能することを意味します。 コードがコンパイル期間を過ぎると、「T」は動作中に無視され、クラス ファイル内で T が見つかりません。 ここで型が <String> であることを指定すると、コンパイラはコンパイル中に GenericHolder に保持されている T を String 型に変換します。 したがって、get を変換する必要はありません (コンパイラーはすでに String を認識しています)。
2. 消去はジェネリックにおいて非常に重要な概念です。消去を理解していなければ、ジェネリックも理解できないと言えます。実際の作業に一般的で関連するのは、gson などのフレームワークで使用されるオブジェクトのシリアル化と逆シリアル化です。
リーリーGenericHolder<String>
のは
と同等です リーリー実際には単なる構文シュガーです