I have a database table that contains a column named type. For every row in my database column I have to create an object depending on the type. At the moment I use if else statements for that:
if (type.equals("object1")){
Object1 object1 = new Object1();
}
else if (type.equals("object2")){
Object2 object2 = new Object2();
}
Somewhat nicer would be to use an enum, as the number of types is limited but is there a possibility to let the creation of an object depend on the value of the String?
I'm open to suggestions that might solve my problem in another way than I am trying to.
You could create a map from String to Class and use newInstance. That however relies on the existence of no-arg constructors.
import java.util.*;
class Test {
public static void main(String[] args) throws Exception {
Map<String, Class<?>> classes = new HashMap<String, Class<?>>();
classes.put("object1", Object1.class);
classes.put("object2", Object2.class);
String type = "object2";
Object obj = classes.get(type).newInstance();
//...
}
}
class Object1 { ... }
class Object2 { ... }
You can use
Object o = Class.forName(type).newInstance();
If you have an int and two Strings as arguments you need.
Object o = Class.forName(type)
.getConstructor(int.class, String.class, String.class)
.newInstance(intValue, string1, string2);
Another possibility is to use factory methods
Object o = getClass().getMethod("create_" + type).invoke(null);
static Object1 create_object1() {
return new Object1(/* with args */);
}
static Object2 create_object2() {
return new Object2(/* with other args */);
}
but the most flexible approach may be to use a switch
Object o;
switch(type) { // in Java 7
case "object1": o = new Object1(); break;
case "object2": o = new Object2(); break;
What would be more elegant is using closures in Java 8.
http://cr.openjdk.java.net/~briangoetz/lambda/lambda-state-final.html
package main;
import java.util.ArrayList;
import java.util.List;
public class TempClass {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
List<Class> classes = new ArrayList<Class>() {{
add(Class.forName("main.Object1"));
add(Class.forName("main.Object2"));
}};
for (Class aClass : classes) {
Object o = aClass.newInstance();
}
}
}
package main;
public class Object1 {
public Object1() {
System.out.println("Object1");
}
}
package main;
public class Object2 {
public Object2() {
System.out.println("Object2");
}
}
If the classes in question are part of an inheritance hierarchy and you happen to use some kind of mapping tool/framework like Hibernate or iBATIS/MyBatis, it might include a way to configure so called discriminators.
You could then configure your "type" column as the descriminator column and map the supported values to your classes. The framework will then instantiate the appropriate classes for you when you retrieve the objects from the database.
Using switch or if statements forces you to hard-code the various options, so you will obtain a not so flexible solution, in my opinion.
I always prefer to write code that is extensible for future software developments.
So I suggest you to use Object o = Class.forName(type).newInstance(); putting in your database the name of the class you want to instantiate and, if you need it, a custom label.
EDIT
If you have to pass some parameter to the constructors of the classes you have to instantiate, is convenient to use Constructor.newInstance() instead of Class.newInstance(); and use the Constructor object to instantiate the class, for example:
Class myClass = Class.forName(type);
// get the constructor you need specifying parameters type
Constructor constructor = myClass.getConstructor(String.class);
Object myObject = constructor.newInstance("constructor-arg");
Related
Say you have a lot of similar classes that may get instantiated at any point. One obvious way to write this would be a whole slew of conditionals:
public static Common factory(String key, InstantiationObj instantiationObj) {
if( key == "A") {
return new TypeA(instantiationObj);
}
else if( key == "B") {
return new TypeB(instantiationObj);
}
else if( key == "C" ) {
return new TypeC(instantiationObj);
}
else if( key == "D" ) {
return new TypeD(instantiationObj);
}
else {
return new DefaultClass(instantiationObj);
}
}
I like to avoid all the conditionals though. In Java I got this working:
public static <T extends Common> T factory(String key, InstantiationObj instantiationObj) throws Exception {
Class[] cArg = new Class[1];
cArg[0] = InstantiationObj.class;
HashMap<String, Class> potentialClasses = new HashMap<>();
potentialClasses.put("A", TypeA.class);
potentialClasses.put("B", TypeB.class);
potentialClasses.put("C", TypeC.class);
potentialClasses.put("D", TypeD.class);
Class<T> classType = potentialClasses.getOrDefault(key, DefaultClass.class);
return classType.getDeclaredConstructor(cArg).newInstance(instantiationObj);
}
This is much easier to test, but it still looks clunky to me especially the block to determine the right constructor. Does Java have a more streamlined way of executing this pattern?
One suggestion can be
public class CommonClass {
private static HashMap<String, Class> potentialClasses = new HashMap<>();
static {
potentialClasses.put("A", TypeA.class);
potentialClasses.put("B", TypeB.class);
potentialClasses.put("C", TypeC.class);
potentialClasses.put("D", TypeD.class);
}
public static <T extends Common> T factory(String key) throws Exception {
Class[] cArg = new Class[1];
cArg[0] = NecessaryConstructor.class;
Class<T> classType = potentialClasses.getOrDefault(key, DefaultClass.class);
return classType.getDeclaredConstructor(cArg).newInstance(descriptor);
}
In case the logic is so simple as in your case, you may use reflection, without defining mapping:
public static Common factory(String key, InstantiationObj instantiationObj) {
String className = "Type" + key;
Class<T> classType = Class.forName(className);
...
Thus, for key "A" the variable className will have value "TypeA", for key "B" it will have value "TypeB", etc.
But this will work in this simple case only, when mapping of parameter key to class names follows a simple pattern.
In case the logic becomes more complex later on, you would need if (...) clauses for every condition.
One way I like implementing the factory pattern is with using spring. You can have as many classes of a specific type in your project.
Then, inject or autowire a List of same type in a class and Spring will set all instances of that type in the list.
Finally, transform the list to a map like you have and you will have maximized the idea of
“Closed for modification , open for extensibility” on you factory and project.
There is a Message superclass and there are various Message subclasses like WeddingMessage, GreetingMessage, FarewellMessage, Birthday Message.
The Message superclass has a constructor:
public Message(String messageType){
this.messageType = messageType;
}
The message subclasses all have different constructors, but they all make a call to the superclass, where they pass the messageType as an argument So for example:
public BirthdayMessage( String name, int age){
super("birthday");
System.out.println("Happy birthday " + name + "You are " + age " years old");
public FareWellMessage(String name, String message){
super("farewell");
System.out.println(message + " " + name);
}
The messageType which is created is determined by arguments passed in by the user. So for example, if a user inserts 'birthday John 12', then a BirthdayMessage will be created with parameters John and 12. If a user enters 'farewell Grace take care' then an instance of FarewellMessage is created with those parameters.
Instead of having a bunch of if/else statements or a switch case, in the form of something like-
words[] = userinput.slice(' ');
word1 = words[0];
if (word1 == birthday)
create new BirthdayMessage(parameters here)
if (word1 == wedding)
create new weddingMessage(parameters here)
etc
How could i use reflection to determine which type of Message class to create.
My current idea is to use the File class to get all the Files in the package which contain the message subclasses. Then use reflection to get each of their constructor parameter types and see if they match the parameters given by user input. Then make instances of those matching classes with random parameters. When made, the subclass will make a call to its superclass constructor with its messageType. Then i can check to see if the messageType variable matches the user input.
So if the user enters 'birthday john 23'
I find all constructors in the package that take a String and an int as parameters and that have a field messageType(inherited from Message). Then i create an instance of that class and check if the messageType is == to the first word in the user input (birthday in this case). If it is, then i create an instance of that class with the user provided parameters.
Is there a better way to do this with reflection?
If you want to go this route (I hate reflection, but it has it's uses) make sure you isolate it inside a factory class. I would recommend looking into #Annotations and mark the classes you want to be scanned with a specific annotation.
Something like: (must admit, actually had fun writing this example)
annotation:
#Target(value = {ElementType.TYPE})
#Retention(RetentionPolicy.RUNTIME)
public #interface GreetingcardInstance {
public String value();
}
Your 2 message classes and base class
public abstract class Message {
private String name;
public Message(String name) {
this.name = name; // not used, but to keep it in line with your example
}
}
#GreetingcardInstance("birthday")
public class BirthdayMessage extends Message {
public BirthdayMessage(Integer i) {
super("birthday");
// this line prints if this works.
System.out.println("Birthdaymessage created: " +i);
}
}
#GreetingcardInstance("other")
public class OtherMessage extends Message{
public OtherMessage(Integer i, Integer j) {
super("other");
}
}
And the factory that hides the nasty reflection code
public class CardFactory {
private final Map<String, Class> messageClasses;
public CardFactory() {
// I had all my implementations of Message in the package instances
Reflections reflections = new Reflections("instances");
Set<Class<?>> greetingCardAnnotations = reflections.getTypesAnnotatedWith(GreetingcardInstance.class);
Map<String, Class> result = new HashMap<String, Class>();
for (Class c : greetingCardAnnotations) {
if (Message.class.isAssignableFrom(c)) {
GreetingcardInstance annotation = (GreetingcardInstance) c.getAnnotation(GreetingcardInstance.class);
result.put(annotation.value(), c);
}
}
messageClasses = result;
}
public Message createMessage(String messageType, Object[] arguments) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
Class clazz = messageClasses.get(messageType);
if (clazz == null) {
throw new IllegalArgumentException("MessageType: " + messageType + " not supported");
}
Class[] argumentTypes = new Class[arguments.length];
for (int i = 0; i < arguments.length; ++i) {
argumentTypes[i] = arguments[i].getClass();
}
Constructor constructor = clazz.getConstructor(argumentTypes);
return (Message) constructor.newInstance(arguments);
}
}
You can either use spring or google's library or scan them by hand, though you'll find that's a pain in the behind. In this example I used the google library which works pretty well.
in this particular implementation the classes all live in the same package. I don't think this is too bad but might not work for you.
I've also not handled basic types, the constructors in this case take Integer, not int as I originally intended.
When you parse a string, just parse the arguments into String, INteger, etc. and pass them as an Object[] , whcih will be used as constructor args.
public static void main(String[] argv) throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
CardFactory cf = new CardFactory();
System.out.println(cf.toString());
cf.createMessage("birthday", new Object[] { new Integer(0) });
}
output:
Birthdaymessage created: 0
Wouldn't it be simpler to instead of creating different classes for each message type use different formats which you could store somewhere like Map<String,String>?
I mean something like
Map<String,String> formats = new HashMap<>();
formats.put("birthday","Happy birthday %s. You are %d years old%n");//name, age
formats.put("farewell","%s %s%n");//message, name
Object[] data = {"Dany", 5};
System.out.printf(formats.get("birthday"),data);
data = new Object[]{"Ferwell Jack.","We will miss you"};
System.out.printf(formats.get("farewell"),data);
If you don't want to recompile your code after each change in formats you can store them in file and load when application starts, or when needed.
Simple way to do it is by java.util.Properties class.
You can create formats.properties file with content like
birthday=Happy birthday %s. You are %d years old%n
farewell=%s %s%n
and code using it could look like
Properties formatProp = new Properties();
formatProp.load(new FileReader("formats.properties"));//
Object[] data = {"Dany", 5};
System.out.printf(formatProp.getProperty("birthday"),data);
data = new Object[]{"Ferwell Jack.","We will miss you"};
System.out.printf(formatProp.getProperty("farewell"),data);
There are lots of ways to do what you want. One way would be to learn how to use an injection library like Google Guice. You'll probably get the most mileage out of that in the long run. Another option would be to learn a language like Clojure edit Clojure example added at end.
If you'd like to see a minimal example of what would look like Java, the following class' main will show you how to do that. Basically, it takes a map of String->Classnames (strings), and turns it into a map of String->Class (objects), then a super simple builder method looks up the codeword in the map and constructs a new instance that class and returns it.
The main builds two of them and prints their output. e.g.
I am a bar.
I'm a baz!
Here's the Java program. If you change the package, you'll have to change the classnames in the textConfig variable. The equivalent Clojure code follows.
package foo;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;
public abstract class Foo {
public abstract String something(); // the abstract method
static class Bar extends Foo { // one subclass
#Override public String something() {
return "I am a bar.";
}
}
static class Baz extends Foo { // another subclass
#Override public String something() {
return "I'm a baz!";
}
}
public static Class loadClass(String classname) {
try { // wrapper for Class.forName that doesn't throw checked exception
return Class.forName(classname);
} catch (ClassNotFoundException ex) {
throw new IllegalArgumentException(ex);
}
}
public static Map<String, Class> buildConfig(Map<String, String> textConfig) {
// turn {codeword, classname} into {codeword, class} entries
// java 8 voodoo follows...
return textConfig.entrySet().stream().collect(Collectors.toMap(
Map.Entry::getKey,
e -> loadClass(e.getValue())));
}
public static Foo construct(Map<String, Class> config, String codeword) {
try { // lookup codeword and return new instance of class
return (Foo)config.get(codeword).newInstance();
}
catch(InstantiationException | IllegalAccessException ex) {
throw new IllegalArgumentException(ex);
}
}
public static void main(String[] args) {
// some configuration, you could hardcode this, or even put the
// data in annoations if you want to be fancy
Map<String, String> textConfig = new HashMap<>();
textConfig.put("codeword-bar", "foo.Foo$Bar");
textConfig.put("codeword-baz", "foo.Foo$Baz");
// turn your text config into something more immediately useful
Map<String, Class> config = buildConfig(textConfig);
// show that it works.
System.out.println(construct(config, "codeword-bar").something());
System.out.println(construct(config, "codeword-baz").something());
}
}
edit
The verbosity of the above code was driving me nuts. So, in case you're interested, here's equivalent code in Clojure.
It puts two functions into a map with the keys :bar and :baz and it looks them up, invokes them and prints the return value.
user=> (def config {:bar (fn [] "I am a bar.") :baz (fn [] "I'm a bar!")})
#'user/config
user=> (println ((:bar config)))
I am a bar.
nil
user=> (println ((:baz config)))
I'm a bar!
nil
I'm migrating a project from C# to Java.
I have many classes, which have a lot of properties and the user can set any subset of them.
So to initialize the class I provide an empty constructor and the user can initialize any property using the C# initialization list as following:
var a = new MyClass() { Prop1 = "something", Prop2 = 8, Prop15 = new Point(2,3) };
What is the best practice for such a case in Java?
I've seen the following syntax:
MyClass a = new MyClass(){
{
setProp1("Something");
setProp2(8);
setProp15(new Point(2,3));
}
};
However, I understand this is a lot more than a syntactic sugar, it actually creates an anonymous class and places all the methods in the initialization block of the new class.
So I'm not sure that it is the recommended way to initialize such a class.
What is the recommendation for such a case?
You have to create POJO for your class and then initialize it field by using it's setter method.
class MyClass{
Prop1 = null;
Prop2 = null;
// getter and setter method
}
I like to use a definition class.
public class VehicleDef
{
int wheels;
Color color;
Brand brand;
Type type;
int cylinderVolume;
....
}
Now, you can create a constructor that takes this VehicleDef class as an argument:
public class Vehicle
{
// all props here:
public Vehicle (VehicleDef def)
{
// set properties and do stuff
}
}
Now, you can use it like this:
VehicleDef def;
def.wheels = 4;
def.color = Color.RED;
def.brand = Brands.HONDA;
def.type = VehicleTypes.CAR;
def.cylinderVolume = 400;
Vehicle vehicle = new Vehicle(def);
Having an object of an anonymous subclass isn't that bad usually. It only becomes a problem when you use constructs like if (object.getClass() == MyClass.class) but these shouldn't really be necessary when you write proper object-oriented code. Better use if (object instanceof MyClass) which is also true for subclasses of MyClass or even better put any class-specific code into the class itself.
An alternative way to initialize an object with many attributes is to use the Builder pattern.
Create a public class nested inside MyClass which has the purpose to create an instance of MyClass. Because it is nested inside MyClass it can access all the private fields of the instance it is initializing. Using such a builder could look like this:
MyClass a = new MyClass.Builder().setProp1("Something")
.setProp2(8)
.setProp15(new Point(2,3))
.build();
This example uses a builder with a fluent interface: All setters return this which allows you to chain method-calls with a simple . between them.
Without double-brace-initialization:
MyClass a = new MyClass();
a.setProp1("Something");
a.setProp2(8);
a.setProp15(new Point(2,3));
This is the way to go if the number of (mutable) properties is large.
When some properties are immutable (final), adding a specific constructor is necessary.
Any number of additional constructors can be added to pass properties at construction time (if possible, also add a default constuctor with no args):
public class MyClass {
// default constructor
public MyClass() {
}
// convenience constructor
public MyClass(String s, int i, Point p) {
setProp1(s);
setProp2(i);
setProp15(p);
}
}
With the introduction of generics, I am reluctant to perform instanceof or casting as much as possible. But I don't see a way around it in this scenario:
for (CacheableObject<ICacheable> cacheableObject : cacheableObjects) {
ICacheable iCacheable = cacheableObject.getObject();
if (iCacheable instanceof MyObject) {
MyObject myObject = (MyObject) iCacheable;
myObjects.put(myObject.getKey(), myObject);
} else if (iCacheable instanceof OtherObject) {
OtherObject otherObject = (OtherObject) iCacheable;
otherObjects.put(otherObject.getKey(), otherObject);
}
}
In the above code, I know that my ICacheables should only ever be instances of MyObject, or OtherObject, and depending on this I want to put them into 2 separate maps and then perform some processing further down.
I'd be interested if there is another way to do this without my instanceof check.
Thanks
You could use double invocation. No promises it's a better solution, but it's an alternative.
Code Example
import java.util.HashMap;
public class Example {
public static void main(String[] argv) {
Example ex = new Example();
ICacheable[] cacheableObjects = new ICacheable[]{new MyObject(), new OtherObject()};
for (ICacheable iCacheable : cacheableObjects) {
// depending on whether the object is a MyObject or an OtherObject,
// the .put(Example) method will double dispatch to either
// the put(MyObject) or put(OtherObject) method, below
iCacheable.put(ex);
}
System.out.println("myObjects: "+ex.myObjects.size());
System.out.println("otherObjects: "+ex.otherObjects.size());
}
private HashMap<String, MyObject> myObjects = new HashMap<String, MyObject>();
private HashMap<String, OtherObject> otherObjects = new HashMap<String, OtherObject>();
public Example() {
}
public void put(MyObject myObject) {
myObjects.put(myObject.getKey(), myObject);
}
public void put(OtherObject otherObject) {
otherObjects.put(otherObject.getKey(), otherObject);
}
}
interface ICacheable {
public String getKey();
public void put(Example ex);
}
class MyObject implements ICacheable {
public String getKey() {
return "MyObject"+this.hashCode();
}
public void put(Example ex) {
ex.put(this);
}
}
class OtherObject implements ICacheable {
public String getKey() {
return "OtherObject"+this.hashCode();
}
public void put(Example ex) {
ex.put(this);
}
}
The idea here is that - instead of casting or using instanceof - you call the iCacheable object's .put(...) method which passes itself back to the Example object's overloaded methods. Which method is called depends on the type of that object.
See also the Visitor pattern. My code example smells because the ICacheable.put(...) method is incohesive - but using the interfaces defined in the Visitor pattern can clean up that smell.
Why can't I just call this.put(iCacheable) from the Example class?
In Java, overriding is always bound at runtime, but overloading is a little more complicated: dynamic dispatching means that the implementation of a method will be chosen at runtime, but the method's signature is nonetheless determined at compile time. (Check out the Java Language Specification, Chapter 8.4.9 for more info, and also check out the puzzler "Making a Hash of It" on page 137 of the book Java Puzzlers.)
Is there no way to combine the cached objects in each map into one map? Their keys could keep them separated so you could store them in one map. If you can't do that then you could have a
Map<Class,Map<Key,ICacheable>>
then do this:
Map<Class,Map<Key,ICacheable>> cache = ...;
public void cache( ICacheable cacheable ) {
if( cache.containsKey( cacheable.getClass() ) {
cache.put( cacheable.getClass(), new Map<Key,ICacheable>() );
}
cache.get(cacheable.getClass()).put( cacheable.getKey(), cacheable );
}
You can do the following:
Add a method to your ICachableInterface interface that will handle placing the object into one of two Maps, given as arguments to the method.
Implement this method in each of your two implementing classes, having each class decide which Map to put itself in.
Remove the instanceof checks in your for loop, and replace the put method with a call to the new method defined in step 1.
This is not a good design, however, because if you ever have another class that implements this interface, and a third map, then you'll need to pass another Map to your new method.
I am writing this query service that's suppose to work with couple predefined classes. However, it seems to me to be redundant that, when using this service class, I need to pass both the Type of the class and a class object it self. For example, to query "Contact" object, I'll need to provide both and Contact.class, like the following:
lookupService = new MyLookupServiceImpl<Contact>(Contact.class);
In this case, is there a way to initialize Class without passing in "Contact.class"?
The service class look like the following:
public class MyLookupServiceImpl<T> {
private Class<T> cls;
public MyLookupServiceImpl(Class<T> clz){
this.cls = clz;
}
public T queryObject(String sql) {
try {
QueryResult result = ConnectionFactory.getConnection().query(sql);
if(result.getSize()>0){
T obj=null;
MyObject sObj = result.getRecords()[0];
MyObjectBuilder<T> ob = new MyObjectBuilder<T>(cls);
obj = ob.buildORMObject(sObj);
return obj;
}
} catch (ConnectionException e) {
logger.warn(e.toString());
}
return null;
}
}
Any suggestion would be appreciated.
Thank you,
The answer is NO. In java, because of type erasure, there is no other way infer/get this info at runtime other that passing in the type info as a Class<?> instance.
This is most likely necessary because it is not possible to create a new instance of an arbitrary class indicated by a type parameter; in other words, you cannot do:
T obj = new T();
because of the way Java generics are implemented (with type erasure).
Note that in your code, cls is passed to MyObjectBuilder<T> which is most likely an object that creates new instances of T. MyObjectBuilder<T> uses reflection to create a new instance of T, with a statement like this:
T obj = cls.newInstance();
See also: Create new instance of T in Java
Bala is correct (+1) unfortunately. However, if you use a Dependency Injection framework like Guice you could ask Guice to pass you a TypeLiteral which is the type you're interested in. You could do something like this:
public class MyLookupServiceImpl<T> {
private Class<T> cls;
#Inject
public MyLookupServiceImpl(TypeLiteral<T> type){
this.cls = (Class<T>)type.getRawType();
}
}
Then use the Guice Injector to pass you instances of MyLookupServiceImpl. Just an idea! :)