通用方法类型参数声明

时间:2014-06-14 19:24:55

标签: java generics

因此,好的' Dietel 表示,“所有通用方法声明都有类型参数部分尖括号(<和>)在方法返回类型,“(Deitel,2012,italicized emphasis mine)之前。给出的例子如下:

public static < T > void printArray (T[] inputArray)
{
    for (T element : inputArray)
    (
        System.out.printlf("%s", element);
}

这对我有意义。我明白了。但是,这是我的问题,书中没有明确说明。

我有一个非常简单的课程来演示:

public class Pair<F, S> 
{
    private F first;
    private S second;
}

现在,根据Deitel的说法,“ ALL ”泛型方法声明必须包含一个类型参数部分。所以,当然,我想在我的类示例中添加get()set()方法。所以,我这样做:

public class Pair<F, S>
{
    private F first;
    private S second;

    // Here, I'll do one instead of both for the sake of shortening the code
    public < F > F getF()
    {
        return F;
    }

    // And the Accessor:
    public < F > void setF(F first)
    {
        this.first = first;
    }
}

所以,这是交易。在我尝试编译(Intellisense的Java版本)之前,Eclipse IDE给出了一个警告:“类型参数F隐藏类型F”。现在,我并不特别信任 Dietel for Java - 并且我越来越了解他们并不是特别可靠(因为他们经常遗漏重要的区别)。所以,我去了Oracle Documentation我正在做的事情 - GUESS WHAT - 他们没有提到任何类型,除非你在谈论'upperbounded'类型参数。

这是问题(它有三个):

  1. 这里的区别是“静态”限定符,即我写的方法出现在一个类中吗?
  2. Dietel 做了什么,尤其是在他们的建议实施时,会产生警告?
  3. 通过更改类类型参数,我摆脱了警告。那么,从概念上讲,方法参数类型“隐藏”类参数类型的位置是什么?

1 个答案:

答案 0 :(得分:4)

JLS专门指定一个声明类型参数的泛型方法。 (JLS)所以这里的混淆是Deital已经说过&#34;所有泛型方法都有一个类型参数部分&#34; 但可能没有特别指出这是他们的定义。更明显的是,&#34;泛型方法是具有类型参数部分&#34; 的方法。

如注释中所述,当您具有类声明的类型参数时,您无需在该方法中重新声明它们。如Eclipse所述,这样做实际上声明了新类型参数,这些参数隐藏了类声明的参数。

当在课堂上宣布它们时,你可以直接使用它们:

class Pair<F, S> {
    F getF() { ... }
    S getS() { ... }
    void setF(F f) { ... }
    void setS(S s) { ... }
}

通用方法的目的是参数化地使用它。给出的示例不是特别适合理解,因为泛型类型实际上未使用:调用Object的printf重载。它可以在没有泛型的情况下重写,而不会改变其功能:

public static void printArray(Object[] arr) {
    for(Object o : arr) {
        System.out.printf("%s", o);
    }
}

理解泛型方法使用的最简单的例子是Objects#requireNonNull的实现,如下所示:

public static <T> T requireNonNull(T obj) {
    if(obj == null)
        throw new NullPointerException();
    return obj;
}

它接受任何对象并方便地将其作为T

返回
// T is inferred
String hello = Objects.requireNonNull("hello world");
// T is provided as a witness (rarely necessary)
Integer five = Objects.<Integer>requireNonNull(5);

这是最简单的通用方法。