1

I have this code:

    public <V> V getPropertiesByObject(V sample) throws TimeoutException {
//settings fields using reflaction
        return sample;
    }

which I call like this:

MyClass a = getPropertiesByObject(new MyClass());

only because I don't know how to construct an instance otherwise.

I would prefer:

public <V> V getPropertiesByObject(Class<V> sample) throws TimeoutException {
//how to create a new V instance?
    return result;
}

Is there a way to refactor my original code?

1
  • I don't really see a problem with getPropertiesByObject(new MyClass());. Commented May 11, 2015 at 12:38

3 Answers 3

2

You can use reflection - here's a basic implementation that shows one way:

public <V> V getPropertiesByObject(Class<V> clazz, Object... params) throws TimeoutException {
    Class<?>[] paramClasses = new Class<?>[params.length];
    for (int i =0; i < params.length; i++)
        paramClasses[i] = params[i].getClass(); 
    V result = clazz.getConstructor(paramClasses).newInstance((Object[])params);
    return result;
}

The parameter params, which may be empty, are the parameters to pass to the constructor corresponding to those parameters. This code won't handle null values. Here's how you might call it:

String str = getPropertiesByObject(String.class); // blank String
Integer i = getPropertiesByObject(Integer.class, "1"); // 1
Sign up to request clarification or add additional context in comments.

4 Comments

You are losing the benefit from generics with that implementation. For example "String string = getPropertiesByObject(String.class, new Object())" will not report an error at compile time but will crash at runtime. The whole point of generics is to guarantee correctness of calls at compile time and prevent runtime errors.
@vap78 of course - reflection bypasses not only generics, but all static type checks. You can protect yourself from runtime errors by writing unit tests that exercise your reflective code - although not strictly compile time checking, build time checking is close enough (since your run all unit tests when you compile your code). The main downside is you don't get any help from IDEs and this kind of code is harder for read.
what I mean that with the suggested changes the usage of generics makes little sense. The method signature could be "Object getPropertiesByObject(Class clazz, Object... params)" and there will be very little difference - the caller will anyway have to watch to pass parameters that match the constructor of the given class.
@vap78 yes, but if the method is typed, as least the calling code can infer the type so it's quite useful. You're right that typing the method doesn't make its implementation any safer ("the gloves are off" when you use reflection)
1

If V has a parameterless constructor, you can use Class<V>::newInstance().

public <V> V getPropertiesByObject(Class<V> sample) throws TimeoutException {
    V result = sample.newInstance();
    // stuff on V
    return result;
}

Of course, you will use it like this: MyClass a = getPropertiesByObject(MyClass.class)

If you have to specify some parameters, you can do something like:

public <V> V getPropertiesByObject(Class<V> sample, Object... params) throws TimeoutException {
    V result = sample.newInstance();
    result.param0 = params[0];
    result.param1 = params[1];
    // etc  
    return result;
}

But in both case, MyClass must have a parameterless constructor. If you can't edit MyClass, you should use the Bohemian's answer using Constructor.

2 Comments

and if no parameterless ctor?
@user1065869 Well, you can add one and specify parameters like in my edited answer, or use Class::getConstrutor(Class<?>... parameterTypes) as specified in the Bohemian's answer :)
0

So you want to create a method that can create an instance of ANY possible class and set ANY possible fields to the instance?

This is quite hard. Frameworks like GSON have the same issue and they either require that you have a no-argument constructor in the beans used, or provide a way to create instances for a certain class (see Is default no-args constructor mandatory for Gson?).

Else for your specific case - if you know the set of classes that you are going to instantiate then you can implement a factory class that creates instances based on a class object with some kind of if-else-if-else... structure.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.