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



简介

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

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

问题所在

问题是,当我做这个反射时,java说这个类型将是Class<?>的,我希望它是一个泛型类型D这样我就可以重用与这个类耦合的代码。

我在哪里

下面是代码,其中D是我要强制转换为的通用对象。ObjectImplementation是抽象层(因此在此类上使用的每个对象都实现了该接口(。SalesRepbyID只是容器类的名称。fileparser是依赖注入的不同部分(暂时忽略它(。最后,Parse 是构造我需要强制转换的实例的方法。

我已经用谷歌搜索了标题,并搜索了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

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

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)以获得Class<? extends CharSequence>。但是,Integer.asSubclass(CharSequence.class)会引发异常。

这意味着您必须在编译时和对象构造时知道D的实际类型:

SalesRepById<ActualType> srbid =
new SalesRepById<>(..., ActualType.class);

让我紧张的是,您似乎在说文件指定了D的实际类型。在这种情况下,我认为您不应该有D的类型参数。似乎您应该改用这样的东西:

class SalesRepById {
SalesRepById(...) {
...
}
@Override
public Map<String, ObjectImplementation> parse() {
try {
Class<? extends ObjectImplementation> typeFromFile =
Class.forName(...).asSubclass(ObjectImplementation.class);
ObjectImplementation instance =
typeFromFile.getConstructor().newInstance();
...
}
}

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

作为一般规则,反射和泛型不能很好地混合。反射是仅运行时的,泛型是仅编译时的。

最新更新