ProgBear
ProgBear

Reputation: 244

Question about java generics

I am writing this query service that's suppose to work with couple predefined classes. However, it seems to me to be redundant that, when using this service class, I need to pass both the Type of the class and a class object it self. For example, to query "Contact" object, I'll need to provide both and Contact.class, like the following:

lookupService = new MyLookupServiceImpl<Contact>(Contact.class);

In this case, is there a way to initialize Class without passing in "Contact.class"? The service class look like the following:

public class MyLookupServiceImpl<T> {
private Class<T> cls;

public MyLookupServiceImpl(Class<T> clz){
    this.cls = clz;
}

public T queryObject(String sql) {
    try {
        QueryResult result = ConnectionFactory.getConnection().query(sql);
        if(result.getSize()>0){
            T obj=null;
            MyObject sObj = result.getRecords()[0];
            MyObjectBuilder<T> ob = new MyObjectBuilder<T>(cls);
            obj = ob.buildORMObject(sObj);
            return obj;
        }
    } catch (ConnectionException e) {
        logger.warn(e.toString());
    }
    return null;
}
}

Any suggestion would be appreciated.

Thank you,

Upvotes: 4

Views: 112

Answers (3)

alpian
alpian

Reputation: 4748

Bala is correct (+1) unfortunately. However, if you use a Dependency Injection framework like Guice you could ask Guice to pass you a TypeLiteral which is the type you're interested in. You could do something like this:

public class MyLookupServiceImpl<T> {
    private Class<T> cls;

    @Inject
    public MyLookupServiceImpl(TypeLiteral<T> type){
        this.cls = (Class<T>)type.getRawType();
    }
}

Then use the Guice Injector to pass you instances of MyLookupServiceImpl. Just an idea! :)

Upvotes: 0

Jesper
Jesper

Reputation: 206796

This is most likely necessary because it is not possible to create a new instance of an arbitrary class indicated by a type parameter; in other words, you cannot do:

T obj = new T();

because of the way Java generics are implemented (with type erasure).

Note that in your code, cls is passed to MyObjectBuilder<T> which is most likely an object that creates new instances of T. MyObjectBuilder<T> uses reflection to create a new instance of T, with a statement like this:

T obj = cls.newInstance();

See also: Create new instance of T in Java

Upvotes: 0

Bala R
Bala R

Reputation: 108947

The answer is NO. In java, because of type erasure, there is no other way infer/get this info at runtime other that passing in the type info as a Class<?> instance.

Upvotes: 3

Related Questions