12

I'm currently learning java generics and below is a list of types in java that is non-reifiable.

A type is not reifiable if it is one of the following:

• A type variable (such as T)

• A parameterized type with actual parameters (such as List<Number>, ArrayList<String>, or Map<String, Integer>)

• A parameterized type with a bound (such as List<? extends Number> or Comparable<? super String>)

I understand why parameterized type with actual parameter and parameterized type with bound is non-refieable, because after runtime erasure, the only type information left is List, but why is type variable (such as T) a non-reifiable type? I thought at runtime, after type erasure, T would become Object (given T is an unbound type parameter), so the type information is available.

Is there something wrong with my understanding?

Thor
  • 8,608
  • 10
  • 43
  • 113
  • Maybe [this](https://stackoverflow.com/questions/18848885/why-following-types-are-reifiable-non-reifiable-in-java) question's answers answer your question? It deals with the same problem. – Ben Jun 18 '18 at 05:23
  • That's exactly what it means. Instead of `T` being reified as the type it represents, it's erased to its upper bound. – shmosel Jun 18 '18 at 05:23
  • @Ben thanks for the suggestion, i have seen that particular post but was still confused after reading it. And my question is more focused on type parameter, so I guess the questions are similar but not exactly same. – Thor Jun 18 '18 at 05:26
  • @Thor yes, I figured, that's why I just suggested it over duping :) – Ben Jun 18 '18 at 05:26
  • @shmosel could you please explain it a bit more? what is wrong with the runtime type of the `new T[]` being `Object[]`? – Thor Jun 18 '18 at 05:33
  • @Ben thanks for the suggestion. really appreciate it :) – Thor Jun 18 '18 at 05:34
  • Not sure what you mean. Who said anything's wrong? – shmosel Jun 18 '18 at 05:34
  • @shmosel lets say `T[] t = new T[10];` is legal syntax (i know it is illegal), then the runtime type of `t` would be `Object[]`, which is perfectly valid java syntax, so why is `T` a non-reifiable type and why is `new T[]` illegal syntax? – Thor Jun 18 '18 at 05:37
  • I do apologise for the follow up questions if it is hard to understand, I'm simply too confused right now – Thor Jun 18 '18 at 05:39
  • It's slightly different. `T[] a = new Foo[0]` is `T[]` at compile time but it is a `Foo[]` at runtime. `Object[] a = new Foo[0]` doesn't work as well. `T` matches *a particular type*, but you shouldn't think that it is matching *any* type of `Object`. – Jai Jun 18 '18 at 05:39
  • 1
    It's non-reifiable because it's not preserved at runtime. That's what non-reifiable means. As to why `new T[]` is illegal, it's because array types *are* reified, and mixing arrays with generics can cause heap pollution. Consider `T[] t = new T[10]; Object[] o = t; o[0] = 1;`. If you replaced `T` with `String`, this would throw an `ArrayStoreException`. But if `T` is a generic type that gets erased to `Object`, the code would run without error, despite possibly violating generic invariants. You can easily test this by casting an `Object[]` to `T[]`. – shmosel Jun 18 '18 at 05:50
  • In java you also can't do new T(), because you don't know if T has a parameterless constructor, that's why this is disallowed, because you don't have that type information about T. I could have made that constructor private, for example. – Coder-Man Jun 18 '18 at 06:30
  • @POrekhov Nobody mentioned `new T()`. – shmosel Jun 18 '18 at 06:32
  • @shmosel so what? It is related, I said it as a "by the way" thing, why are you so judgemental all the time? – Coder-Man Jun 18 '18 at 06:34
  • @POrekhov Because without making several hundred if not thousand judgments per day a human being cannot survive, let alone function, let alone act as a professional in an intellectually demanding occupation. I first heard that particular nonsense in 1970 and I recognized it then for the arrant BS that it is. Nothing has changed. As for your specific point, the issue of not knowing what `T` actually is because it has been erased at compile time is logically prior to the issue of whether it has a no-args constructor. – user207421 Jun 21 '18 at 09:58

2 Answers2

5

An object is reifiable when its typing information is not lost at compile time. Some operations are not allowed on non-reifiable objects. For example, we can not do an instance of.

Generic types are not reifiable and that's why we can not do such a

 List <Conference> instance

This would be practical in some cases but we must not forget that the JDK must be backward compatible from one version to another. This constraint explains some limitations in implementations.

A Java type is reifiable if it is represented completely during execution (without erasure Of type) :

 primitive type
 non-parametric type
 parametric type in which all arguments of type are unbounded jokers (List <?>)
 type "raw" (List)
 table whose type of elements is reifiable

I don't know if this can help you, I can delete it if not, have nice day !

Adam Perea
  • 135
  • 8
2

The docs state that

A non-reifiable type does not have all of its information available at runtime.

The type of T at runtime is Object so information is lost. An example of the information that is lost is how an object can be created. Consider this class:

public class A {
    private int a;
    public A() {
        a = 5;
    }
}

Now look at this not compiling code:

public class Generic<T> {
    T foo() {
        return new T(); //Compiler Error!
    }
}

If this was allowed and you were instantiating a Generic<A> g = new Generic<>(); and calling g.foo(), the constructor of T could not be called, because, at runtime, T is only known as Object. Therefore, an valid instance of A cannot be created and returned. You even cannot be sure which information a constructor of T needs. The information how T can be constructed is lost.

That is one reason why type parameters must be non-reifiable types.

Tobias
  • 106
  • 8