public class Test {
public static class Nested<T> {
public T val;
Nested(T val) { this.val = val; }
}
public static void main(String[] args) {
Nested<Integer> a = new Nested<Integer>(5);
Nested<Integer> b = new Nested<Integer>(2);
Integer diff = a.val - b.val;
}
}
The above code works fine. However, if I add a method to Nested:
T diff(Nested<T> other) { return this.val - other.val; }
I get a compilation error:
operator - cannot be applied to T,T
This makes sense to me. The type of T gets erased at runtime, so Java can't apply an operator that's only defined for certain classes like Integer. But why does a.val - b.val
work?
Edit:
Lots of good answers. Thanks everyone. The gist of it, if I understand correctly, is that the compiler can add casts to Integer in a.val - b.val
because it knows a
and b
were instantiated as as Nested
. However, since <Integer
>this.val - other.val
occurs inside the body of a generic function definition (where T still could be anything), the compiler cannot add the casts that would be necessary to make "-
" work. This leads to a more interesting question, namely, if the Java compiler were capable of inlining, would it be possible for a generic function like diff to work?
Type erasure ensures that no new classes are created for parameterized types; consequently, generics incur no runtime overhead.
What Is Type Erasure? Type erasure can be explained as the process of enforcing type constraints only at compile time and discarding the element type information at runtime. Therefore the compiler ensures type safety of our code and prevents runtime errors.
- Erasure is a type of alteration in document. It can be classified as chemical erasure and physical erasure.
Type erasure is a process in which compiler replaces a generic parameter with actual class or bridge method. In type erasure, compiler ensures that no extra classes are created and there is no runtime overhead.
The difference between the two is whether you are inside a generic method or you are outside of it.
You got it absolutely right that inside the method T
is not known to be an Integer
, so operator minus -
cannot be applied. However, when you are in main()
, outside the generic method, the compiler knows that you've instantiated Nested
with Integer
, so it knows very well how to apply the operator. Even though the implementation of the generic has erased the type to produce the code for Nested<T>
, the compiler does not think of a
and b
in terms of Nested<T>
: it has enough knowledge to insert an appropriate cast, unbox the results, and apply the minus -
operator.
You are getting a compile-time error, not a runtime one.
public static void main(String[] args) {
Nested<Integer> a = new Nested<Integer>(5);
Nested<Integer> b = new Nested<Integer>(2);
Integer diff = a.val - b.val;
}
Here, compiler knows that both T
are Integer
. You just declared <Integer>
.
T diff(Nested<T> other) { return this.val - other.val; }
Here, compiler is not certain about T
. It could be anything. And, numeric only operator -
is not allowed for just anything.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With