I am using java 8 and I would like to detect subtle class differences at compile time modifying withProperty()
header. This code is working but I would like to force a compilation error in main()
function because this::getInteger
returns an Integer and the second argument is a String.
import java.util.function.Function;
public class MatcherProperty<T, K> {
public static <T, K> MatcherProperty<T, K> withProperty(
Function<T, K> mapper,
K expected
){
return new MatcherProperty<>();
}
private Integer getInteger(Object object) {
return 1;
}
public void main() {
withProperty(this::getInteger, "Random string");
}
}
I would like to avoid (if possible) a third argument in withProperty()
function specifying the class type or something like this. Maybe K is translated to Object, the superclass of Integer an String. What is actually happening under the hoods? Is it possible to force a compilation error in this case?
Thanks in advance.
There is no compile error in your current code because the result of the call to withProperty
is ignored.
If you would try to assign the result like this:
MatcherProperty<Object, Integer> mp = withProperty(this::getInteger, "Random string");
then you'd get a compilation error because the String
argument doesn't match type K
which is Integer
in the result.
If you would try to assign the result like this:
MatcherProperty<Object, String> mp = withProperty(this::getInteger, "Random string");
then you'd get a compilation error because the Integer
result of the function given as first argument doesn't match type K
which is String
in the result.
You can only make the assignment compile by using a common super type such as Object
or Serializable
:
MatcherProperty<Object, Serializable> mp = withProperty(this::getInteger, "Random string");
You can't force people to assign the result of course. You can add a Class<K>
parameter to make them choose a class (such as Integer.class
or String.class
) but even then, they can just pass Serializable.class
or Object.class
instead:
public static <T, K> MatcherProperty<T, K> withProperty(
Class<K> clazz,
Function<T, K> mapper,
K expected
)
withProperty(String.class, this::getInteger, "Random string"); // doesn't compile
withProperty(Integer.class, this::getInteger, "Random string"); // doesn't compile
withProperty(Serializable.class, this::getInteger, "Random string"); // compiles
If you don't tell the compiler somehow what type K
is (using class argument or assignment of the return value which is of type K
) then it will infer the common type, Serializable
in this case.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.