【问题标题】:Why we have to mention generic type parameter before the method return type?为什么我们必须在方法返回类型之前提到泛型类型参数?
【发布时间】:2014-10-02 23:39:06
【问题描述】:

在这个page,它有下面的代码示例来介绍泛型方法?

public static <K, V> boolean compare(Pair<K, V> p1, Pair<K, V> p2) {
    return p1.getKey().equals(p2.getKey()) &&
           p1.getValue().equals(p2.getValue());
}
  1. 我有一个问题,为什么我们需要在此处的“布尔”之前提及泛型?这个方法只是返回布尔类型。当我删除&lt;K, V&gt;编译器抛出错误说cannot make a static reference to the non-static type K

    public void setValue(V value) {
        this.value = value;
    }
    
  2. 在同一个链接上,我们有上面的方法,那么为什么我们这里没有提到的泛型类型参数&lt;V&gt;

编辑:在此处发布完整的代码,以便更好地理解我的问题:

Util.Java

public class Util {
    // Generic static method
    public static <K, V> boolean compare(Pair<K, V> p1, Pair<K, V> p2) {
        return p1.getKey().equals(p2.getKey()) &&
               p1.getValue().equals(p2.getValue());
    }
}

对.Java

public class Pair<K, V> {

    private K key;
    private V value;

    // Generic constructor
    public Pair(K key, V value) {
        this.key = key;
        this.value = value;
    }

    // Generic methods
    public void setKey(K key) { this.key = key; }
    public void setValue(V value) { this.value = value; }
    public K getKey()   { return key; }
    public V getValue() { return value; }
}

【问题讨论】:

  • 它是静态的。见这里:stackoverflow.com/questions/4409100/…
  • @user2588666:这个问题的反面在这里:Static method in a generic class?
  • 我无法重现您的错误消息。如果我从方法中删除&lt;K,V&gt;,我会得到error: cannot find symbol public static boolean compare(Pair&lt;**K**, V&gt; p1, Pair&lt;K, V&gt; p2) { symbol: class K, location: class Util。考虑发布MCVE,这将使我们重现您的实际问题。总之简而言之,如果你想在方法中使用一些泛型类型,但你没有通过class YourClass&lt;K,V&gt; 在类本身中声明它,你可以在方法中进行。你需要在它的返回类型之前声明它,因为返回类型也可以使用你声明的泛型类型。
  • @Pshemo 我不希望这个问题太长太无聊所以没有在这里发布完整的代码而是提到了链接。
  • 提问准确比不枯燥更重要。没有人希望您粘贴数百万行代码,只需创建一些简单的示例,让我们重现您的错误/问题。

标签: java generics


【解决方案1】:

如果类没有声明泛型类型,该方法将不知道您请求的类型。这通常是静态的情况,因为这些方法不是类实例的一部分。

类上的泛型参数的范围仅属于实例方法和字段。静态方法必须声明它们自己的类型参数,仅适用于其范围。

来自The Java™ Tutorials: Generic Methods

泛型方法是引入自己的类型参数的方法。这类似于声明泛型类型,但类型参数的范围仅限于声明它的方法。允许使用静态和非静态泛型方法,以及泛型类构造函数。

您的示例似乎来自此页面,您在该页面上拥有所需的所有信息。如果您需要探索有关泛型的更多信息,请继续您的教程。 :-)

对于第二个问题,setValue() 方法是Pair 类的成员,该类提供KV 类型参数:

public class Pair<K, V> {
    private V value;
    public void setValue(V value) { this.value = value; }
    public V getValue() { return value; }
}

V 在实例范围内声明。

【讨论】:

    【解决方案2】:

    为什么我们必须在方法返回类型之前提到泛型类型参数?

    因为返回类型可能使用其中一种泛型类型,并且因为该方法是静态的,所以它不会“看到”包含类的泛型类型。

    在同一个链接上,我们有上面的方法,那么为什么我们这里没有提到的泛型类型参数呢?

    因为它必须包含在泛型类中。

    【讨论】:

      【解决方案3】:

      您的问题与 method 泛型参数有关,这些参数在返回类型之前 声明 - 这是必要的,因为返回类型可能并且通常是基于泛型。

      【讨论】:

        【解决方案4】:

        在 Java 中有两种声明和使用泛型类型参数的方法。

        1. compare 方法一样,您可以在方法本身上声明类型参数。这些在返回类型之前声明,并且可以在整个方法中使用。

        2. setValue 方法一样,未在方法上声明的类型参数必须在其他地方声明——在类声明本身上。在setValue 方法的类中,您会看到如下内容:

        对:

        public class Pair<K, V> {
        

        这是声明类范围泛型类型参数的地方。它们在整个课程的范围内,包括 setValue 方法。

        例外情况是此类类级别的类型参数不在static 方法的范围内,因此必须在static 方法上声明它们才能在范围内。请注意,它们将是与在类上声明的类型参数不同的类型参数。

        【讨论】:

        • @Pshemo 哎呀。它是缩进的,但这计入降价列表。固定。
        【解决方案5】:

        您必须提及泛型类型,否则KV 将分别被解释为具体的classinterface。程序无法编译,因为找不到KV。在方法之前添加泛型告诉编译器这些类是泛型。如果在调用时无法通过输入类型推断它们,则需要像这样提及它:

        Foo.<String>createFoo();
        

        您(不)返回从泛型派生的对象这一事实并不是这些要求的全部原因。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-02-14
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-05-01
          • 2016-12-24
          相关资源
          最近更新 更多