1. 程式人生 > >Java中型別擦除與橋接方法

Java中型別擦除與橋接方法

型別擦除與橋接方法

Java中型別擦除與橋接方法

原文地址

  • Java語言是不根據返回值型別來判定是否為方法的過載的
    • 方法簽名 = 方法名 + 引數型別
  • 但是JVM卻是把返回值型別當做判定條件的
    • 方法簽名 = 方法名 + 引數型別 + 返回值型別

可能出現的問題.

  • 如果說子類重寫父類方法,返回值型別改變了.對於Java來講是重寫,但是對於JVM卻不是.
  • 另外在使用泛型時,父類T,子類重寫父類方法在型別擦除時,方法簽名也會改變.
  • 所以在子類重寫父類方法時,如果有上述情況,則會出現橋接方法.

下面,我以型別擦除為例,簡單瞭解一下橋接方法

Node類

package bm;
public class Node<T> {
	public T data;
	public Node(T data){
		this.data = data;
	}
	public void setData(T data) {
		this.data = data;
		System.out.println("Node: data = "
+data); } }

MyNode類

package bm;
public class MyNode extends Node<Integer>{
	public MyNode(Integer data) {
		super(data);
	}
	public void setData(Integer data){
		System.out.println("Node: data = "+data);
	}
}

測試程式碼

public static void main(String[] args) {
    MyNode myNode = new MyNode
(12); //原始型別,會有個warning Node node = myNode; //型別轉換異常 node.setData("hello"); Integer x = myNode.data; }

在型別擦除之後,上面的程式碼變成了

public static void main(String[] args) {
    MyNode myNode = new MyNode(12);
    //原始型別,會有個warning
    Node node = (MyNode)myNode;
    node.setData("hello");
    //型別轉換異常
    Integer x = (String)myNode.data;
}

錯誤的原因

  • 就是型別轉換錯誤.node引用了myNode
  • 雖然呼叫了setData(),但是是父類的.

型別擦除後的兩個類

Node中的泛型引數T 變成了 Object
這樣MyNode就不再是重寫父類的方法了

public class Node {
    public Object data;
    public Node(Object data) { this.data = data; }
    public void setData(Object data) {
        this.data = data;
    }
}

public class MyNode extends Node {
    public MyNode(Integer data) { super(data); }
    public void setData(Integer data) {
        super.setData(data);
    }
}

為了解決這種情況和維持多型性,所以編譯器就提供了橋接方法(自動生成)

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);
    }

    // ...
}