I'm building an API, which uses abstract classes, to invoke static methods. Some Java Pseudocode:
public abstract class APIBaseClass {
public static List<?> myMethod(Class<?> clazz, MyConverter converter, List<Object> objects) {
return objects.stream()
.map(object -> converter.convertObjectToType(object, clazz))
.collect(Collectors.toList());
}
}
And, where myMethod
is invoked:
public abstract class MyAPIClass extends APIBaseClass {
public static List<MyClassType> invokingMethod(MyConverter converter, List<Object> objects) {
List<MyClassType> list = myMethod(MyClassType.class, converter, objects);
...
return list;
}
}
myMethod
compiles, as expected. And, invokingMethod
does not compile, also as expected, due to incompatible types:
Required: List<blah.blah.blah.MyClassType>
Found: List<capture<?>>
It compiles without errors or warnings if I: (1) @SuppressWarnings("unchecked") on invokingMethod
, and (2) cast the result of myMethod
to a list of MyClassType
, when invoked, i.e. List<MyClassType> list = (List<MyClassType>) myMethod(MyClassType.class, converter, objects);
. However, there's no transparency that this would be necessary to anybody using the API, which feels less than ideal.
What are my options for myMethod
returning the a list of the type it is invoked with to invokingMethod
, while maintaining my abstract classes and static methods, while ideally improving usability within invokingMethod
?
Any suggestions or alternative ideas are welcome.
Thanks in advance.
The fact that your classes are abstract is completely irrelevant. If you make them abstract to prevent their instantiation, and use inheritance to avoid having to specify the class name, then that's an antipattern, which doesn't use abstract classes for polymorphism as they're intended to be used. Just add a private constructor to the classes, and use static imports.
Now, regarding the question itself, you need to make the method generic, and the MyConverter.convertObjectToType()
method generic, too:
public static <T> List<T> myMethod(Class<T> clazz, MyConverter converter, List<Object> objects) {
return objects.stream()
.map(object -> converter.convertObjectToType(object, clazz))
.collect(Collectors.toList());
}