javaの一般的なタイプの消去と橋の方法を詳しく説明します。
Javaでは、汎型の導入は、コンパイルの際に強力なタイプの検査と汎型プログラミングをサポートするためである。汎型を実現するために、Javaコンパイラアプリケーションのタイプ消去が実現されます。
1、 タイプパラメータ(type parameters)の定義(なければObject)で、汎型のすべてのタイプのパラメータを置換します。
2、 タイプを安全に保つ必要がある場合は、タイプ変換(暗黙挿入)を挿入します。
3、 多形性を保証するために、extented汎型で橋を生成する方法
タイプ消去は、パラメータ化されたタイプには新しいタイプが発生しないことを確保します。このように汎型は運転時の負荷がないことを保証します。
一般タイプの消去
タイプ消去中に、Javaコンパイラはすべてのタイプのパラメータを消去し、その限定またはObject(無制限のタイミング)で置換します。
次の汎型類を考慮します。
タイプ消去の影響とブリッジの方法
タイプが消去されると予知できない場合があります。たとえば:
次の2つのクラスを指定します。
この問題を解決するために、汎型の多形性を維持するために、javaコンパイラは橋の方法を生成する。
1、 タイプパラメータ(type parameters)の定義(なければObject)で、汎型のすべてのタイプのパラメータを置換します。
2、 タイプを安全に保つ必要がある場合は、タイプ変換(暗黙挿入)を挿入します。
3、 多形性を保証するために、extented汎型で橋を生成する方法
タイプ消去は、パラメータ化されたタイプには新しいタイプが発生しないことを確保します。このように汎型は運転時の負荷がないことを保証します。
一般タイプの消去
タイプ消去中に、Javaコンパイラはすべてのタイプのパラメータを消去し、その限定またはObject(無制限のタイミング)で置換します。
次の汎型類を考慮します。
public class Node<T> {
private T data;
private Node<T> next;
public Node(T data, Node<T> next) }
this.data = data;
this.next = next;
}
public T getData() { return data; }
// ...
}
タイプパラメータTは限定されていないので、JavaコンパイラはObjectを使って置換します。
public class Node {
private Object data;
private Node next;
public Node(Object data, Node next) {
this.data = data;
this.next = next;
}
public Object getData() { return data; }
// ...
}
以下の例では、汎型Node類は、限定型パラメータを使用しています。
public class Node<T extends Comparable<T>> {
private T data;
private Node<T> next;
public Node(T data, Node<T> next) {
this.data = data;
this.next = next;
}
public T getData() { return data; }
// ...
コンパイラは最初の限定クラスを使用します。限定パラメータタイプをComprableに置き換えます。
public class Node {
private Comparable data;
private Node next;
public Node(Comparable data, Node next) {
this.data = data;
this.next = next;
}
public Comparable getData() { return data; }
// ...
}
同様に、一般的な方法でも消去できます。ルールは似ています。詳しくは言いません。タイプ消去の影響とブリッジの方法
タイプが消去されると予知できない場合があります。たとえば:
次の2つのクラスを指定します。
public class Node<T> {
public T data;
public Node(T data) { this.data = data; }
public void setData(T data) {
System.out.println("Node.setData");
this.data = data;
}
}
public class MyNode extends Node<Integer> {
public MyNode(Integer data) { super(data); }
public void setData(Integer data) {
System.out.println("MyNode.setData");
super.setData(data);
}
}
以下のコードを考慮します。
MyNode mn = new MyNode(5);
Node n = mn; // C
n.setData("Hello");
Integer x = mn.data; // ClassCastException
タイプが消去されると、コードは次のようになります。
MyNode mn = new MyNode(5);
Node n = (MyNode)mn; // C
n.setData("Hello");
Integer x = (String)mn.data; // ClassCastException
public class Node {
public Object data;
public Node(Object data) { this.data = data; }
public void setData(Object data) {
System.out.println("Node.setData");
this.data = data;
}
}
public class MyNode extends Node {
public MyNode(Integer data) { super(data); }
public void setData(Integer data) {
System.out.println("MyNode.setData");
super.setData(data);
}
}
タイプが消去された後、メソッドの署名はマッチしませんでした。Node方法はsetData(Object)になり、MyNode方法はsetData(Integer)になります。MyNode setDataメソッドはもはやNode setDataをカバーする方法ではない。この問題を解決するために、汎型の多形性を維持するために、javaコンパイラは橋の方法を生成する。
class MyNode extends Node {
//
//
public void setData(Object data) {
setData((Integer) data);
}
public void setData(Integer data) {
System.out.println("MyNode.setData");
super.setData(data);
}
// ...
読んでくれてありがとうございます。みなさんのご協力をお願いします。ありがとうございます。