1

I'm not certain if this is possible in Java. Also, I'm not able to figure out what to query on Google for this. Anyway, I want a method that takes as an argument a Class (interface or class) and the method's return type is an instance of that Class. I don't want to have to recast an Object after the fact.

I'm not certain if this feature exists or what the syntax would be. Let's say I have a class named XYZ and here is my pseudo method.

private XYZ createInstance(XYZ.class, other args) {
  ...
  // create an instance of XYZ with other args named "_xyz_"
  ...
  return _xyz_;
}

Now assume XYZ is some sort of generic syntax. Is this possible at all in Java? Thanks for any help.

martinatime
  • 2,462
  • 1
  • 17
  • 23

2 Answers2

8
private <T> T createInstance(Class<? extends T> c) {
    return c.newInstance();
}
SLaks
  • 800,742
  • 167
  • 1,811
  • 1,896
  • This is the same approach as the answer given in [Create instance of generic type in Java?](http://stackoverflow.com/questions/75175/create-instance-of-generic-type-in-java). – Joshua Taylor Apr 28 '14 at 19:15
2

Use the diamond operator:

private <T> T createInstance(Class<T> concreteClass){
  return concreteClass.newInstance();
}

//usage
Integer i = instanceWithThatMethod.createInstance(Integer.class);

To pass "arguments", you have to get the Constructor of the class matching the desired parameter types, and invoke the call on that one, like this:

private <T> T createInstance(Class<T> concreteClass, String stringArg){
    return concreteClass.getConstructor(String.class).newInstance(stringArg);
}

//usage
SomeClass s = createInstance(SomeClass, "testString");

//equals
SomeClass s = new SomeClass("testString");

//where SomeClass HAS to serve:
public SomeClass(String s){
  ...
}
dognose
  • 18,985
  • 9
  • 54
  • 99
  • How could we support multiple args? – Mingtao Zhang Apr 28 '14 at 19:26
  • 1
    @MingtaoZhang `getConstructor(Class>... parameterTypes)` is varargs - you could use `concreteClass.getConstructor(Integer.class, String.class, List.class)` and will then receive the reference to `public SomeClass(Integer i, String s, List l)` – dognose Apr 28 '14 at 19:27
  • I am wondering whether we could accept (Object... args) as second parameter for createInstance. Something like this Class[] types = new Class[args.length]; for(int i = 0; i < args.length; i++) { types[i] = args[i].getClass(); } return c.getConstructor(types).newInstance(args); – Mingtao Zhang Apr 28 '14 at 19:29
  • @MingtaoZhang You would need to convert each object to its classType to obtain the constructor. `getConstructor` takes `Class>...` - not (wrong syntax): `?...` – dognose Apr 28 '14 at 19:31
  • I think it should be part of the answer :) – Mingtao Zhang Apr 28 '14 at 19:33
  • @MingtaoZhang Problem: You need to provide the ClassTypes and the values at the same time: `createInstance(Class concreteClass, Object... args, Object... values)` in order to do something like `return concrete.class.getConstructor(args).newInstance(values);` - meaning: `createInstance(SomeClass.class, Integer.class, String.class, 5, "Hello Word")` - but double varargs are not supported. – dognose Apr 28 '14 at 19:43
  • Do those args carry both value and type in runtime? – Mingtao Zhang Apr 28 '14 at 19:44
  • @MingtaoZhang no. If you pass "values" like (`1,"Hello World",false`) you need to use .getClass() to determine their class type, which you can't use to find a constructor. If you pass `Integer.class, String.class, Boolean.class` - there are no values associated. – dognose Apr 28 '14 at 19:50
  • true. Primitives are special in this context ... – Mingtao Zhang Apr 28 '14 at 20:22