[効果java]アイテム26|のタイプは使用しないでください
GenericクラスとGenericインタフェース
クラスとインタフェース宣言でタイプパラメータが使用されている場合は、JENICクラスまたはJENICインタフェースと呼ばれます.
List
インタフェースは、要素タイプを表すタイプパラメータE
を受け入れ、List<E>
として表す.GenericクラスとGenericインタフェースは、総称してGenericタイプと呼ばれます.
ジェニーリックタイプとパラメトリックタイプ
ジェニーリックタイプは一連のパラメータ化タイプを定義した.
まずクラス名またはインタフェース名、次にカッコ内に実際のタイプのパラメータをリストします.
List<String>
とは、要素タイプがString
のリストのパラメトリックタイプを指す.ここで、String
は、従来型パラメータE
に相当する実際型パラメータである.ジェニーンリック型とロー型
Genericタイプが定義されている場合、付属のプロトタイプ(rawtype)も一緒に定義されます.
「羅型」とは、ジェニーンリック型でタイプパラメータを全く使用しない場合を指す.
List<E>
の炉型はList
です.この羅型の動作はジェニーリック型のすべての情報が消去されたようだ.これはJENICを開発前のコードと互換性を持たせるための方法である.
プロトタイプの欠点
異なるタイプのデータを入力してもコンパイルおよび実行されます.
[コレクションの原型]
private final Collection stamps = ...;
...
stamps.add(new Coin(...)); // 실수로 동전을 넣는다.
上記のコードのように、他のタイプをコレクションに入れ、コレクションからコインを取り出すまでエラーは見つかりません.そのため、エラーが発生し、実行時に長い時間が経ってからエラーが発見される可能性があります.そうすると、原因を提供するコードと実行時に問題が発生するコードが分離され、エラーをキャプチャするためにコード全体を表示する必要があります.
この問題を解決するには、パラメータ化された集合タイプを使用して、タイプの安定性を確保する必要があります.
パラメトリックコレクションタイプ
[パラメトリックコレクションタイプ-タイプの安定性を確保]
private final Collection<Stamp> stamps = ...;
このように宣言すると、コンパイラはstampsセットにstampインスタンスのみを配置すべきであることを認識し、予想通りに動作することを確認します.異なるタイプのインスタンスを挿入すると、コンパイルエラーが発生し、問題が表示されます.
コンパイラは、アセンブリから要素を取り出したすべての場所に非表示のフォーマットコピーを追加し、絶対に失敗しないようにします.
リストとリスト<オブジェクト>
ロスタイプを使用すると、ジェニーンリックの抱擁の安定性と表現性が失われます.
それでも、JavaのGenericを受け入れる前のコードとの互換性のため、このタイプが保持される.
List
のようなタイプは使用できないが、List<Object>
のように任意のオブジェクトのパラメトリックタイプを許可することは可能である.ジェネリックタイプではない
List
とは異なり、List<Object>
はすべてのタイプを許可するという意味をコンパイラに伝えている.ジェニーンリックサブタイプルール
List
を受信List<String>
の方法に渡すことができるが、List<Object>
を受信方法に渡すことはできない.これはジェニーリックのサブタイプルールのためです.
List<String>
はList
のサブタイプであるが、List<Object>
はList
のサブタイプではない.その結果,
List<Object>
などのパラメトリックタイプを用いる場合と異なり,List
などのタイプを用いるとタイプ安定性が失われることが分かった.[プロトタイプを使用して実行に失敗しました]
public static void main(String[] args) {
final List<String> strings = new ArrayList<>();
unsafeAdd(strings, Integer.valueOf(42));
String s = strings.get(0);
}
private static void unsafeAdd(final List list, final Integer valueOf) {
list.add(0);
}
このコードはコンパイルできますが、Unchecked call to 'add(E)' as a member of raw type 'java.util.List
の警告が表示されます.警告を無視してプログラムを実行すると
ClassCastException
が発生します.[
List <Object>
タイプを使用-コンパイル時にエラーをチェック]public static void main(String[] args) {
final List<String> strings = new ArrayList<>();
unsafeAdd(strings, Integer.valueOf(42));
String s = strings.get(0);
}
private static void unsafeAdd(final List<Object> list, final Integer valueOf) {
list.add(0);
}
List
をList<Object>
に変更すると、エラーメッセージが出力され、コンパイルできません.非限定ワイルドカードタイプ
ジェニーリックタイプを使いたいが、実際のタイプパラメータが何なのか気にしたくない場合は、疑問符(
?
)を使いましょう.ジェニーリックタイプ
Set<E>
の非限定ワイルドカードタイプはSet<?>
です.<?>
は、任意のタイプを収容できる最も一般的なパラメトリックタイプである.[非限定ワイルドカードタイプ-タイプ安全、ソフト]
static int numElementsInCommon(Set<?> s1, Set<?> s2){...}
lotypeと非限定ワイルドカードタイプの違いは、lotypeには任意の要素を加えることができないため、タイプ不変式を破壊しやすく、非限定ワイルドカードタイプ(null以外)を使用すると任意の要素を加えることができないことです.他の要素を入れると、エラーメッセージが表示されます.
[コレクションを使用して各タイプを比較]
public class TypeTest {
public static void main(String[] args) {
List raw = new ArrayList<>();
List<?> wildCard = new ArrayList<>();
List<Object> generic = new ArrayList<>();
raw.add("Hello"); // 로 타입 (오류발생x)
wildCard.add("Hello"); // 컴파일 오류 발생
generic.add("Hello"); // <Object> 타입 (오류발생x)
}
}
羅タイプを使用する必要がある場合
class literalはrotypeを使用するべきです。
List.class, String[].class, int.class
JAvaリストではclass文字でパラメトリックタイプを使用できません.instanceof演算子を使用する場合はタイプを使用します。
if (o instanceof Set) { // 로 타입
Set<?> s = (Set<?>) o; // 와일드카드 타입
}
実行時にJENICタイプ情報が消去されるため、instanceof
演算子は非限定ワイルドカードタイプ以外のパラメトリックタイプに適用できません.また、
instanceof
演算子のrotypeおよび非限定ワイルドカードタイプでの動作は同じである.上記のコードでは、
O
タイプがSet
であることを確認し、Set<?>
に変換する.(プロトタイプSet
ではありません.)これは、コンパイラの警告が発生しないチェック変換です.整理する
プロトタイプは互換性のために残されただけです.使用すると、実行中に異常が発生する可能性がありますので、使用しないでください.ただし、
class
literalおよびinstanceof
演算子ではrotypeを使用します.Reference
この問題について([効果java]アイテム26|のタイプは使用しないでください), 我々は、より多くの情報をここで見つけました https://velog.io/@alkwen0996/이펙티브-자바-아이템26-로-타입은-사용하지-말라テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol