我上了这个课:

public abstract class SlightExpression<T> extends Expression<T> {
    public BooleanExpression eq(Expression<? super T> right) {}
}

去看下一个句子:
    SlightExpression<?> left;
    SlightExpression<?> right;
    //...

    left.eq(right);

Java告诉我:
The method eq(capture#19-of ?) in the type SlightExpression<capture#19-of ?>
is not applicable for the arguments (SlightExpression<capture#20-of ?>)

然而,
public abstract class StringExpression extends SlightExpression<String> {}

然后,Java对此一无所知。
StringExpression s, f;
s.eq(f);

我不了解这种行为。

最佳答案

当左右声明为

SlightExpression<?> left;
SlightExpression<?> right;

您可以为其分配具有不同参数类型的SlightExpression。例如 :
left = new SlightExpression<Integer>();
right = new SlightExpression<String>();

现在,您无法将SlightExpression<String>传递给eq实例的SlightExpression<Integer>方法。

另一方面,在您的第二个片段中,两个实例都是SlightExpression<String>的子类,因此将一个实例作为参数传递给另一个实例的eq方法没有问题。

为了更好地理解该概念,可以将其应用于更知名的类。例如 :
List<?> l1 = new ArrayList <String> ();
List<?> l2 = new ArrayList <Integer> ();
l1.addAll (l2); // this doesn't pass compilation, since you can't add Integer elements to
                // a List<String>

List<?> l1 = new ArrayList <String> ();
List<?> l2 = new ArrayList <String> ();
l1.addAll (l2); // this doesn't pass compilation too, since the compiler doesn't know that
                // l1 and l2 will refer to Lists of the same element type when addAll is
                // invoked

另一方面,此代码段将通过编译,因为编译器会看到两个List具有相同的元素类型:
List<String> l1 = new ArrayList <String> ();
List<String> l2 = new ArrayList <String> ();
l1.addAll (l2);

10-04 13:40