Java 8 does have improved target type inference. This means that the compiler will use the target type to infer the type parameter.
In your case, this means that in this statement
StringUtils.isNullOrEmpty(props.getProperty("value"));
Java will use the parameter type of isNullOrEmpty
to determine the type parameter of the getProperty
method. But there are 2 overloads of isNullOrEmpty
, one taking an Object
and one taking a String
. There is no bound on T
, so the compiler will choose the most specific method that matches -- the overload that takes a String
. T
is inferred to be String
.
Your cast to T
is unchecked, so the compiler allows it, but it gives you an unchecked cast warning about casting an Object
to a T
. However, when the isNullOrEmpty
method is called, the class cast exception is thrown, because the original object was really a Date
, which can't be converted to a String
.
This illustrates the dangers of ignoring the unchecked cast warning.
This didn't occur in Java 7, because the improved target type inference didn't exist. The compiler inferred Object
.
The improved target type inference in Java 8 has revealed that your getProperty
method is incorrectly ignoring the unchecked cast warning that you're suppressing with @SuppressWarnings
.
To fix this, don't even have an overloaded method that takes a String
. Move the String
-specific logic inside the overload that takes an Object
.
public static boolean isNullOrEmpty(Object o) {
// null instanceof String is false
String string = (o instanceof String) ? ((String) o) : valueOf(o);
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;
}
Of course this means that the generics on the getProperty
method are meaningless. Remove them.
public Object getProperty(String name) {
return properties.get(name);
}