Runtime-Generics

I’m a heavy user of generalized classes and interfaces in Java.Sadly, the generalization is only for compile-time checks. But because you can cast any parameterized class-instance to an unchecked instance you can fool the system. This can be very annoying if a class-cast exception occurs later. For example with collections, the ClassCastException happens somewhere later and the stacktrace points to the wrong location.

Well for Collections there is a simple solution available. You can create runtime-checked Collections with the Collections-class

    List<String> test = Collections.checkedList(new ArrayList<String>(),String.class);
    List somewhereElse = test;
    somewhereElse.add(44); // Here the ClassCastException will be thrown

The bad thing is, this is made just for collections. Now I’m thinking about creating an small library, which can create runtime-checks for any interface. Since I saw the little trick on the Google-Guice-library, this seems to be solvable. Sure, you have to use some dirty tricks to archive this goal, but maybe it is realizable.

The following code-snippet shows, what I’m thinking of:

    // This is our target-type
    Task<Map<String, ?>, List<? extends InputStream>> targetType;

    // To create in the code, we create an inner-class of the Type-interface.
    //  This type will be interpreted by the system to create the typed version.
    //  Then we bind it the the normal implementation class and create an instance at the end.
    targetType =
          RuntimeTypeSave.create(new Type<Task<Map<String, ?>, List<? extends InputStream>>>() {})
                  .bindTo(new HashMap())
                  .createInstance();

And the code for more dynamic creation, for example when you create a typed based on configuration:

    // There has to be a possibility to create the same type complete dynamically.
    //  Because the type may get constructet depending on a configuration.

    // Build the first parameter The Type.ANY_TYPE represents the ? on the parameterlist.
    Builder<Map> firstParam = RuntimeTypeSave.getBuilder(Map.class);
    Type firstType = firstParam.setParameters(String.class, Type.ANY_TYPE.class).createType();

    // Create the second parameter
    Builder<List> secondParam = RuntimeTypeSave.getBuilder(List.class);
    Type secondType = secondParam.extendsFrom(InputStream.class).createType();

    // Create the final type
    Type<Task> finalType = RuntimeTypeSave
        .getBuilder(Task.class).setParameters(firstType, secondType)
        .createType();

    // Ugly cast =(
    targetType = (Task<Map<String,?>, List<? extends InputStream>>) RuntimeTypeSave.create(finalType).
                   bindTo(new TaskImpl()).createInstance();

Leave a Reply

Your email address will not be published. Required fields are marked *