効果java item 29.それなら、ジェニーンリックのタイプにしましょう.

16696 ワード

item29. それなら、ジェニーンリックのタイプにしましょう。

public class Stack {
	private Object[] elements;
    private int size = 0;
    private static final int DEFAULT_INITIAL_CAPACITY = 16;
    
    public Stack() {
    	elements = new Object[DEFAULT_INITIAL_CAPACITY];
    }
    
    public void push(Object e) {
    	ensureCapacity();
        elements[size++] = e;
    }
    
    public Obejct pop() {
    	if (siez == 0)
        	throw new EmptyStackException();
        Object result = elements[--size];
        elements[size] = null; //다 쓴 참조 해제
        return result;
    }
    
    public boolean isEmpty() {
    	return size == 0;
    }
    
    private void ensureCapacity() {
    	if (elements.length == size)
        elements = Arrays.copyOf(elements, 2 * size + 1);
    }
}
一般クラスをJENICクラスの第一歩にする.
クラス宣言にタイプパラメータを追加します.
要素タイプを追加するだけでスタックができます.
->タイプ名は通常Eを使用します(プロジェクト68)
->オブジェクトを適切なタイプのパラメータに変換します.
public class Stack<E> {
	private E[] elements;
    private int size = 0;
    private static final int DEFAULT_INITIAL_CAPACITY = 16;
    
    public Stack() {
    	elements = new E[DEFAULT_INITIAL_CAPACITY];
    }
    
    public void push(E e) {
    	ensureCapacity();
        elements[size++] = e;
    }
    
    public E pop() {
    	if (size == 0)
        	throw new EmptyStackException();
        E result = elements[--size];
        elements[size] = null;  // 다 쓴 참조 해재ㅔ
        return result;
    }
    ...// isEmpty와 ensureCapacity 메서드는 그대로
}
これによりエラーが発生します.
Eなどの非実体化タイプではアレイを作成できません
解決策は.
elements = (E[]) new Object[DEFAULT_INITIAL_CAPACITY];
ギネス世界記録の生成を禁止する制限を堂々と迂回する方法.
->オブジェクトアレイを作成し、ジェネリックアレイに変換します.
->あまり安全でない方法
//배열 elements는 push(E)로 넘어온 E 인스턴스만 담는다.
//따라서 타입 안전성을 보장하지만,
//이 배열의 런타임 타입은 E[]가 아닌 Object[]다!
@SuppressWarnings("unckecked")
public Stack() {
	elements = (E[]) new Object[DEFAULT_INITIAL_CAPACITY];
}
elementsフィールドのタイプをE[]からObjectに変更する方法
E result = elements[--size]
public E pop() {
	if (size == 0)
    	throw new EmptyStackException();
        
    //push에서 E 타입만 허용하므로 이 형변환은 안전하다.
    @SuppressWarnings("unchecked") E result = (E) elements[--size];
    
    elements[size] = null;  // 다 쓴 참조 해제
    return result;
}
第一の方法
  • は毒性が良い.
  • コードもより短い
  • は業界に人気があり、
  • をよく使用しています.
  • アレイの稼働時タイプとコンパイル時タイプが異なり、臀部汚染を引き起こす
  • public static void main(String[] args) {
    	Stack<String> stack = new Stack<>();
        for (String arg : args)
        	stack.push(arg);
        while (!stack.isEmpty())
        	System.out.println(stack.pop().toUpperCase());
    }
    コマンドラインパラメータを逆順序で大文字出力に変換するプログラム.
    Generic Stackクラスを使う様子
    Stackから取り出した要素がStringのtoUpperCaseメソッドを呼び出す場合、明示的な変換は実行されません.
    (コンパイラによって自動的に生成される)異形変換が常に成功していることを確認します.
  • DelayQueue(拘束タイプパラメータのGenericタイプ)
    https://runebook.dev/ko/docs/openjdk/java.base/java/util/concurrent/delayqueue
  • ClassCastException
    https://shs2810.tistory.com/15
  • コアの整理
    Genericタイプは、クライアントで直接変換する必要があるタイプよりも安全で使いやすいです.新しいタイプを設計するときは、形を変えずに使用します.
    そうするなら、ジェネリックタイプにすることが多い.
    既存のタイプの中にジェニーンリックのはずがあるとすれば、ジェニーンリックのタイプに変えましょう.
    これは、既存のクライアントに影響を及ぼさずに、新しいユーザーをより楽にする方法です.(アイテム26)