将未知的反射类的类型更改为泛型

时间:2018-07-06 17:12:29

标签: java generics reflection dependency-injection type-conversion

简介

我正在代码中实现依赖注入。

我已经到了一个配置了名为config.properties的属性文件的地步。我也知道如何将属性字符串反映到一个对象中。

问题

问题是,当我进行反射时,Java表示类型将为Class<?>,并且我希望它为通用类型D,因此我可以重用与此类耦合的代码。

我在哪里

下面是D是我要投射到的通用对象的代码。 ObjectImplementation是抽象层(因此在该类上使用的每个对象都实现该接口)。 SalesRepbyID只是容器类的名称。 fileparser是依赖项注入的另一部分(暂时忽略)。最后,解析是构造我需要投射的实例的方法。

我已经搜索了标题,并搜索了Stackoverflow结果以及外部网页。我认为我所缺少的称为工厂模式,但是我不确定如何实现这种事情,或者我是否处在正确的道路上。

目标

这里的目标是使用反射和通用类型,以便可以在此容器类中构造实现ObjectImplementation的任何类,并且可以通过属性文件而不是代码来更改要使用的实现。我在命名约定方面所做的任何愚蠢的事情,请让我知道,并一如既往地感谢您的努力。

public class SalesRepbyId<D extends ObjectImplementation> implements 
DataParserImplementation<Map<String,D>> {
private FileParserImplementation<ArrayList<String[]>> FileParser;

public SalesRepbyId(FileParserImplementation<ArrayList<String[]>> FileParser){
    this.FileParser = FileParser;

}
@Override
public Map<String, D> Parse() {
    Properties prop = new Properties();
    try {
        prop.load(Data_Parser.class.getResourceAsStream("config.properties"));
    } catch (IOException e) {
        System.out.println(e + " error with config.properties I/O");
    }
    try {
        Class<?> classToUse = Class.forName(prop.getProperty("ObjectImplementation"));

//construct classToUse instances here in the method many times with type D

1 个答案:

答案 0 :(得分:0)

因此,在这种情况下,您可以做的是在构造Class<D>时传递SalesRepById

class SalesRepById<D extends ...> {
    private Class<D> typeOfD;

    SalesRepById(..., Class<D> typeOfD) {
        ...
        this.typeOfD = typeOfD;
    }

    @Override
    public Map<String, D> parse() {
        try {
            Class<? extends D> typeFromFile =
                Class.forName(...).asSubclass(typeOfD);

            D instanceOfD =
                typeFromFile.getConstructor().newInstance();

        ...
    }
}

(请参阅Class.asSubclass,它用于向下广播Class实例。例如,如果我说Class<?> c = String.class;,我可以说c.asSubclass(CharSequence.class)以获得{{ 1}}。但是,Class<? extends CharSequence>会引发异常。

这意味着您必须在编译时和构造对象时知道Integer.asSubclass(CharSequence.class)的实际类型:

D

令我感到不安的是,您似乎在说SalesRepById<ActualType> srbid = new SalesRepById<>(..., ActualType.class); 的实际类型是由文件指定的。在那种情况下,我认为您不应该为D使用类型参数。看来您应该改用以下方式:

D

这仍然允许文件指定要使用的确切子类型,并且您不必在编译时就知道它。

通常,反射和泛型并不能很好地融合在一起。反射仅在运行时,而泛型仅在编译时。