Java中反射的一些适当和不适当的用法是什么?

Java中反射的一些适当和不适当的用法是什么?,java,reflection,Java,Reflection,Java的反射API显然是一个非常强大的工具,但并不特别面向对象。在哪些情况下使用反射是合适的(反之,也是不合适的?我建议看一看这本书: 它非常好,非常详细,实际上是关于这一先进概念的完整参考 此外,这比我们在这里所能解释的要多得多,场景、用法和概念,当你简单地阅读它时,首先会清楚:)。在我看来 适当(清洁): 实例化动态加载的实现(如小程序)的根 使用Proxy创建代理或模拟实现(在编译时可能更好) 实现允许不受限制地访问Java库的解释器。(注意,从安全角度来看,解释后的代码现在拥有作为解

Java的反射API显然是一个非常强大的工具,但并不特别面向对象。在哪些情况下使用反射是合适的(反之,也是不合适的?

我建议看一看这本书:

它非常好,非常详细,实际上是关于这一先进概念的完整参考

此外,这比我们在这里所能解释的要多得多,场景、用法和概念,当你简单地阅读它时,首先会清楚:)。

在我看来

适当(清洁):

  • 实例化动态加载的实现(如小程序)的根
  • 使用
    Proxy
    创建代理或模拟实现(在编译时可能更好)
  • 实现允许不受限制地访问Java库的解释器。(注意,从安全角度来看,解释后的代码现在拥有作为解释器的有效特权——可能有点危险。)
适当的黑客:

  • 在第三方代码中绕过Java语言访问控制,这是您必须做到的
  • 实现“交叉关注点”,如持久性
  • 删除加载导致启动较慢的类的静态依赖项
不适当:

  • 规避Java语言访问控制的一般方法(包括测试)
  • 任何依赖于特定反射调用类提供的Java语言访问权限的内容
  • 任何可以实现接口的地方

一般来说,反射比生成源代码要容易得多,而生成源代码比创建字节码要容易得多。

与任何技术一样,共同的感觉应该是决定哪种用法是合适的驱动因素。而不是“模式”,阻碍大脑的思维能力

不要将反射视为“技术”。它只是一个与任何数据类型关联的元数据对象,在运行时可用。简单对象,以最佳可能的方式实现(只要想想您将如何实现它,您很可能会猜到实际实现)

从简单的考虑来看,很明显,类型为get的类/方法/字段上的所有方法在每次调用时都会按名称进行映射/索引查找,因此此操作在应用程序生命周期中只需要执行一次。但是一旦获得,method.invoke(object,args)的性能与object.method(args)的性能几乎相同,因为它只引入了一个更高级别的间接寻址,不涉及任何额外的查找

我将使用基于反射的方法的示例:

  • 按名称初始化/复制/序列化/打印bean的属性,这项任务在大多数业务应用程序中都会出现,并且,一旦您使用动态编程(意味着只进行一次基于名称的查找来初始化转换器/加载程序,然后在应用程序生命周期中应用相同的转换器)增加的开销不多,但为软件增加了极大的灵活性(参见commons beanutils,spring依赖注入)

  • 事务/会话/授权/度量/模拟代理(使用来自JDK的动态代理API)

  • 可以方便地替代XSD消除XML解析器(使用JPA/JAXB/WS/JAXB和任何其他注释),以保留关于对象应如何保持自身、每个字段应显示哪些GUI标签等的补充信息(请参阅jax WS,hibernate)

我想不出一个不使用反射的例子,只是在基于元数据的解决方案不是最佳解决方案的情况下不使用反射(仅分析元数据对象是什么)。

我使用反射为CS分配计算简单的未修改代码位的时间。有三个素数查找程序,我们将比较从1E5到1E6的10个等距天花板的运行时间。因为它们都以相同的方式接收输入(stdin中的天花板),所以我可以使用stdio的重定向为它们提供天花板的“键盘”输入,放弃输出,并干净地比较运行时间。当然,这只有通过使用反射调用主方法才能实现(不修改代码)。不需要修改测试程序,但我认为这会很有趣。然后我发现这个帖子在寻找r

写起来很有趣,解决问题和维护起来也很痛苦,就像任何API一样,在需要的时候使用它;我遇到了一些我最近维护的代码,我认为是这样的。