Avoid repeating type names for generic functions that take a Class/GenericType param

Tags: java generics
Question!

Given functions such as the following using GenericType, or even just Class<T>, which I often see with serialization code (JSON, XML, etc.), is it possible to write it in such a way that I do not have to write the full (and sometimes long) type multiple times?

e.g. like the Java diamond operator when creating collections, or the C++ 11 auto keyword. Or even just a C style typedef style solution (so I can create a shorter name, maybe by using a null initialized variable instance?).

//What I want to avoid, long "GenericType" parameter
Map<EnterpriseId, List<EnterpriseUser>> usersByEnterprise = Json.readFile(data,
    new GenericType<Map<EnterpriseId, List<EnterpriseUser>>>() { } );

//Creating a container instance
Map<EnterpriseId, List<EnterpriseUser>> usersByEnterprise = new HashMap<>();


Answers

The problem is that you need a (reifiable) subclass to capture the actual type arguments, but Java 8 strictly specifies the requirement to list the type arguments explicitly for anonymous subclasses. What you can do, is to keep the instantiated type token, which might help, if you need exactly the same type multiple times, e.g.

static final GenericType<Map<EnterpriseId, List<EnterpriseUser>>> MAP_ID_USER
       = new GenericType<Map<EnterpriseId, List<EnterpriseUser>>>() { };

…

Map<EnterpriseId, List<EnterpriseUser>> usersByEnterprise=Json.readFile(data, MAP_ID_USER);

If you don’t like having a static variable floating around, you may recall, that the class doesn’t have to be anonymous to serve as type token, e.g.

public final class MapIdUser extends GenericType<Map<EnterpriseId, List<EnterpriseUser>>> {
}
…

Map<EnterpriseId, List<EnterpriseUser>> usersByEnterprise
                                      = Json.readFile(data, new MapIdUser());

As said, this all helps only, if a particular type occurs multiple times in your project.


That said, not all hope is lost and there’s a better future in sight. Java 9 is supposed to lift the restrictions for type inference on anonymous class instantiations. So in Java 9, you’ll be able to write:

Map<EnterpriseId, List<EnterpriseUser>> usersByEnterprise
                                      = Json.readFile(data, new GenericType<>() { } );

In current snapshots this is already working…

By : Holger


You can write:

Map usersByEnterprise = new HashMap();

And use what's called a 'raw type'. This avoids the generic type information but also throws away compile time safety on the map contents. It is probably flagged by your IDE and by Sonar as a code violation, since we generally agree that generic typing is a Good Idea.

Otherwise you are stuck with the generic types, although you could opt for some shorter names, for example:

Map<Id, List<User>> usersByEnterprise = new HashMap<>();


Use Stuff Function:

DECLARE @tblTest AS Table(
    ID INT,
    EVENT VARCHAR(5)
)

INSERT INTO @tblTest VALUES
(1,'A'),
(1,'A'),
(1,'C'),
(2,'A'),
(2,'B'),
(2,'C')

SELECT DISTINCT
    T1.ID,
    STUFF
    (
         (SELECT '' + convert(varchar(10), T2.EVENT, 120)
          FROM @tblTest T2
          where T1.ID = T2.ID
          FOR XML PATH (''))
    , 1, 0, '')  AS EVENT
FROM @tblTest T1


This video can help you solving your question :)
By: admin