Design Help! java generics in a enum factory transformer! - java

I am wondering if I could get some input on a good way to design this. I will put my approach but I think that there is a better solution (hence the question :) ).
I want to create an enum (to make clear the options and to avoid a singleton architecture) that has accessors for creating one object from another. But what those objects are is pretty flexible.
Think of it as a way to limit the number of options for this transformation.
Let me go into a little of the hierarchy. If I am going from a diverse set of objects to something like this:
class Base {...}
class ValueA extends Base {...}
class ValueB extends Base {...}
I was thinking of doing something like this:
public enum ValueTransformer{
VALUE_A{
#Override
public <T> T createVo (Class<T> expectedRtn, Object obj) {
ValueA retObj = null;
if (expectedRtn == getReturnType ()) {
if (obj != null && CanBeTranslatedToA.class == obj.getClass ()) {
retObj = new ValueA ();
/*...*/
}
}
return retObj;
}
#Override
public Class<ValueA> getReturnType () { return ValueA.class; }
},
VALUE_B {
#Override
public Class<ValueB> getReturnType () { return ValueB.class; }
#Override
public <T> T createVo (Class<T> expectedRtn, Object obj) {
ValueB retObj = null;
if (expectedRtn == getReturnType ()) {
if (obj != null && CanBeTranslatedToB.class == obj.getClass ()) {
retObj = new ValueB ();
/*...*/
} else if (obj != null && AnotherClassForB.class = obj.getClass ()){
retObj = new ValueB();
/* ... */
}
}
return retObj;
}
};
public abstract <T> Class<T> getReturnType ();
public abstract <T> T createVo (Class<T> expectedRtn, Object obj);
}
Is this a decent design? This enum will probably grow, and what ValueA and ValueB can be created from might change (as the sys grows). I could return a 'Base' in all those cases, but it would require a cast and a check. I'd prefer to not have that.
Is it necessary for me to have the expectedRtn parameter? Should I be using Generics at all? I am fairly new to Java so I am not always sure the best way to handle this case.
Thanks for any tips!!!!

This isn't a very good design and I really can't even tell what this enum is trying to accomplish. To start with, you're using generic methods that each enum value implements, which means the caller of the method gets to decide what type they want T to be... but that's not what you want, because the methods are in fact opinionated about what types of objects they'll return.
Class<String> foo = ValueTransformer.VALUE_B.getReturnType();
String string = ValueTransformer.VALUE_A.createVo(String.class, "");
The above is totally legal given your code, but your code does not actually handle this. Generic methods don't do what you seem to think they do.
I feel like what you actually want is just a simple way to transform objects of specific types to objects of type ValueA or ValueB. The simplest way to do this is just to have each class that can be transformed in this way provide a method that does that on each such class:
public class CanBeTranslatedToB {
...
public ValueB toValueB() {
ValueB result = new ValueB();
...
return result;
}
}
Then, if you have an instance of CanBeTranslatedToB, rather than doing:
CanBeTranslatedToB foo = ...
ValueB b = ValueTransformer.VALUE_B.createVo(ValueB.class, foo);
you'd just do:
CanBeTranslatedToB foo = ...
ValueB b = foo.toValueB();
That's much clearer and not error-prone like the enum version.
If necessary, you can do various things to make this easier such as making an interfaces that define the toValueA() and toValueB() methods and making helper classes to provide any common behavior that all implementations need to use. I don't see any use for an enum like you describe.
Edit:
If you can't change the code for the classes that need to be transformed to ValueB etc., you have several options. The simplest (and probably best, in my opinion) way to handle that would be to add factory methods to ValueA and ValueB such as:
// "from" would be another good name
public static ValueB valueOf(CanBeTranslatedToB source) {
...
}
public static ValueB valueOf(AnotherClassForB source) {
...
}
Then you can just write:
CanBeTranslatedToB foo = ...
ValueB b = ValueB.valueOf(foo);
If you don't want those methods on ValueB, you could have them in another class with method names like newValueB(CanBeTranslatedToB).
Finally, another option would be to use Guava and create a Function for each conversion. This is the closest to your original design, but it is type safe and works well with all the Function-accepting utilities Guava provides. You could collect these Function implementations in classes as you see fit. Here's an example of a singleton implementing a conversion from Foo to ValueB:
public static Function<Foo, ValueB> fooToValueB() {
return FooToValueB.INSTANCE;
}
private enum FooToValueB implements Function<Foo, ValueB> {
INSTANCE;
#Override public ValueB apply(Foo input) {
...
}
}
However, I wouldn't use this as the only way to do the conversion... it would be better to have the static valueOf methods I mentioned above and provide such Functions only as a convenience if your application needs to transform whole collections of objects at once a lot.

Regarding Generics, Java doesn't have "real" generics, which can be both beneficial and detrimental in this case. Using generics is tricky when you don't know at compile time exactly what type of object you're dealing with. If the code consuming this information actually knows which type of object it's supposed to expect from a call to ValueTransformer.ValueA.createVo, then it should honestly be expected to cast the returned value. I would expect the call to look more like this:
MyTypeA myType = (MyTypeA)ValueTransformer.ValueA.createVo(sourceObject);
If I'm getting the wrong type out of this method, I would rather see a Cast exception on this line (where the problem really happened) than a null pointer exception later on. This is correct "fail-fast" practice.
If you really don't like the explicit casting, I've seen a cool trick that lets you cast these things implicitly. I think it goes something like this:
public abstract <T> T createVo (Object obj) {...}
MyTypeA myType = ValueTransformer.ValueA.createVo(sourceObject);
However, I don't really recommend this approach because it still performs the cast at runtime, but nobody would suspect that by looking at your usage code.
I can see a few goals that you may be hoping to achieve:
Have a single "source of truth" to go to for all objects of the given Base class.
Allow the creation of an instance of a given object every time you request one.
Have type-safety and avoid casting at runtime.
Unless you have other requirements I'm not thinking of, it seems like a factory would be preferable:
public class ValueFactory
{
public ValueA getValueA(Object obj) {return new ValueA();}
public ValueB getValueB(Object obj) {return new ValueB();}
}
This satisfies all the requirements mentioned above. Furthermore, if you know what type of object is required to produce a ValueA object, you can use a more explicit type on the input value.

I spent some time and finally managed to implement enum based factory that looks like what you are looking for.
Here is the source code of my factory:
import java.net.Socket;
public enum EFactory {
THREAD(Thread.class) {
protected <T> T createObjectImpl(Class<T> type) {
return (T)new Thread();
}
},
SOCKET(Socket.class) {
protected <T> T createObjectImpl(Class<T> type) {
return (T)new Socket();
}
},
;
private Class<?> type;
EFactory(Class<?> type) {
this.type = type;
}
protected abstract <T> T createObjectImpl(Class<T> type);
public <T> T createObject(Class<T> type) {
return assertIfWrongType(type, createObjectImpl(type));
}
public <T> T assertIfWrongType(Class<T> type, T obj) {
if (!type.isAssignableFrom(obj.getClass())) {
throw new ClassCastException();
}
return obj;
}
}
Here is how I use it.
Thread t1 = EFactory.THREAD.createObject(Thread.class);
String s1 = EFactory.THREAD.createObject(String.class); // throws ClassCastException
Personally I do not like too much this implementation. Enum is defined as Enum, so it cannot be parametrized on class level. This is the reason that classes-parameters (Thread and Socket in my example) must be passed to factory method itself. Also the factory implementation itself contains casting that produces warning. But from other hand at least code that uses this factory is clean enough and does not produce warnings.

Related

Question about return type( need to return instances of different classes) in generics

So my current code looks like this. The idea is to take in an instance of different classes using generic type T and return those instances.
I should be able to call instances of classes like this
new A().add(new B())
public static <T> T <T> add(T t) {
return new T();
}
Basically to me the return type should be the class itself so that it can take a new instance through the return type.
Can someone guide me as to where my logic is going wrong?
You can't call a constructor just from the generic type because 1. type erasure means T gets turned into Object (or whatever its upper bound is) at runtime, and 2. you don't know that the constructor necessarily takes 0 arguments.
A better way to do it would be with a Supplier
public static <T> T add(Supplier<T> supplier) {
return supplier.get();
}
and you could use this method like this. With method references, it's pretty concise.
B b = YourClass.add(B::new);

Access static field of generic type

Can I require classes implementing an interface to have a certain static field or method and access/invoke that field or method through a generic type argument?
I have an interface, Arithmetical<T>, which specifies several functions like T plus(T o) and T times(T o). I have as well a Vector<N extends Arithmetical<N>> class, which is intended for vectors (of variable dimension) with components of type N. I ran into an issue, however, when trying to implement the dot product.
I want to implement the method N dot(Vector<N> o). For this, I plan to start with whatever N's zero is and iterate through both Vector<N>s' List<N>s, adding the product of each pair of elements to my total. Is there a way to specify in Arithmetical<T> that all implementing classes must have a static (and preferably final) field ZERO and start dot(Vector<N> o)'s body with something along the lines of N sum = N.ZERO;?
If not, what other approaches might there be to this problem? I want to allow 0-dimensional vectors, so I can't just begin by multiplying the vectors' first components. Is there a way to instantiate an object of a generic type, so I can merely specify a T zero() method in Arithmetical<T>?
I have a reason for not using Java's numerical types—I want to have vectors with complex components.
Here's Arithmetical:
public interface Arithmetical<T> {
public T plus(T o);
public T minus(T o);
public T negate();
public T times(T o);
public T over(T o);
public T inverse();
// Can I put a line here that requires class Complex (below) to define ZERO?
}
Vector:
public class Vector<N extends Arithmetical<N>> {
private List<N> components;
public Vector<N>(List<N> cs) {
this.components = new ArrayList<N>(cs);
}
public N dot(Vector<N> o) {
// Here's where I need help.
}
}
And Complex:
public class Complex implements Arithmetical<Complex> {
public static final Complex ZERO = new Complex(0, 0); // Can I access this value through N if <N extends Arithmetical<N>>?
private double real;
private double imag;
public Complex(double r, double i) {
this.real = r;
this.imag = i;
}
/* Implementation of Arithmetical<Complex> (and some more stuff) not shown... */
}
I'm quite new to Java (and programming in general); I will likely not understand complex (ha) explanations and workarounds.
Thanks!
(Python is a suggested tag... Huh.)
You need a "zero" for every possible implementation type. A constant in the interface won't do, because a constant cannot be overridden and must remain the same.
The solution is to add a new method to your Arithmetical interface:
public T zero();
Each implementation is forced to implement this and return its own version of zero. In this case, you're using it as a starting point for adding; it's the additive identity.
The Complex class implementation would look like this.
#Override
public Complex zero() {
return ZERO;
}
If your instances are mutable, then don't use a constant; just return new Complex(0, 0).
Another idea is to borrow from what Streams do when reduce-ing items and combining them to one single item -- take an identity value that represents the initial state, i.e. no items collected yet -- zero.
public N dot(Vector<N> o, N identity) {
N dotProduct = identity;
// Perform operations on each item in your collection
// to accumulate and return a dot product.
}
The caller will have to supply the identity value.
Complex dotProduct = vectorOfComplex.dotProduct(otherVector, new Complex(0, 0));
Can I put a line here that requires class Complex (below) to define ZERO?
No. The best you can do is to define an interface, for example:
interface ZeroProvider<A extends Arithmetical<A>> {
A zero();
}
and then supply a compatible instance of that where you need to provide a zero, for example:
class ComplexZeroProvider implements ZeroProvider<Complex> {
public Complex zero() { return new Complex(0, 0); }
}
There's something you can do sometimes using reflection in situations like this. If you put the following method in the Vector class, it will invoke a static method N.zero() (with caveats, below):
protected N zero() {
try {
Type s = getClass().getGenericSuperclass();
#SuppressWarnings("unchecked")
Class<N> n = (Class<N>) ((ParameterizedType) s).getActualTypeArguments()[0];
Method zero = n.getMethod("zero");
return n.cast(zero.invoke(null));
} catch (RuntimeException | ReflectiveOperationException x) {
// probably better to make a custom exception type
throw new IllegalArgumentException("illegal type argument", x);
}
}
However, it's important to understand what this is actually doing. This is getting the type argument from the class file of the direct superclass of this. In other words, there must actually be a superclass of this with an actual type argument (which is a class).
The usual idiom then is that you'd create all of your vectors like this:
new Vector<Complex>() {}
instead of this:
new Vector<Complex>()
Or you'd declare subclasses like this:
public class Vector<N> {
// ...
public static class OfComplex extends Vector<Complex> {
}
}
Since you need an actual superclass with a type argument which is a class, instantiations like in the following examples will fail:
new Vector<Complex>()
new Vector() // never use this anyway
new Vector() {} // never use this anyway
// also, you can't do stuff like this:
public Vector<T> copy() {
return new Vector<T>(this) {};
}
In your case I think the suggestions in the other answers are better, but I wanted to post this answer along with the proper explanation and caveats which are sometimes not included. There are cases where this technique is actually good, mainly when you have pretty tight restrictions on how the class in question is extended. Guava TypeToken will also do some of the reflection for you.
Also, this is the best Java can do at doing exactly what you're asking for (at the moment), so it's worthwhile to point out just as a comparison.

Approach doing the same stuff on different objects

I am currently making a library which is an utility for me to handle something which is not associated with the question (I am implicitly not saying the subject because it is not really important), however it does use reflection.
I am retrieving all declared and inherited methods from a class, which currently works fine and is not the issue. But the thing is, I need to do this as well for sub-classes since those inherit over like methods do (however you cannot override those like methods).
The problem that I am facing that it will use the same algorithm but there will be on difference, instead of calling clazz.getDeclaredMethods() I need to call clazz.getMethods. What is the best way too approach this, and I kind of need to return Class[] and Method[] in the method signature as well.
Normally I would look for a shared superclass, but in this case I prefer to the have Class[] and Method[] accordingly. For starters, I did some research and found some shared superclasses:
GenericDeclaration
AnnotatedElement
Since I need both Class[] and Method[] arrays I am thinking something
like generics, so the method would look like:
public static <T extends GenericDecleration> T[] getT () {
}
As mentioned by dasblinkenlight this will not work since the method doesn't take any arguments and cannot check whether to retrieve Class or Method objects.
But how would I detect whether I need to call getDeclaredMethods or getDeclaredClasses?
What is the best approach on how to do this without duplicating a lot of code? I really tried to explain myself here, but if it is still unclear what I am doing please feel free to ask away!
Thank you very much in advance!
After messing around with this, I have found a solution that totally fits my needs. This is a combination of generics and #dasblinkenlight's solution, like so:
public interface DeclExtractor<T extends GenericDecleration> {
public T[] extract (Class clazz);
public Class<? extends T[]) getGenericClass ();
DeclExtractor<Method> methodExtractor = new DeclExtractor<Method>() {
#Override
public Method[] extract (Class clazz) {
return clazz.getDeclaredMethods();
}
#Override
public Class<? extends Method[]> getGenericClass () {
return Method[].class;
}
}
// Same for Class
}
Now the method which also will return the correct type so you dont have to manually cast all GenericDeclaration to your original object type. My issue was that I used a collection for it and not the correct array:
public <T> T[] getAll (final DeclExtractor<T> extractor, Class<?> clazz) {
T[] declaration = extractor.extract (clazz);
//.. The algorithm..
// Return an instance of a collection as array (I use a set in my implementation)
final Object[] objects = myCollection.toArray();
return Arrays.copyOf(objects, objects.length, extractor.getGenericClass());
}
Technically you do not need the getGenericClass method in the interface, but I am using extract directly in a loop so I cannot pull the class of that, however, you can.
Hopefully this helps someone in the future :) Thanks again to #dasblinkenlight for the inspiration!
Your getT needs to get some input in order to decide what to do.
What about a method which can takes an enum as argument to determine whether it needs to get classes or methods? (from a comment)
There is a better approach: define an interface that performs the appropriate extraction, and make two instances of it - one for extracting classes, and one for extracting methods:
public interface DeclExtractor {
GenericDecleration[] extract(Class cl);
final DeclExtractor forClasses = new DeclExtractor() {
public GenericDecleration[] extract(Class cl) {
// make an array of GenericDecleration from extracted classes
}
};
final DeclExtractor forMethods = new DeclExtractor() {
public GenericDecleration[] extract(Class cl) {
// make an array of GenericDecleration from extracted methods
}
};
}
Now you can rewrite your getT to take an "extractor", like this:
public static GenericDecleration[] getT (DeclExtractor extractor, Class cl) {
...
// When it's time to get components of the class, make this call:
GenericDecleration[] components = extractor.extract(cl);
...
}
To initiate a call to getT, pass DeclExtractor.forClasses or DeclExtractor.forMethods:
GenericDecleration[] c = getT(DeclExtractor.forClasses);
GenericDecleration[] m = getT(DeclExtractor.forMethods);

How to name class name according to Java Generics type return?

< T > T foo(P p) {
...
}
I'll get different types of return from foo according to the parameter I inserted, which means T changes according to p.
Then I try to call this function and use its return result.
Class x = foo(p);
What should I write in substitute of Class here?
Suppose parameter is a enum type.
enum P {
XX,YY,ZZ
}
then the return type T is Xx, Yy, Zz respectively according to parameter.
Let me give the exact sample here.
public <T> List<T> getProperty(Property property) {
switch(property) {
case NAME: List<Name> names = new ArrayList<Name>();
names.add(this.name); return (List<T>) names;
case PHONE: return (List<T>) this.phones;
case EMAIL: return (List<T>) this.emails;
case ADDRESS: return (List<T>) this.addresses;
case NOTE: List<Note> notes = new ArrayList<Note>();
notes.add(this.note); return (List<T>) this.note;
default: return null;
}
}
public enum Property {
NAME, PHONE, EMAIL, ADDRESS, NOTE
}
public List<Entry> search(Property property, String s) {
if(this.isEmpty()) {
return null;
}
List<Entry> result = new ArrayList<Entry>();
for(Entry e : entries) {
if(e.getProperty(property) != null) {
for( **Object** p : e.getProperty(property)) { //What should I write instead of Object
if(p != null) {
if(p.containString(s)) { //there'll be errors if use Object. Need to know p's class.
result.add(e);
}
}
}
}
}
return this.nonDuplicatedResult(result);
}
I'm really not sure what you're asking. You haven't explained your use cases at all and haven't given us much code to look at. It's difficult to provide useful feedback from within the fog of obfuscation.
Generally speaking, if you want a method that returns a different object depending on the value of a supplied argument, then what you're probably talking about is a static factory method which can return any object that is a subtype of the method's return type. It is convenient to make such objects a part of an interface-based type system (eg. the static factories for the EnumSet class).
The use of an interface-based type system is actually necessary if you wish to return an enum, because enums cannot be part of a class hierarchy, but they can implement an interface that forms an interface-based type system.
Suppose parameter is a enum type.
enum P {
XX,YY,ZZ
}
then the return type T is Xx, Yy, Zz respectively according to parameter.
No it isn't. The return type is P. You're over-thinking this. The 'enum' case isn't a job for Generics at all.
Assuming you have an finite number of return types, you could just check through each one using instanceof to see if the returned value is of a certain type. So in this case Object would substitute class, then you could later cast it.
What is happening is basically with that method definition, what you are saying to the compiler is that your method will return whatever the parameter assignment declares itself to be. You can do that, but how your method is implemented will boil down to a compiler warning, as you can't actually ensure that you are generating the appropriate type - since you don't know it, it is never passed to the method, and erased at compile time.
More typically what you would do is:
<T extends P> T foo(T p) {
...
}
Now you get an object of the right type as a parameter, so you have some idea of what to return. That concept has little utility with enums, though.
Here is a real world example of where you could use the method definition you posed in your question:
public static <T> T generateProxy(Object realObject, Class<?>... interfaces) {
return (T) Proxy.newProxyInstance(realObject.getClass().getClassLoader(), interfaces, new SimpleInvocationHandler(realObject));
}
Of course such a method generates a compiler warning. Now, what you are saying here is that the caller will define a variable, and will be sure to pass in at least one interface of the type they define. If they don't, they will end up with a ClassCastException at runtime, but you avoid calling code that knows what it is doing from explicitly casting.
It is debatable if that is a good idea.
So the short answer is that you can define the Class to be whatever you want - the compiler will accept anything - but if the method doesn't return the correct type, you will get an exception at runtime, so it is all about how you implement the method. Rarely can a method be smart enough to return the right thing without the correct type as a parameter. And if you can't pass in an appropriate parameter declared with the generic type to the method, you will have to deal with a compiler warning in order to return anything (other than null).

Is there a way to define a generic method that checks for null and then create the object?

I'd like to write a method that checks where the argument is null, and if it is, returns a new object of that type. it looks like:
public static <T> T checkNull(T obj) {
if (null == obj) return someHowCreateTheObjectWithTypeT();
else return obj;
}
After some struggling and digging, I still can't get a way to achieve this, is it atually possible in java?
I thought about reflection at first. But I just can't get a Class instance when the object is null, and you can't create a Class without the type T's name...
Update:
I thought about passing a Class as a parameter, but that's not the best solution, as the following answers shows :)
My currunt solution is to use a defaultValue parameter:
public static <T> T checkNull(T obj, T defaultValue) {
if (null == obj) return defaultValue;
return obj;
}
Which is faster and safer than a reflection solution, and is the same verbose;
But then I have to systematically specify a DEFAULT_VALUE for all types of interest, which is not an easy work.
This is not possible. For generics to work in this manner, it has to capture at compile-time the type that it will be called with. However, null has no type so you won't be able to figure out T to instantiate it.
Now, you may be able to work around this also passing in the Class instance, but you will need some rather robust error handling using Reflection to ensure that type T is a concrete class and has a public parameterless constructor that you can invoke.
Generic information is compile time only and not available at runtime. You'd have to pass the Class of the object in as a hint, and the class would have to have a public default constructor. e.g.
public static T checkNull(Object o, Class<T> c) {
try {
return (o == null) ? c.newInstance() : o;
} catch (Exception e) {
return null;
}
}
Cannot be done. You must add an additional parameter of Class<T>, and then use it to reflectively new. The type T does not survive the compilation process.
As others have pointed out, this can't be done. However, Guava provides an equivalent to the default value you method you posted:
String foo = Objects.firstNonNull(someString, "default");
This differs slightly from your method in that firstNonNull will throw a NullPointerException if both arguments are null.
Another option would be to create a method that makes use of Guava's Supplier<T> interface or something similar:
public static T firstNonNull(T first, Supplier<? extends T> defaultSupplier) {
return first != null ? first : Preconditions.checkNotNull(defaultSupplier.get());
}
You could then use a Supplier that creates and returns a new default instance when and only when the first argument is null.

Categories

Resources