@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;
}
}
В течение многих лет этот unit test прошел. Затем после перехода на Java 8 в определенных средах, когда код скомпилирован через javac, он выбирает перегрузку StringUtils.isNullOrEmpty(String). Это приведет к сбою unit test со следующим сообщением об ошибке:
java.lang.ClassCastException: java.util.Date cannot be cast to java.lang.String
at 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 32bit).
Java вывод типа, который выбирает наиболее специфическую перегрузку из всех применимых перегрузок при компиляции, был изменен в Java 8. Я полагаю, что моя проблема имеет какое-то отношение к это.
Я знаю, что компилятор видит возвращаемый тип метода MyProperties.getProperty(...) как T, а не Date. Поскольку компилятор не знает тип возвращаемого метода getProperty (...), почему он выбирает StringUtils.isNullorEmpty(String) вместо StringUtils.isNullorEmpty(Object) - который всегда должен работать?
Является ли это ошибкой на Java или просто результатом изменения вывода типа Java 8? Кроме того, почему разные среды, использующие одну и ту же версию java, компилируют этот код по-другому?