Reputation: 12459
The following Java code is valid - no compile- or run-time errors.
public class Test {
public static void main(String[] args) {
System.out.println(
new Comparator<>("hello", 5).areEqual()
);
}
private static class Comparator<T> {
private final T left;
private final T right;
public Comparator(T left, T right) {
this.left = left;
this.right = right;
}
public boolean areEqual() {
return left.equals(right);
}
}
}
I expect the values "hello"
and 5
are casted to Object
, which is a common parent.
Is there a way to write the class in such a way that passing other than objects of the same type causes a compile-time error? I.e. passing objects casted to a common ancestor not allowed.
Upvotes: 1
Views: 1528
Reputation: 718
As @Makoto already answered, the short answer is no.
If you look at code snippet for equals
method in your favorite IDE then you'll see that it has line like if (getClass() != another.getClass()) return false;
It means that you check class of object inside equals
. You could do the same at areEqual
method but probably it's not needed - it should be implemented on another level
Upvotes: 1
Reputation: 43078
Just specify the type in the generic parameters...
public class Test {
public static void main(String[] args) {
System.out.println(
new Comparator<String>("hello", 1).areEqual()
);
}
...
}
If you do this with your current code, you will get a compiler error.
When you leave it unspecified, Java does not bother doing any type checking and simply uses the super type (Object
) as the type for both.
You will also find the same issue when you do something like:
System.out.println(Arrays.asList("hello", 1)); // Will compile
vs
System.out.println(Arrays.<String>asList("hello", 1)); // Will not compile
Upvotes: 2
Reputation: 7315
So, I think it is not possible by using generic. But you can restrict it by checking the Object type in the constructor like below code.
public Comparator(T left, T right) {
if(left.getClass()!=right.getClass()) {
throw new IllegalArgumentException("All values passed needs to be object of same class");
}
this.left = left;
this.right = right;
}
However, this will not give you compile time error but it will through Exception when a different type of object passed to the constructor.
Upvotes: 1
Reputation: 106400
Not really, no.
Because your generic type is unbound, there's only one common ancestor: Object
- as you correctly surmise.
The only thing you can realistically do in this scenario is ensure that equals
is correctly defined for objects you want to pass through this method. You would also want to handle cases in which you pass null
as an argument, too.
Upvotes: 3