简体   繁体   中英

Safe method return type for unknown generic during construction

I have a class as follows

public class GenericObjectBuilder {

    private Class<?> classType;

    public GenericObjectBuilder(Class<?> classType) {
       this.classType = classType;
    }
}

I want to be able to add a method (eg getObject) to this class that will return an object of type '?', so that the constructor will determine the return type of this method. Eg

GenericObjectBuilder gc1 = new GenericObjectBuilder(String.class);
String value = gc1.getObject();

GenericObjectBuilder gc2 = new GenericObjectBuilder(Integer.class);
Integer value = gc2.getObject();

I cannot use proper generics in this scenario. For example I cannot do

GenericObjectBuilder<String> gc1 = new GenericObjectBuilder<>();
String value = gc1.getValue();

Is this possible using the constructor argument?

Without Generics I am not sure you will be able to achieve what you target.

Depending on how tied you are to this 3rd party library, you could try and design around it.

  • Pass in a wrapper object.

    If you have control over the constructor and implementation of the GenericObjectBuilder you could pass in a wrapper object.

     GenericObjectResult<String> result = new GenericObjectResult<>(String.class); GenericObjectBuilder builder = new GenericObjectBuilder(result); builder.build(); String object = result.getObject(); 

    This is quite ugly but might as well get you going.

  • Have only the getObject method generic.

    You should be able to have the following implementation.

     GenericObjectBuilder builder = new GenericObjectBuilder(); String value = builder.getObject(String.class) 

    This last implementation is a bit cleaner but you still need to use generics for the getObject method. The class itself will not be generic, though. Maybe this will be OK with the 3rd party library.

  • Make a wrapper builder

    This last approach creates a wrapper builder on top of the GenericObjectBuilder .

     GenericObjectBuilder builder = new GenericObjectBuilder(String.class); // We don't actually care what the constructor is GenericObjectBuilderWrapper wrapper = new GenericObjectBuilderWrapper(builder, String.class); // You could try and get the class from the `builder` if it has the proper API String value = wrapper.getObject(); 

    What the wrapper would do internally, would be something of this kind.

     class GenericObjectBuilderWrapper<T> { private Class<T> clazz; private GenericObjectBuilder delegate; public GenericObjectBuilderWrapper(GenericObjectBuilder delegate, Class<T> clazz) { this.clazz = clazz; this.delegate = delegate; } public <T> getObject() { final Object value = delegate.getObject(); return clazz.cast(value); } } 

If you really cannot use any type of generic anywhere in the project because you are using older version of Java, then you will have to rely on explicit casting.

String value = (String)builder.getObject();

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