Use Method of generic type - java

I am currently writing an XML converter for a supply chain project. We use Requests and Orders.
The converter has multiple method that currently do same but are separately implements for requests and orders.
I have therefore created an abstract class to improve maintainability of the code and used a generic type:
public abstract class AbstractConverter<T extends BusinessObject>
Then I have the specific implementations for the actual converters
public class OrderConverter extends AbstractConverter<Order>
public class RequestConverter extends AbstractConverter<Request>
As I said, I have several methods in the two specific classes that basically do the same, so I naturally want them in the abstract class. I have now added the following method to the abstract class:
protected Comment createComment(T obj) {
String remark;
if (obj instanceof Order) {
remark = ((Order) obj).getRemark();
} else if (obj instanceof Request) {
remark = ((Request) obj).getRequestRemark();
} else {
throw new IllegalArgumentException("This method does not support objects of the type " + obj.getClass().toString());
}
return new Comment(remark);
}
My question now is: is this the way to go or is there a more elegant way to use generics in this context?
I need this solved but I also want to use good style.

The natural object oriented solution is to make createComment an abstract method
protected abstract Comment createComment(T obj);
and let the subclasses implement it:
public class OrderConverter extends AbstractConverter<Order> {
protected Comment createComment(Order order) {
return new Comment(order.getRemark());
}
}
public class RequestConverter extends AbstractConverter<Request> {
protected Comment createComment(Request request) {
return new Comment(request.getRequestRemark());
}
}

I'd suggest extracting the getRemark method to an interface which both Request and Order implements.
That way you can simply check if the incoming generic object is an instance of the interface.
protected Comment createComment(T obj) {
if (obj instanceof Remarkable) {
return new Comment(((Remarkable) obj).getRemark());
}
throw new IllegalArgumentException("This method does not support objects of the type " + obj.getClass().toString());
}

Related

JDBI3 Returning a Parameterized Class

I have an abstract EntryPoint class that looks like this:
public abstract class EntryPoint<T extends Tag> implements Serializable {
public EntryPoint(){}
protected ArrayList<T> tiedTags;
public abstract ArrayList<T> getTiedTags();
public abstract void setTiedTags(List<T> tiedTags);
}
I then have subclasses of this EntryPoint class that each accept only one kind of Tag. For instance an SNMPEntryPoint only stores SNMPTags. The subclasses provide implementations of the abstract methods:
public class SNMPEntryPoint extends EntryPoint<SNMPTag> implements Serializable {
//Default Constructor for Serialization
public SNMPEntryPoint(){}
#Override
public ArrayList<SNMPTag> getTiedTags(){ return tiedTags; }
//etc
}
Is there a means to create a JDBI query that returns a List of parameterized classes? At the moment, this is what I'm doing:
public List<SNMPEntryPoint> getSNMPEntryPoints(){
try(Handle handle = daoFactory.getDataSourceController().open()) {
return handle.createQuery("SELECT * FROM dbo.EntryPoints WHERE Active = 1 AND SiteID = :sID AND Protocol = 'SNMP'")
.mapToBean(SNMPEntryPoint.class)
.list();
}
catch(Exception e){
if(sysconfig.getVerbose()){ e.printStackTrace(); }
}
return null;
}
But this feels like a raw use of the class. So I guess my question is, if I use this code to generate SNMPEntryPoints and then call getTiedTags or setTiedTags on those EntryPoints, will that work? Am I breaking any coding conventions by creating my SNMPEntryPoint objects in this way?
Just wanted to close this out. My classes weren't actually parameterized. As you can see above they extend the parameterized abstract class however SNMPEntryPoint doesn't actually take any parameters, so there's no need to do anything differently from what I'm doing above.
HOWEVER, if you do need to return a parameterized generic from JDBI you can do so using the details found here.

How can i make an interface in java with a function that accepts a parameter of the type that extends the interface?

How can i make an interface in java with a function that accepts a parameter of the type that extends the interface?
For example take the interface ISelfComparable
if class A extends it then i would expect it to implement
bool compareTo(A other)
but if class B extends it then i would expect it to implement
bool compareTo(B other)
I know i can use a generic interface but it seems incorrect because it doesn't make any sense for A to extend ISelfComparable<B>
If this is impossible, what is the best practice in this kind of situation?
The usual solution is self-bounded generics, as seen in the Enum class.
interface Example<T extends Example<T>> {
void foo(T t);
}
public class ExampleImpl implements Example<ExampleImpl> {
#Override
public void foo(ExampleImpl example) {
}
}
How it works is a bit dizzying, but is explained very well here for example. There is also a very good answer on the subject here.
Note that it isn't foolproof, as it allows this:
public class ExampleImpl2 extends Example<ExampleImpl {
#Override
public void foo(ExampleImpl example) {
}
}
But in practice the self-bounded idiom is used to express exactly the sort of thing you're after.
If you really, really, really need the parameter object to always be the exact same class as this, you have to do a runtime check. (It also raises the question of why you need this, but that would take us way off topic.)
Have a look at the class java.lang.Comparable: it has an argument with the type of the objects that can be used int compareTo.
By analogy:
public interface ISelfComparable<T extends ISelfComparable<T>> {
boolean compareTo(T other);
}
There is a way to check the type of parameter but only in runtime. For example you can implement type checking in default method:
interface ISelfComparable {
default boolean compareTo(ISelfComparable param) {
if (this.getClass() != param.getClass()) {
throw new IllegalArgumentException();
}
...
}
}
Then each implementation of this interface should look like this:
class A implements ISelfComparable {
#Override
public boolean compareTo(ISelfComparable param) {
ISelfComparable.super.compareTo(param);
...
}
}
In this case if you call new A().compareTo(new B()); then java.lang.IllegalArgumentException will be thrown

Java generic interface calling with abstract parameter

I know there's many similar question but I had no luck finding a nice and clean solution if it's possible at all.
I'm implementing a generic interface with subclasses of an abstract type. Problem is that when I'm calling them I either must do type cast in a switch/case or cast type in every method inside interface implementations and I can't figure out a nice and clean approach... I'll better just write down a short example.
// An abstract type with 2 implementations...
public abstract class ObjTypeAbstract {}
public class ObjType extends ObjTypeAbstract {}
public class ScriptType extends ObjTypeAbstract {}
Now the processor for both types with an interface
interface ProcessorInterface<T extends ObjTypeAbstract> {
public void abcMethod(T obj);
}
public class ObjProcessor implements ProcessorInterface<ObjType> {
public void abcMethod(ObjType obj) {}
}
public class ScriptProcessor implements ProcessorInterface<ScriptType> {
public void abcMethod(ScriptType obj) {}
}
What I'm struggling with is a way of calling those processors based on ObjAbstractType. I have a single class that servers as middleware?? or how should I call it.:
Idea was to simple get the right processor via a single switch/case:
public class Processor {
private ProcessorInterface objProcessor = new ObjProcessor();
private ProcessorInterface scriptProcessor = new ScriptProcessor();
public methodAbc(ObjAbstractType obj) {
getProcessor(obj).abcMethod(obj);
}
private ProcessorInterface getProcessor(ObjAbstractType obj) {
if (obj instanceof ObjType) {
return objectProcessor;
} else if (obj instanceof ScriptType) {
return scriptProcessor;
}
return nullProcessor;
}
}
This is what I'd like to have, it also takes care of type casting of objAbstract to actual type for abcMethod, problem is that it results in RawType warning which won't break the code, but I'd like to get rid of it.
And thats where I'm stuck... because if I cast processors to specific type like this:
private ProcessorInterface<ObjType> objProcessor = new ObjProcessor();
private ProcessorInterface<ScriptType> scriptProcessor = new ScriptProcessor();
I won't be able to return an abstract one from getProcessor method so I would have to implement those interfaces with an ObjAbstractType with all it's method and have type casting in all methods of every processor like:
public class ScriptProcessor implements ProcessorInterface<ObjAbstractType> {
public void abcMethod(ObjAbstractType obj) {
ScriptType scr = (ScriptType) obj;
}
}
The other solution might be having a switch/case inside Processor middleware class and cast ObjAbstractType in it, but I'd have to write that switch inside abcMethod and all others or from getProcessor method returns both the Processor and casted ObjType... so I'd have to return some dto containing both. :/
Do you have any ideas / patterns that might help me to get rid of RawType call warning without extending the code with more switch/case or type casts?
Wish you a nice day and I'll be glad for any discussion, David.
You need a way to store the mapping between a ObjTypeAbstract class and a ProcessorInterface instance.
You could use a Map that associates ObjTypeAbstracts (as key) to ProcessorInterfaces (as value).
About the raw type issue, you could use ProcessorInterface<? extends ObjTypeAbstract> for the declared variable but you will still need to perform a unsafe cast to ProcessorInterface<ObjTypeAbstract> to be able to invoke ProcessorInterface.abcMethod() with as parameter a ObjTypeAbstract declared type.
This cast is unavoidable with your actual design.
It could give something like :
public class Processor {
private Map<Class<? extends ObjTypeAbstract>, ProcessorInterface<? extends ObjTypeAbstract >> map = new HashMap<>();
public Processor(){
map.put(ObjType.class, new ObjProcessor());
map.put(ScriptType.class, new ScriptProcessor());
}
public void methodAbc(ObjTypeAbstract obj) {
#SuppressWarnings("unchecked")
ProcessorInterface<ObjTypeAbstract> processorInterface = (ProcessorInterface<ObjTypeAbstract>) map.get(obj.getClass());
processorInterface.abcMethod(obj);
}
}
I don't think there is a substantially more elegant way to get around some form of instanceof logic. However, there should not be need for casting, if you add some types to getProcessor.
public <T extends ObjTypeAbstract> ProcessorInterface<T> getProcessor(Class<T> theClass) {
if (theClass.isAssignableFrom(ObjType.class)) {
return objProcessor;
} else if (theClass.isAssignableFrom(ScriptType.class)) {
return scriptProcessor;
}
return null;
}
This can then be called like this:
ProcessorInterface<ScriptType> scriptProcessor = new Processor().getProcessor(ScriptType.class);
ProcessorInterface<ObjType> objProcessor = new Processor().getProcessor(ObjType.class);

Reference Object Through Its Implemented Generalized Interface [duplicate]

This question already has answers here:
Java generic interfaces with typesafe implementations
(2 answers)
Closed 8 years ago.
I have a converter interface that looks something like this:
public interface MyTypeConverter<T>
{
public MyObject toMyObject(T obj);
public T fromMyObject(MyObject mo);
}
I also have an implementation of that interface:
public class ABCTypeConverter implements MyTypeConverter<ABCObject>
{
public MyObject toMyObject(ABCObject obj)
{
...do conversion...
}
public ABCObject fromMyObject(MyObject mo)
{
...do conversion...
}
}
And a factory that evaluates the objects type, and returns an appropriate converter implementation:
public class MyTypeConverterFactory
{
public static MyTypeConverter<?> create(Object source)
{
if ( source instanceof ABCObject )
return new ABCTypeConverter();
...and so on...
}
}
Now the problem I am having is in referencing the Factory's returned converter instance by using the interface:
MyTypeConverter<?> converter = MyTypeConverterFactory.create(someObject);
MyObject mo = converter.toMyObject(someObject);
The last line gives me the following compile-time error:
The method toMyObject(capture#3-of ?) in the type MyTypeConverter<capture#3-of ?>
is not applicable for the arguments (ABCObject)
So how could I reference the converter in a generic fashion?
EDIT
The core of my question is: How do I call a method on an interface reference without first casting to the underlying concrete type? And if I can't, then what is the point of creating a generic interface to begin with? I.E., How do I do this (regardless of how I get the reference):
MyTypeConverter<?> converter = MyTypeConverterFactory.create(someObject);
MyObject mo = converter.toMyObject(someObject);
Without first casting "converter" to its underlying concrete type?
This is a total anti-pattern approach to the FactoryMethod Pattern:
if ( source instanceof ABCObject )
return new ABCTypeConverter();
...and so on...
Don't do that it will never scale and will never be maintainable.
What is wrong with:
TypeConverter<ABCObject> tc = new TypeConverter<ABCObject>();
That is how every sane framework that implements something like this works.
For example:
com.google.common.base.Converter
Look at the how Jackson does it for JSON Serializer/Deserializers as well.
There is a way with Guava to get an instance of a type T
Class<T> klass = (Class<T>) new TypeToken<T>(getClass()) {}.getRawType();
Then you can do klass.newInstance(); but this is hacky was well.
You can try with Polymorphism as well instead of making it Generic.
Just return the interface reference instead of actual object reference from factory's create() method. At run-time the actual object decide what method should be called based on overridden method logic.
In below sample code I have created an interface MyTypeConverterObject that is implemented by all the classes that are part of MyTypeConverter interface.
Now simply return MyTypeConverterObject from factory's create() method.
Sample code:
interface MyTypeConverterObject {}
class ABCObject implements MyTypeConverterObject {}
class XYZObject implements MyTypeConverterObject {}
class MyObject {}
interface MyTypeConverter {
public MyObject toMyObject(MyTypeConverterObject obj);
public MyTypeConverterObject fromMyObject(MyObject mo);
}
class ABCTypeConverter implements MyTypeConverter {
public MyObject toMyObject(MyTypeConverterObject obj) {
return new MyObject();
}
public MyTypeConverterObject fromMyObject(MyObject mo) {
return new ABCObject();
}
}
class MyTypeConverterFactory {
public static MyTypeConverter create(Object source) {
if (source instanceof ABCObject) {
return new ABCTypeConverter();
}
return ...;
}
}
A Factory method should return product of same type i.e. product that implements same interface.
For example: A car factory can return cars of different type but can't produce bike.
If you need to return different type of products then use Abstract factory.

Loading generic service implementations via java.util.ServiceLoader

I've stumbled upon some inconvenience the other day using java.util.ServiceLoader and some questions formed in me.
Suppose I have a generic service:
public interface Service<T> { ... }
I couldn't explicitly tell ServiceLoader to load only implementations with a specific generic type.
ServiceLoader<Service<String>> services =
ServiceLoader.load(Service.class); // Fail.
My question is: what are reasonable ways to use ServiceLoader to safely load implementations of a generic service?
After asking the above question and before PaĆ­lo's answer I've managed to come up with a solution.
public interface Service<T> { ...
// true if an implementation can handle the given `t' type; false otherwise.
public boolean canHandle(Class<?> t) { ...
public final class StringService implements Service<String> { ...
#Override public boolean canHandle(Class<?> t) {
if (String.class.isAssignableFrom(type))
return true;
return false;
}
public final class DoubleService implements Service<Double> { ...
// ...
public final class Services { ...
public static <T> Service<T> getService(Class<?> t) {
for (Service<T> s : ServiceLoader.load(Service.class))
if (s.canServe(t))
return s;
throw new UnsupportedOperationException("No servings today my son!");
}
Changing boolean canServe(Class<?> t) to boolean canServe(Object o) and also changing <T> Service<T> getService(Class<?> t) in the same manner can be more dynamic (I'm using the latter for myself as I had a method boolean canHandle(T t) on my interface in the beginning.)
The problem here is that the service loader is using a file listing all implementations of a given class/interface, the file being named by the interfaces name. It was not foreseen to put the type parameter into this file name, and it also is not really possible to pass generic types as Class objects.
So, you here can only get your generic services of any types, and then inspect their class object to see if it is a subtype of Service<String>.
Something like this:
class Test{
public Service<String> getStringService() {
// it is a bit strange that we can't explicitely construct a
// parametrized type from raw type and parameters, so here
// we use this workaround. This may need a dummy method or
// variable if this method should have another return type.
ParametrizedType stringServiceType =
(ParametrizedType)Test.class.getMethod("getStringService").getGenericReturnType();
ServiceLoader<Service<?>> loader = ServiceLoader.load(Service<?>.class);
for(Service<?> service : loader) {
if(isImplementing(service.getClass(), stringServiceType)) {
#SuppressWarnings("unchecked")
Service<String> s = (Service)service;
return s;
}
}
}
public boolean isImplementing(Class<?> candidate, ParametrizedType t) {
for(Type iFace : candidate.getGenericInterfaces()) {
if(iFace.equals(t)) {
return true;
}
if(iFace instanceof ParametrizedType &&
((ParametrizedType)iFace).getRawType().equals(t.getRawType())) {
return false;
}
}
return false;
}
}
This is not tested, and may need to be extended to also search interfaces extended by the interfaces our class implements directly, and interfaces implemented by our (generic) superclass.
And of course, this can only find classes like
class Example implements Service<String> { ...}
not something like
class Example<X> implements Service<X> { ... }
where Example<String> might be a valid implementation of your service.
You could also just copy the ServiceLoader class file and remove the generic type argument from the load() method, causing it to always work. You'll just need to override the warnings.
public static <S> ServiceLoader load(final Class<S> service)
{
return load(service, Thread.currentThread().getContextClassLoader());
}

Categories

Resources