0

It's difficult to explain what I'm trying to achieve here (so...sorry if I missed a glaringly obvious answer in my searching)...

I'm trying to dynamically instantiate an object based on a Class paired to a value in a HashMap. However, I've been having issues finding an approach that actually works. Currently, I'm doing something like this:

HashMap<String, Flag<?>> flags = new HashMap<String, Flag<?>>(); HashMap<String, Class> keys = new HashMap<String, Class>(); keys.put("test", BooleanFlag.class); keys.put("thing", StringFlag.class); keys.put("foo", DoubleFlag.class); for (Map.Entry<String, Class> key : keys.entrySet()) { try { Class c = key.getValue(); Object obj = c.getConstructor(String.class, String.class).newInstance(key.getKey(), "test value that will be checked and coerced by one of the flag classes"); flags.put(key.getKey(), c.cast(obj)); } catch (Exception ex) { //exception handling } } 

In this current incarnation of the method, c.cast(obj) throws a compiler error about an Object being found where Flag is expected. Am I going about this horribly wrong/is this possible?

2
  • Possible duplicate of Java Dynamically Loading a class Commented Dec 7, 2015 at 11:40
  • Why not store a Builder Object instead of BooleanFlag. The BuilderObject can know what type it is supposed to create and that way you don't need to cast. Or have a factory that creates your object and pass in the key as a flag on what to do? Commented Dec 7, 2015 at 11:56

2 Answers 2

1

May be the 'Factory pattern' is what you actually need?

public class Flag<T> {} public interface FlagFactory<T> { public Flag<T> newInstance(); } public class BooleanFlagFactory implements FlagFactory<Boolean> { public Flag<Boolean> newInstance() { return new Flag<Boolean>(); } } public class StringFlagFactory<T> implements FlagFactory<String> { public Flag<String> newInstance() { return new Flag<String>(); } } HashMap<String, FlagFactory> factories = new HashMap<String, FlagFactory>(); public void test() { factories.put("test", new BooleanFlagFactory()); factories.put("thing", new StringFlagFactory()); Flag flag = factories.get("test").newInstance(); } 
Sign up to request clarification or add additional context in comments.

1 Comment

I think I'm going to go with something along those lines. I figure avoiding reflection is best anyway.
1

You could do

if(obj instanece of Flag) { flags.put(key.getKey(), (Flag)obj); } 

That should handle all subclasses/implementations of Flag

12 Comments

Wouldn't I need to cast it back to a BooleanFlag or a StringFlag to access member methods of the more specific subclasses? That's something I need to avoid, hence why I'm using a Flag<?> generic instead of just casting to Flag in the first place.
Yes of cause - but only if those methods were not part of Flag. If you would iterate through the values of your flags map you'd either use valies as Flag or go checkijg for instanceof of some specifics. If you give more detail as to how StringFlag differs from Flag?
Flag is an abstract class. StringFlag is the simplest, merely accepting the value given to it. The others, like BooleanFlag, parse the string value given to them and set the canonical value (a boolean value in the case of BooleanFlag, cartesian coordinates in the case of another flag type, etc).
But how would you use them different? What additional (public) methods are there you'd want to call if you knew this was BooleanFlag?
Hm...that's a good point. I think everything that's public should be in the abstract class. And it should still be possible to poke it with instanceof in edge cases...
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.