简体   繁体   中英

Create an instance of the given Class type

I have some child classes where all of them are extended by one common parent class.

What I want is a concrete method in the parent class and, that method should return a new object of the given class type.

This is what I tried.

class Vehicle {

    public <T> T get(Class<T> type){
        //return new T();
    }
}

class Car extends Vehicle {
}

class Van extends Vehicle {
}

Above get(...) method's

return new T();

statement gives an compile error saying,

Unexpected type
required: class
found: type parameter T

I can't create objects of the child classes directly like,

new Car();

for some reason. There can be any number of child classes so overriding get() method in each of them is also not an option. Any idea?

You can instantiate a Class object using Class.newInstance() .

public <T> T get(Class<T> type) throws InstantiationException, IllegalAccessException {
    return type.newInstance();
}

But there must be a no-argument constructor for the class; and it might throw an exception.

T is a placeholder for a type, not a type; therefore you cannot call new T() because you don't have a value in T .

The value is in type and you must use that variable.

It is important to remember that, in the generics system, placeholders are not types in the sense of Java types. They follow different rules about how they are constrained (super, etc). They have different bindings on when they apply (compile time). These characteristics mean they cannot be reconciled with Java's type system, even if they (to a degree) control it.

Now you do have a Class object as a value, bound to the variable type . You can use Java's facilities for creating new instances from the Class object in type .

You can make the base class generic, so you have a proper return type for the get() method.

abstract class Vehicle<T extends Vehicle> {
    public abstract T get();
}

class Car extends Vehicle {
    @Override
    public Car get() {
        return new Car();
    }
}

However, this does not force Car to actually return a Car ; it's free to return a Van .

Modify your get method as in the following code:

public <T> T get(Class<T> type) throws InstantiationException, IllegalAccessException {
    return type.newInstance();
}

In case you have default constructor in Car and Van classes, then you could use this approach:

public static <T extends Vehicle> T get(Class<T> cls) throws Exception {
    return cls.getConstructor().newInstance();
}

Or, as alternative, this one (it looks more preferable to me; but I do not have any contra against previous one):

public static <T extends Vehicle> T get(Class<T> cls) {
    if (cls.isAssignableFrom(Car.class))
        return (T)new Car();
    if (cls.isAssignableFrom(Van.class))
        return (T)new Van();
    throw new RuntimeException("Unknown class '" + cls.getSimpleName() + '\'');
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM