<分区>
@Test
public void test() {
MyProperties props = new MyProperties();
props.setProperty("value", new Date());
StringUtils.isNullOrEmpty(props.getProperty("value"));
}
public class MyProperties {
private Map<String, Object> properties = new HashMap<String, Object>();
public void setProperty(String name, Object value) {
properties.put(name, value);
}
@SuppressWarnings("unchecked")
public <T> T getProperty(String name) {
return (T) properties.get(name);
}
}
public class StringUtils {
public static boolean isNullOrEmpty(Object string) {
return isNullOrEmpty(valueOf(string));
}
public static String valueOf(Object string) {
if (string == null) {
return "";
}
return string.toString();
}
public static boolean isNullOrEmpty(String string) {
if (string == null || string.length() == 0) {
return false;
}
int strLength = string.length();
for (int i = 0; i < strLength; i++) {
char charAt = string.charAt(i);
if (charAt > ' ') {
return true;
}
}
return false;
}
}
多年来,这个单元测试一直通过。然后升级到Java 8后,在某些环境下,通过javac编译代码时,选择了StringUtils.isNullOrEmpty(String)重载。这会导致单元测试失败并显示以下错误消息:
java.lang.ClassCastException: java.util.Date 无法转换为 java.lang.String
在 com.foo.bar.StringUtils_UT.test(StringUtils_UT.java:35)
单元测试通过 ant(ant 1.9.6、jdk_8_u60、Windows 7 64 位)在我的机器上编译和运行时通过,但在另一个具有相同版本的 ant 和 java(ant 1.9.6 jdk_8_u60、Ubuntu 12.04。 4 32 位)。
Java 的 type inference ,它在编译时从所有适用的重载中选择最具体的重载,已在 Java 8 中更改。我认为我的问题与此有关。
我知道编译器将 MyProperties.getProperty(...) 方法的返回类型视为 T,而不是 Date。由于编译器不知道 getProperty(...) 方法的返回类型,为什么它选择 StringUtils.isNullorEmpty(String) 而不是 StringUtils.isNullorEmpty(Object) - 这应该始终有效?
这是 Java 中的错误还是仅仅是 Java 8 类型推断更改的结果?另外,为什么使用相同版本的 java 的不同环境会以不同方式编译此代码?