我在滥用/滥用Java反射吗?

时间:2011-08-04 15:01:24

标签: java reflection casting

我正在编写一个程序来读取文件中的数据,该文件可能是多种格式之一(实际上是相同格式的不同版本),我正在使用反射为每种格式调用相应的函数。假设文件格式是在文件的第一个字节上指定的数字:

Class DataFile extends Model {
...
Blob file
...
public void parse() throws Exception{

    InputStream is = file.get();

    Class c = Class.forName("models.DataFile");
    Method m = c.getMethod("parse_v"+is.read(), (Class []) null);
    m.invoke(this, (Object []) null);
}

public void parse_v0() throws Exception{
   ...
}

public void parse_v1() throws Exception{
   ...
}
}

我的问题是,我是在滥用/滥用反思吗?我觉得我应该使用继承并使用自己的“解析”过程为每个文件类型创建一个不同的类,但在开始解析之前我不知道文件类型...然后我不能“低估”并且只使用像((DataFile_v1) this).parse()这样的东西,所以我有点迷失。

感谢您的时间!

5 个答案:

答案 0 :(得分:7)

这没有什么根本性的错误,但是更灵活和可扩展的方法来做同样的事情就是将版本信息用作Map中的密钥,并且具有{{1}中的值是处理程序对象。然后任何代码都可以注册一个处理程序(处理程序都可以实现一个公共接口),你的读者代码可以只查找Map中的处理程序并调用它。

请务必处理Map不包含特定版本处理程序的情况!

答案 1 :(得分:2)

如果您使DataFile接口定义parse方法,并实现具有多个类(DataFile_v1等)的接口,则调用代码不必知道选择了哪种实施方式。

DataFile dataFile = dataFileFactory.getForVersion(is.read());
dataFile.parse(file);

我认为从一般设计的角度来看,这是一种更好的方法。但是,在某些时候,您需要在版本号和DataFile实现之间创建某种映射。 (在这种情况下,我是在假想的dataFileFactory中进行的。)你必须确定使用反射或其他方法选择实现是否更合适。

答案 2 :(得分:0)

我认为在这里使用反射是可以的。替代方案是使用继承或枚举(即Strategy pattern),以及从版本代码到正确策略的映射。一旦初始化了所有所需的映射,就可以从地图中获取正确的解析器对象并调用它。但是,设置此解决方案仍然需要大量的样板代码,这会降低其可读性。

答案 3 :(得分:0)

你在做什么也不错。如果你想在不同的类中使用不同的解析器,你不能像你说的那样向下转换,但你可以实例化一个新的解析器对象。因此,在您知道要解析的格式之前,您现有的类将是实际解析器前面的一个外观,它们不会被实例化。

答案 4 :(得分:0)

您可以使用集合,但使用反射也可以查找集合。如果您的映射没有改变,我会使用反射。

getClass().getMethod("parse_v"+is.read()).invoke(this);