3

I have a parameterized interface RestHandler.

public interface RestHandler<T> {
   blah blah blah...
}

And I need to create a class from config using Class.forName. Now I come up with three version , which ALL compiles successfully.

Version 1:

@SuppressWarnings("unchecked")
public static <T> RestHandler<T> create(final String handlerImplFqcn) throws ClassNotFoundException, 
                                                                    IllegalAccessException, 
                                                                    InstantiationException {
    Class<?> handlerClass = Class.forName(handlerImplFqcn);
    return (RestHandler<T>) handlerClass.newInstance();
}

Version 2:

public static RestHandler<?> create(final String handlerImplFqcn) throws ClassNotFoundException, 
                                                                    IllegalAccessException, 
                                                                    InstantiationException {
    @SuppressWarnings("rawtypes")
    Class handlerClass = Class.forName(handlerImplFqcn);
    return (RestHandler<?>) handlerClass.newInstance();
}

Version 3:

public static RestHandler<?> create(final String handlerImplFqcn) throws ClassNotFoundException, 
                                                                    IllegalAccessException, 
                                                                    InstantiationException {
    Class<?> handlerClass = Class.forName(handlerImplFqcn);
    return (RestHandler<?>) handlerClass.newInstance();
}

My question is , why they ALL work and which one would be best practice ?

Levin Kwong
  • 393
  • 1
  • 3
  • 7
  • My personal preference is for the first example, though you shouldn't need the SuppressWarnings Annotation. Though you should note that it's possible to also throw ClassCastException in all of these examples. – Dave Feb 04 '15 at 11:06

2 Answers2

2

Version 1, re-written to this:

public static <T extends RestHandler<?>> RestHandler<T> create(final String handlerImplFqcn) throws ClassNotFoundException, IllegalAccessException, InstantiationException, ClassCastException {
    Class<T> handlerClass = (Class<T>) Class.forName(handlerImplFqcn);
    return (RestHandler<T>) handlerClass.newInstance();
}
Dave
  • 591
  • 2
  • 13
  • Do you mean `public static > T create(String handlerImplFqcn) throws IllegalAccessException, InstantiationException, ClassNotFoundException { Class handlerClass = (Class) Class.forName(handlerImplFqcn); return handlerClass.newInstance(); }` – Levin Kwong Feb 04 '15 at 11:21
0

Use version 1.

Version 2 uses raw types - avoid these if at all possible.

Version 3 uses <?> which is also often an anti pattern as it rarely achieves what you mean to achieve.

OldCurmudgeon
  • 64,482
  • 16
  • 119
  • 213