4

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,

ProgBear
  • 234
  • 2
  • 10

3 Answers3

3

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.

Bala R
  • 107,317
  • 23
  • 199
  • 210
0

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

Community
  • 1
  • 1
Jesper
  • 202,709
  • 46
  • 318
  • 350
0

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! :)

alpian
  • 4,668
  • 1
  • 18
  • 19