Map from int to class - java

I want to create objects of different classes based on user input, i.e. the user will tell which class's object to create. I have something like this :
launcher.addProcessor((Processor) new SerializableFieldProcessor(projectKey));
Now I have other processors and want the user to give an integer input and depending on that, the respective processor's object to be created. A straightforward way is to use switch cases, but later on I'm going to have more than 50 or 100 separate processors. Is there a way to do this with a map or something similar? Something like this :
Map<int,Processor> mymap;
//initialize mymap;
int x= user_input;
launcher.addProcessor((Processor) new mymap[x]);

Another solution you might want to consider is as follows:
Map<Integer, Class<? extends Processor>> map = new HashMap<>();
// Integer.valueOf(x) used to prevent autoboxin just a matter of opinion.
map.put( Integer.valueOf( 0 ), MyProcessor.class );
Processor chosen = map.get( userIn ).getConstructor( String.class ).newInstance( projectKey );
launcher.addProcessor(chosen);
It is basically the same but the difference is that the returned object is of the type Processor and the class does definitly exist. When you are using a String and Class.forName(...) there are two additional exceptions that may be thrown. First the ClassNotFoundException which will be thrown if the Class.forName() method did not find the class for the given name. The 2nd additional exception is the ClassCastException which will be thrown if the created object is not an implementation or subclass of Processor.
Explanation:
We are using a map with an Integer as our key and a Class<? extends Processor> as our value. A Class<T> object can be considered as an object representation of the corresponding .class file (technically incorrect but for the sake of simplicity we assume it is that way). What does <? extends Processor> mean in concrete? It means that the map will only allow values of Classes which are an implementation or a subtype of Processor. Doing so eliminates the thread of a ClassCastException because if we can only store classes which extend Processor we can only retrieve classes which can be casted to an Processor without any issues or even the thread of one.
Note: I chained the instantiation process which usually is a bad idea in a productive environment but it shortens the code quite a lot and there is no need to further explain it since you use the exact same approach in your own answer.

Thank you Lews Therin. I have found a solution using Java Reflection.
Map<Integer,String > rule=new HashMap<Integer, String>();
rule.put(1948,"SerializableFieldProcessor");
Class<?> processor = Class.forName(rule.get(1948));
Constructor<?> cons = processor.getConstructor(String.class);
Object object = cons.newInstance(projectKey);
launcher.addProcessor( (Processor)object);

public class Foo { }
public class Bar { }
private Object userChosenClass(Int userInput) {
if (userInput == 0) {
return new Foo();
} else if (userInput == 1) {
return new Bar();
} else {
return null;
}
}
Or, you can have a map of Ints -> Classes and then query the map to get the corresponding class for the given input Int. For instance:
public class UserClassSelector {
private Map<Int, Class> map;
public UserClassSelector() {
map = new Map<Int, Class>();
}
public Void addMapping(Int fromInt, Class toClass) {
map[fromInt] = toClass;
}
public Object instantiateFromMap(Int forInt) {
if (map[forInt] != null) {
return new map[forInt]();
} else {
return null;
}
}
}

Related

Check if Object is an instance of a class from a list of classes and cast

I have a number of classes that my object might be at run time. Currently to check which class it is i have a number of if statements like
int id = 0;
if (object instanceof Comment) {
id = ((Comment) object).getId();
}
if (object instanceof Follow) {
id = ((Follow) object).getId();
}
if (object instanceof Like) {
id = ((Like) object).getId();
}
if (object instanceof Post) {
id = ((Post) object).getId();
}
if (object instanceof User) {
id = ((User) object).getId();
}
This works but doesn't feel very clean. I had a look at Check if an object is an instance of any one of a list of classes (Android) which suggests a way to check if the object is an instance of a class from a list of classes like
if(myClasses.contains(obj.getClass())) {
// obj is one of the classes I care about, so do something
}
However this doesn't then work as i need to go on and cast the object to that class.
Does anyone know of a cleaner way to bot check my object type is of a class from a list of classes AND then cast the object to that class.
Something like
if(myClasses.contains(object.getClass())) {
((CLASS_THAT_MATCHED) object).getId()
}
NOTE of course normally I would just make all of the Classes be subclasses of a super class that had the getID method and other methods I need. However in this specific instance these classes all need to be subclasses of a libraries class. Making them inherit from one base classes breaks code in the library. Which i know is a bad design issue on the libraries side but isn't something i can fix.
However in this specific instance these classes all need to be subclasses of a libraries class
Then you should use an interface:
public interface HasId{
int /* or whatever type is the ID*/ getId();
}
public class Like extends LibrarySuperClass implements HasId{
...
}
However, if Like, Post etc are also library classes, you can do something like this:
// UNTESTED
Object obj =...;
List list = List.of(
Like.class,
Follow.class,
Comment.class,
User.class,
Post.class,
);
Integer id = list
.stream()
.filter(class -> class.isInstance(obj))
.map(class -> (Integer) class.cast(obj).getId())
.findFirst()
.orElse(null);
You need to use polymorphism. For example, create an interface
public interface Message {
int getId();
}
And let your classes implement it. Then you can call the getId method on each of them. Additionally, you can create an abstract class with basic functionality for the Post, Like, etc. classes. Something like that.
Re #Alberto Sinigaglia solution,
it works excellent... but looks ridiculous after all necessary casts ;), ex:
...
Object obj = new Comment();
List<?> list = new ArrayList<>() {
private static final long serialVersionUID = 4804401786243829831L;
{
add(Comment.class);
add(Message.class);
add(Post.class);
}
};
Integer id = (Integer) list.stream().filter(c -> ((Class<?>) c).isInstance(obj))
.map(c -> (Integer) ((I_ObjectType) ((Class<?>) c).cast(obj)).getObjectId()).findFirst().orElse(null);
System.out.println("result?=" + id);
...
each Class implements:
public interface I_ObjectType {
int getObjectId();
}

How to Check if type of Map extends Number

I'm trying to check if a Map<String, T> contains Objects (T) of type Double or Integer.
I don't want to use the actual Objects in the map for checking the class since It's not certain that the Map contains Objects at all.
I can achieve this by doing the following (Assuming the field is containing a Map):
ParameterizedType type = (ParameterizedType) field.getGenericType();
isNumeric(type);
/**
* #param type
* #return Returns true if type is numeric
*/
private static boolean isNumeric(ParameterizedType type) {
return type.getActualTypeArguments()[1].toString().equals("? extends java.lang.Number");
}
It's sufficient for me but it doesn't feel like a clean solution.
However, I can retrieve the Type of the getActualTypeArguments()[1]
by doing the following:
Type typeOfSecondGeneric = type.getActualTypeArguments()[1]; // equals '? extends java.lang.Number'
I can't use Number.class.isAssignableFrom(typeOfSecondGeneric); // Class expected
After I researched a bit, I didn't came up with a better solution than doing the String comparison.
What am I getting wrong?
Help is appreciated!
An ad hoc solution could be something like this:
private static boolean isNumericValue(ParameterizedType t) {
return isSubclassOf(t.getActualTypeArguments()[1], Number.class);
}
private static boolean isSubclassOf(Type t, Class<?> clazz) {
if (t instanceof Class<?>)
return clazz.isAssignableFrom((Class<?>) t);
if (t instanceof ParameterizedType)
return isSubclassOf(((ParameterizedType) t).getRawType(), clazz);
Type[] bounds = null;
if (t instanceof TypeVariable<?>)
bounds = ((TypeVariable<?>) t).getBounds();
if (t instanceof WildcardType)
bounds = ((WildcardType) t).getUpperBounds();
if (bounds != null && bounds.length > 0)
return isSubclassOf(bounds[0], clazz);
return clazz == Object.class;
}
That short example doesn't handle interface types or generic array types. It's also nowhere near to being complete with respect to the actual rules of subtyping.
If it's true that you really do need something like this, I think the better solution is to use Guava TypeToken:
private static final TypeToken<Map<?, ? extends Number>> T =
new TypeToken<Map<?, ? extends Number>>() {};
private static boolean isNumericValue(ParameterizedType t) {
return T.isSupertypeOf(t);
}
That said, I'm not all that convinced that you do need this. This looks like an XY problem and you might do better asking a question about the problem you're trying to solve rather than your attempted solution. This is the kind of code that can turn in to a huge pain in the neck after your program is tied down to using it, especially if it's pervasive.
This information is lost at run-time so in general you won't be able to figure out what T really is.
The exception to this general rule are limited to those case in where the map object class itself has a more specific constraint on that T. For example:
class MyDoubleMap<K> extends Map<K, Double> {
...
}
...
Map<String, Double> standard = new HashMap<>();
Map<String, Double> doubles = new MyDoubleMap<>();
Map<String, Double> annonDoubles = new HashMap<>() {};
With standard any reflection trick won't be able to recover more than T and that it could be anything that extends Object.
However for the other two cases doubles and annonDoubles the reflection code included in other answer should get to the Double assignation to the T.
With doubles it should be easy to see that that information should be available thru reflection as it is integral part of this declaration of MyDoubleMap. Perhaps
annonDoubles is a bit less obvious but in fact with the trailing {} it is effectively declaring an anonymous
inner class that extends HashMap<String, Double> and so such an information for T (and also for K) can be recovered by reflection.

in java how to avoid multiple if else with map for isAssignableFrom

I would like to avoid the if else, in java this:
for (Class clazz : method.getParameterTypes()) {
if (SomeClass.class.isAssignableFrom(clazz)) {
arguments[i] = onearg;
} else if (SomeOtherClass.class.isAssignableFrom(clazz)) {
arguments[i] = someotherarg;
}
}
can anyone suggest how to do this? thanks
You could store the classes and their arguments in a Map<Class<?>, Object> and iterate the map, this would replace the if-else construct by an iteration loop with one if-statement.
For instance like this:
Map<Class<?>, Object> map = ... /* initialize */
for (Class cls : method.getParameterTypes()) {
for (Entry<Class<?>, Object> candidate : map.entrySet()) {
if (candidate.getKey().isAssignableFrom(cls)) {
arguments[i] = candidate.getValue()
break; // continue with the next parameter type
}
}
}
The concrete implementation depends on your classes. If the classes in your map have no relationship between each other (e.g. superclass, subclass, interface, etc.) then you can apply the code directly. Otherwise, as bestsss has pointed ought you should stick to super class/interface iteration in order to preserve the class hierarchy.
Further your could investigate into Java Annotations, though I am not 100% sure how to apply them in your case without further details on the requirements. You could annotate your super classes with the arguments
#Argument("onearg")
public class SomeClass {
/* ... */
}
and get the super class of the method parameter types during iteration with cls.getSuperClass() and retrieve the annotated argument value afterwards for assignment.

Can I have a type safe map that either contains A or List<A>?

I need a Map container that contains either an
Item Object
or
List<Item> Object
as its value, and I can get it out without casting, is it possible?
Short answer: No.
Union types don't exist in Java. The closest thing you could do in order to get compile-time type checking would be to create list of some custom wrapper class which contained either an A or a List<A>, something like the following:
public class UnionListWrapper<A> {
private final A item;
private final List<A> list;
public UnionListWrapper(A value) {
item = value;
list = null;
}
public UnionListWrapper(List<A> value) {
item = null;
list = value;
}
public Object getValue() {
if (item != null) return item;
else return list;
}
}
At least you wouldn't be able to create instances of this class that weren't either an A or a List<A>, but getting the value back out would still have to just be Object, with associated casting. This could get quite clumsy, and on the whole it's probably not worth it.
In practice I'd probably just have a List<Object> with some comments around being very careful about what data types are accepted. The problem is that even run-time checks (sub-optimal) aren't going to be possible, since Java's generic erasure means that you can't do an instanceof A check at runtime (doubly so on the generic parameter of the List).
No, you can't do this in a type-safe manner.
From a design standpoint, I'd suggest using only List<Item> as values. If some of them are single-element lists, that's just fine; your code is likely to be much cleaner if you handle all values in the same way.
In fact, I'm curious how you plan to use a map with elements and lists of elements. Do you know which type to expect for a given key a priori?
Sounds like you want a MultiMap -- There is an Apache implementation and a Google implementation
Possibly the type safe heterogeneous container pattern is what you are looking for
http://books.google.com/books?id=ka2VUBqHiWkC&pg=PA142&lpg=PA142&dq=type+safe+heterogeneous+container+pattern&source=bl&ots=yYDfNltZS3&sig=giH1d_rIQ-MumOnrMmiT4OgtM7E&hl=en&ei=880dTqHcJYSyhAeVhqS3Bw&sa=X&oi=book_result&ct=result&resnum=5&ved=0CDUQ6AEwBA#v=onepage&q=type%20safe%20heterogeneous%20container%20pattern&f=false
Addressing the good point raised in the comment below re type erasure - using super type tokens. Taken from http://gafter.blogspot.com/2007/05/limitation-of-super-type-tokens.html, which highlights an issue with the approach.
import java.lang.reflect.*;
public abstract class TypeRef<T> {
private final Type type;
protected TypeRef() {
ParameterizedType superclass = (ParameterizedType)
getClass().getGenericSuperclass();
type = superclass.getActualTypeArguments()[0];
}
#Override public boolean equals (Object o) {
return o instanceof TypeRef &&
((TypeRef)o).type.equals(type);
}
#Override public int hashCode() {
return type.hashCode();
}
}
public class Favorites2 {
private Map<TypeRef<?>, Object> favorites =
new HashMap< TypeRef<?> , Object>();
public <T> void setFavorite(TypeRef<T> type, T thing) {
favorites.put(type, thing);
}
#SuppressWarning("unchecked")
public <T> T getFavorite(TypeRef<T> type) {
return (T) favorites.get(type);
}
public static void main(String[] args) {
Favorites2 f = new Favorites2();
List<String> stooges = Arrays.asList(
"Larry", "Moe", "Curly");
f.setFavorite(new TypeRef<List<String>>(){}, stooges);
List<String> ls = f.getFavorite(
new TypeRef<List<String>>(){});
}
}
Not without writing a wrapper class (WrapsA) which holds either a single A or a List, and making your list be List
Functional Java provides a disjoint union data type called Either<A, B>, so you can define a Map<Key, Either<Item, List<Item>>>.

Design Help! java generics in a enum factory transformer!

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.

Categories

Resources