Java继承在反射中无法识别

时间:2012-10-01 06:33:17

标签: java inheritance reflection

我一般反对扩展,因为它在类之间创建了一个非常强大的连接,这很容易意外中断。

然而,我终于认为我找到了一个合理的案例 - 我想在现有系统中选择使用压缩版本的文件类型。压缩版本几乎与未压缩版本一样快,并且具有完全相同的可用方法(即读取和写入) - 唯一的区别在于磁盘上的表示。因此,我使用压缩版本扩展了未压缩版本,以便可以使用任何一种文件,只需选择性地对其他类型进行实例化。

public class CompressedSpecialFile extends SpecialFile(){ ... }

if (useCompression){
    SpecialFile = new CompressedSpecialFile();
} else {
    SpecialFile = new SpecialFile();
}

但是,在程序的稍后阶段,我们使用反射:

Object[] values = new Object[]{SpecialFile sf, Integer param1, String param2, ...}
Class myclass = Class.forName(algorithmName);
Class[] classes = // created by calling .getClass on each object in values
constructor = myclass.getConstructor(classes); 
Algorithm = (Algorithm) constructor.newInstance(values)

这一切都运行正常,但现在myclass.getConstructor类抛出NoSuchMethodException,因为SpecialFile的运行时类型是CompressedSpecialFile。

但是,我认为扩展应该如何工作 - 因为CompressedSpecialFile扩展了SpecialFile,任何接受SpecialFile的参数都应该接受CompressedSpecialFile。这是Java反思中的错误,还是我的理解失败?

1 个答案:

答案 0 :(得分:2)

嗯,对这个错误报告的回应似乎表明这是故意的。 http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4301875

  

我们无法对兼容性进行此更改。而且,我们   我希望getConstructor的行为类似于getDeclaredMethod,   这也需要完全匹配,因此更改一个没有意义   没有改变另一个。可以添加一个额外的套件   仅在参数类型匹配方式上有所不同的方法,   然而。   在某些情况下,我们可能希望在运行期间应用   反射相同的过载分辨率算法静态使用   编译器,即在调试器中。实现这一点并不困难   但是,使用现有API的功能,所以添加此功能的情况   核心反射的功能很弱。

该错误报告已作为以下错误报告的副本关闭,它提供了更多的实现细节: http://bugs.sun.com/bugdatabase/view_bug.do;jsessionid=1b08c721077da9fffffffff1e9a6465911b4e?bug_id=4287725

  

解决问题   getMethod的用户必须精确识别传递给参数的类。

     

评价
  此请求的本质是用户想要Class.getMethod   应用与编译器相同的重载规则。我想是的   一个合理的要求,因为我认为有必要经常出现这种情况   各种反射程序,如调试器和脚本解释器,   并且为每个人提供标准实施会很有帮助   做对了。但是,为了兼容性,现有的行为   Class.getMethod应该保持不变,并定义一个新方法。有   以脚印为基础保留此功能的案例   可以使用现有的API实现,尽管效率不高。   另见4401287。   共识似乎是我们应该提供重载解决方案   反射。确切地说,何时提供这样的功能在很大程度上取决于   关于兴趣和潜在用途。
  出于兼容性原因,Class.get(已声明)+ {Method,Constructor}   实施不应改变;应该引入新方法。该   确实需要修改这些方法的规范来定义“匹配”。看到   bug 4651775。

你可以继续深入研究那些引用的错误和我提供的实际链接(讨论的地方以及可能的解决方法)但我认为这得到了推理(尽管为什么在反射中反映java的oop的新方法也没有但实施后,我不知道。)

就变通方法而言,我认为对于一级深度版本的继承,你可以在每个类上调用getSuperclass(),这个类的名称是扩展类的名称,但是它非常不优雅并且与你绑定使用它只适用于以规定方式实施的课程。非常kludgy。我会尝试寻找另一种选择。