繁体   English   中英

如何在特定情况下Java不是类型安全的?

[英]How can it be that Java is NOT type safe in a particular situation?

今天我发现了一个非常奇怪的JVM 行为 ,一个(通常是类型安全的) List<Date>确实在运行时持有List<MyObject>

我想知道怎么会发生,但在网络上找不到任何东西。

情况就是这样:我正在使用JRE 1.6.0_18-b07JBoss EAP 6.0 Server上使用Spring Data JPA 1.2.0

错误地,在Spring Data JPA Repository类中,在@Query表达式中写入了错误的结果类型。 应该是:

  @Query("select distinct trunc(record.orderDateTime) from MyType record [...]" )
  public List<Date> getOrderDates(...);

但是:

  @Query("select record from MyType record [...]" )
  public List<Date> getOrderDates(...);

因此,目的是加载日期列表( java.util.Date ),如果在第一个代码片段中正确定义了查询,则该日期工作正常。

但是编码错误导致了以下结果:在运行时,实际上返回了一个List<MyType> ,即使方法的签名定义了List<Date> 同样在我的模型中, List<Date>的属性包含List<MyType> 我调试了它,无法相信我的眼睛! 我甚至可以将此列表的内容写入JSP(我只识别这种奇怪的行为,因为尝试从MyTypeDate键入匹配时出现Spring Expression Language错误,因此无法再显示JSP,其中当然不得不崩溃)。

天哪,我现在应该放弃对Java类型安全性的信任吗?

有没有人遇到过这样的问题?

是否存在对此的解释?

我可以做任何事情来解决这个问题,还是一般问题? 也许是另一个版本的JRE,JBOSS,......?

我想知道怎么会发生,但在网络上找不到任何东西。

之所以发生这种情况,是因为泛型主要是仅编译时功能。 元数据是根据类的类型参数,字段等来维护的......但是在执行时,类型参数(大部分)都会丢失。 例如:

Object x = new ArrayList<String>();
Object y = new ArrayList<Integer>();
System.out.println(x.getClass() == y.getClass()); // True

JVM无法区分 - 这就是为什么当您尝试强制转换时会收到警告的原因:

// At execution time, this cast will *really* only check for List
List<String> dodgyCast = (List<String>) y;

大多数情况下,编译器使用泛型保持“常规”代码安全。 但是当你有像ORM这样的东西通过反射或动态字节代码提供值时,所有这些安全性就会消失。

可悲的是,由于类型擦除,可能会发生这种情况。 您在集合中设置的类型仅在编译时检查,而不是在运行时检查。

问题是您的查询未编译,因此Java无法知道它将返回哪种对象。 为了避免这种行为,我总是创建我的查询测试。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM