Why should I care that Java doesn't have reified generics?

后端 未结 13 713
予麋鹿
予麋鹿 2020-11-28 02:59

This came up as a question I asked in an interview recently as something the candidate wished to see added to the Java language. It\'s commonly-identified as a pain that Jav

相关标签:
13条回答
  • 2020-11-28 03:03

    Arrays would probably play much nicer with generics if they were reified.

    0 讨论(0)
  • 2020-11-28 03:04

    Serialization would be more straightforward with reification. What we would want is

    deserialize(thingy, List<Integer>.class);
    

    What we have to do is

    deserialize(thing, new TypeReference<List<Integer>>(){});
    

    looks ugly and works funkily.

    There are also cases where it would be really helpful to say something like

    public <T> void doThings(List<T> thingy) {
        if (T instanceof Q)
          doCrazyness();
      }
    

    These things don't bite often, but they do bite when they happen.

    0 讨论(0)
  • 2020-11-28 03:10

    Here's one that's caught me today: without reification, if you write a method that accepts a varargs list of generic items ... callers can THINK they're typesafe, but accidentally pass in any-old crud, and blow up your method.

    Seems unlikely that would happen? ... Sure, until ... you use Class as your datatype. At this point, your caller will happily send you lots of Class objects, but a simple typo will send you Class objects that don't adhere to T, and disaster strikes.

    (NB: I may have made a mistake here, but googling around "generics varargs", the above appears to be just what you'd expect. The thing that makes this a practical problem is the use of Class, I think - callers seem to be less careful :( )


    For instance, I'm using a paradigm that uses Class objects as a key in maps (it's more complex than a simple map - but conceptually that's what's going on).

    e.g. this works great in Java Generics (trivial example) :

    public <T extends Component> Set<UUID> getEntitiesPossessingComponent( Class<T> componentType)
        {
            // find the entities that are mapped (somehow) from that class. Very type-safe
        }
    

    e.g. without reification in Java Generics, this one accepts ANY "Class" object. And it's only a tiny extension of the previous code :

    public <T extends Component> Set<UUID> getEntitiesPossessingComponents( Class<T>... componentType )
        {
            // find the entities that are mapped (somehow) to ALL of those classes
        }
    

    The above methods have to be written out thousands of times in an individual project - so the possibility for human error becomes high. Debugging mistakes is proving "not fun". I'm currently trying to find an alternative, but don't hold much hope.

    0 讨论(0)
  • 2020-11-28 03:11

    The thing that most commonly bites me is the inability to take advantage of multiple dispatch across multiple generic types. The following isn't possible and there are many cases where it would be the best solution:

    public void my_method(List<String> input) { ... }
    public void my_method(List<Integer> input) { ... }
    
    0 讨论(0)
  • 2020-11-28 03:12

    Type safety comes to mind. Downcasting to a parametrized type will always be unsafe without reified generics:

    List<String> myFriends = new ArrayList();
    myFriends.add("Alice");
    getSession().put("friends", myFriends);
    // later, elsewhere
    List<Friend> myFriends = (List<Friend>) getSession().get("friends");
    myFriends.add(new Friend("Bob")); // works like a charm!
    // and so...
    List<String> myFriends = (List<String>) getSession().get("friends");
    for (String friend : myFriends) print(friend); // ClassCastException, wtf!? 
    

    Also, abstractions would leak less - at least the ones which may be interested in runtime information about their type parameters. Today, if you need any kind of runtime information about the type of one of the generic parameters you have to pass its Class along as well. That way, your external interface depends on your implementation (whether you use RTTI about your parameters or not).

    0 讨论(0)
  • 2020-11-28 03:13

    I have a wrapper that presents a jdbc resultset as an iterator, (it means I can unit test database-originated operations a lot easier through dependency injection).

    The API looks like Iterator<T> where T is some type that can be constructed using only strings in the constructor. The Iterator then looks at the strings being returned from the sql query and then tries to match it to a constructor of type T.

    In the current way that generics are implemented, I have to also pass in the class of the objects that I will be creating from my resultset. If I understand correctly, if generics were reified, I could just call T.getClass() get its constructors, and then not have to cast the result of Class.newInstance(), which would be far neater.

    Basically, I think it makes writing APIs (as opposed to just writing an application) easier, because you can infer a lot more from objects, and thereby less configuration will be necessary...I didn't appreciate the implications of annotations until I saw them being used in things like spring or xstream instead of reams of config.

    0 讨论(0)
提交回复
热议问题