问题
The code following is taken from Oracle documentation of generics -
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;
}
}
class MyNode extends Node<Integer> {
public MyNode(Integer data) { super(data); }
public void setData(Integer data) {
System.out.println("MyNode.setData");
super.setData(data);
}
public static void main(String[] args) {
MyNode mn = new MyNode(5);
Node n = mn; // A raw type - compiler throws an unchecked warning
n.setData("Hello");
Integer x = mn.data; // Causes a ClassCastException to be thrown.
}
}
My understanding of this code -
Q - is method setData
overrided or overloaded?
my under standing - because MyNode
is extending Node<Integer>
, the value of type parameter T
is set to Integer
.
so class Node
has method setData(Integer data)
as T= Integer
and class MyNode
has method setData(Integer data)
.
It is overriding as signature is same.
Q- is the method setData Overrided even after Erasure? My understanding -
after we erase <T>
the set method becomes in Node
becomes, setData(Object data)
and the set method of Mynode
will be - setData(Integer data)
as there is no type parameter, nothing to remove.
But this is overloading.
Q - we wanted overloading or overriding?
My understanding - by the looks of methods defined before erasure, we wanted overriding.
Q - So how to achieve Overiding after Erasure?
My understanding - By Bridging Method. for example:
setData(Object data){
setData((Integer) Data);
}
Is my understanding correct?
Also, class MyNode extends Node<Integer>
when does Integer
is passed down to <T>
? when super is called?
回答1:
- Yes, the method
setData
is overridden. From the point of view of the user, it will look as if
setData(T data)
is overridden bysetData(Integer i)
, i.e. when you invokesetData(42)
, it will print something with "MyNode", not with "Node".On the level of type erased method signatures, this will be achieved by a synthetic bridge method
setData(Object)
added toMyNode
, i.e. if you decompileMyNode.class
withjavap
, you will see two methods:public void setData(java.lang.Integer); public void setData(java.lang.Object);
The language spec says "override", I don't know why anyone would want something else.
It's not clear what you mean by "achieve overriding after erasure". The type erasure comes after the type checking and determining what overrides what. There is nothing to "achieve", it's just the order in which things work (see also this comment). The synthetic bridging method that overrides the original
setData(Object)
looks like what you wrote (up to minor typos):setData(Object data){ setData((Integer) data); }
at least that's what the documentation says. But this is a synthetic method, it is generated by the compiler automatically. If it appeared in the source code, it would give you compilation errors.
来源:https://stackoverflow.com/questions/55783070/erasure-type-and-bridging-method-clarification