Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does Java's type erasure not break this?

Tags:

java

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<Integer>. However, since 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?

like image 974
Kevin Avatar asked Aug 03 '13 02:08

Kevin


People also ask

What is the advantage of type erasure?

Type erasure ensures that no new classes are created for parameterized types; consequently, generics incur no runtime overhead.

How does type erasure work?

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.

What are the two 2 types of Erasure?

- Erasure is a type of alteration in document. It can be classified as chemical erasure and physical erasure.

How does type erasure works in Java?

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.


2 Answers

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.

like image 155
Sergey Kalinichenko Avatar answered Sep 27 '22 22:09

Sergey Kalinichenko


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.

like image 38
S.D. Avatar answered Sep 27 '22 23:09

S.D.