NOTE: This question is not Enum-related, so it\'s not duplicate. Enum\'s are forced to compare only-with-itself because compiler generation of type paramete
Concerning the statement
every time I've tried to remove additional - no new errors/warnings came up.
This should not be the case. It should print a warning, because you are using the raw type Some, and the result of this is missing type safety, as demonstrated in the answer by newacct.
The Dog/Cat example is a bit contrived, and somewhat flawed. You suggested declaring a class
public class Dog extends Animal { } // Note "Cat" !!!
But here, the type parameter basically means: "This parameter (Cat) is the type that objects of this class (Dog) can be compared with". You are thus explicitly stating that a Dog should be comparable to Cat. Even with sophisticated languages and smart compilers, after all, it's in the responsibility of the programmers to write code that makes sense.
Indeed, there are not many cases where these self-referential generic types are necessary. One of these examples is sketched in this FAQ entry: It declares a structure of nodes (that is, a tree) where the type parameter can be used to decouple the definition of the tree structure from the actual type of the nodes:
public class RecurringTest {
public static void main(String[] args) {
SpecialNode sa = new SpecialNode(null);
SpecialNode sb = new SpecialNode(sa);
SpecialNode s = sa.getChildren().get(0);
}
}
abstract class Node> {
private final List children = new ArrayList();
private final N parent;
protected Node(N parent) {
this.parent = parent;
if (parent != null) {
this.parent.getChildren().add(getThis());
}
}
abstract N getThis();
public N getParent() {
return parent;
}
public List getChildren() {
return children;
}
}
class SpecialNode extends Node {
public SpecialNode(SpecialNode parent) {
super(parent);
}
SpecialNode getThis() {
return this;
}
}
But from my personal experience, I can say that when you think you need to create such a type, you should thoroughly think about the benefits and drawbacks. The latter mainly refers to reduced readability. When you have the choice between methods like
Node extends Node extends N, ? extends T>, T> doSomething(
Node super Node extends N>, ? extends T> p,
Node extends Node super N>, ? super T> c) { ... }
that are type safe, or methods like
Node doSomething(Node parent, Node child) { ... }
that are not type safe (because of raw types, or simply because the types have not been genericified), then I'd prefer the latter. Code is read by humans.