通用类和静态通用方法

4

我正在编写一个通用类

public class SomeClass<T> {

    public static <T extends Comparable<? super T>> T min(Collection<? extends T> c) {
        T min = c.iterator().next();
        for (T element : c)
            if (element.compareTo(min) < 0)
                min = element;
        return min;
    }

}

public class Main {

    public static void main(String[] args) {
        SomeClass<Integer>.min(Arrays.asList(1, 2, 3)); // compile-time error
        SomeClass.min(Arrays.asList(1, 2, 3)); // ok
    }

}

在泛型类 SomeClass 和泛型方法 SomeMethod 中,类型参数 T 是相同的还是不同的?

为什么我们在字符串 SomeClass<Integer>.min(Arrays.asList(1,2,3)); 中会出现编译时错误?


编译时错误是什么? - newacct
@newacct 错误描述为“应该是';'而不是语句”。 - user2889159
5个回答

3
类声明
public class SomeClass<T> 

定义了一个通用的类,其中<T>指定了类型参数(也称为类型变量)。这引入了类型变量T,它可以在类的任何地方使用。

方法声明如下:

public static <T extends Comparable<? super T>> T min(Collection<? extends T> c) {
...
}

定义了一个通用方法。通用方法是介绍其自己的类型参数的方法。这类似于声明通用类型,但类型参数的作用域仅限于声明它的方法。

现在,如果您想调用通用方法min,则需要调用:

SomeClass.<Integer>min(Arrays.asList(1,2,3));

我已经意识到这一点了。那么我的第二个问题呢?为什么我们在字符串SomeClass<Integer>.min(Arrays.asList(1,2,3))中出现了编译时错误?我认为这是正确的,因为我正在尝试调用通用类的方法。 - user2889159
是的,我想了解为什么编译器不允许写 SomeClass<Integer>.min(Arrays.asList(1,2,3)); - user2889159
@Dmitrii,这是因为你把类型参数放在了“.”之前。这是错误的,因为你想要为方法提供参数而不是类。当指定类型时,在类名后面提供类型参数,例如在声明变量时。 - Viktor Seifert

0

T代表类型,你正在访问与T无关的静态方法。

要么就像这样使用

SomeClass<Integer> a = new SomeClass<Integer>();
a.min(Arrays.asList(1, 2, 3));

或者

SomeClass.min(Arrays.asList(1, 2, 3));

0

这是不同的,你永远不应该编写这样的代码,特别是因为可能会产生混淆。请始终在类和这些类中的方法上使用不同类型的变量。


方法 min 中的类型参数 T 只在该方法的主体中可见吗? - user2889159
第二个问题呢:为什么 SomeClass<Integer>.min(Arrays.asList(1, 2, 3)); 不合法?我只是想调用静态方法 min。 - user2889159
括号应该放在点的另一侧:SomeClass.<Integer>min(Arrays.asList(1, 2, 3))。当调用类的静态方法时,不应提供泛型参数。 - Louis Wasserman

0

这两个T是不同的:第一个是类的参数(未使用),第二个是特定于方法的。由于该方法是静态的,类参数不会影响它。

当您编写SomeClass<Integer>.min(Arrays.asList(1, 2, 3));时,会出现错误,因为向SomeClass添加参数没有意义,因为该类的对象未实例化。 SomeClass仅用于告诉编译器您要从该类调用静态方法。您可以使用SomeClass.<Integer>min(Arrays.asList(1, 2, 3));方法添加参数,但您不必这样做,因为编译器可以在此处推断类型。


0

所以编译消息告诉你的是它是一个语法错误。为什么它是无效的语法很容易理解。你正在尝试在类型上调用一个方法。这意味着你正在调用一个静态方法。静态方法不在通用类型参数的范围内。因此,在左侧放置通用类型参数是不允许的。

如果你想知道技术原因,那就是因为你的方法调用表达式不是语法允许的形式之一。最接近你的形式是TypeName . NonWildTypeArguments Identifier ( ArgumentListopt )。但是TypeName(在这里定义)必须是标识符或包限定标识符。它不允许使用括号。


感谢您详尽的回答! - user2889159

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接