如何使Java Generic方法静态?

时间:2010-12-10 13:05:47

标签: java generics

以下是如何使java泛型类将单个项附加到数组的片段。如何使appendToArray成为静态方法。将static添加到方法签名会导致编译错误。

public class ArrayUtils<E> {

        public E[] appendToArray(E[] array, E item) {
            E[] result = (E[])new Object[array.length+1];
            result[array.length] = item;
            return result;
        }
}

5 个答案:

答案 0 :(得分:243)

您唯一能做的就是将签名更改为

public static <E> E[] appendToArray(E[] array, E item)

重要细节:

返回值之前的通用表达式总是引入(声明)一个新的泛型类型变量。

此外,类型(ArrayUtils)和静态方法(appendToArray)之间的类型变量绝不会相互干扰。

那么,这意味着什么: 如果方法不是<E>,我的回答E会隐藏ArrayUtils<E> static。 AND <E>E的{​​{1}}无关。

为了更好地反映这一事实,更正确的答案是:

ArrayUtils<E>

答案 1 :(得分:69)

public static <E> E[] appendToArray(E[] array, E item) { ...

请注意<E>

静态泛型方法需要将自己的泛型声明(public static <E>)与类的泛型声明(public class ArrayUtils<E>)分开。

如果编译器在调用静态泛型方法时抱怨类型歧义(在您的情况下再次不太可能,但一般来说,以防万一),这里是如何使用特定类型显式调用静态泛型方法({ {1}}):

_class_.<_generictypeparams_>_methodname_

只有在编译器无法确定泛型类型时才会发生这种情况,例如,泛型类型与方法参数无关。

答案 2 :(得分:9)

您需要将type参数移动到方法级别,以指示您具有泛型方法而不是泛型类:

public class ArrayUtils {
    public static <T> E[] appendToArray(E[] array, E item) {
        E[] result = (E[])new Object[array.length+1];
        result[array.length] = item;
        return result;
    }
}

答案 3 :(得分:3)

我将以简单的方式进行解释。

在类级别定义的泛型与在(静态)方法级别定义的泛型完全分开。

class Greet<T> {

    public static <T> void sayHello(T obj) {
        System.out.println("Hello " + obj);
    }
}

当您在任何地方看到上述代码时,请注意,在类级别定义的T与static方法中定义的T没有任何关系。以下代码也完全有效,并且等同于上面的代码。

class Greet<T> {

    public static <E> void sayHello(E obj) {
        System.out.println("Hello " + obj);
    }
}

为什么静态方法需要将自己的泛型与类的泛型分开?

这是因为静态方法可以在没有偶数的情况下被调用 实例化类。因此,如果尚未实例化该类,则我们 尚不知道什么是T。这就是为什么使用静态方法的原因 需要有自己的泛型。

因此,无论何时调用静态方法,

Greet.sayHello("Bob");
Greet.sayHello(123);

JVM将其解释为以下内容。

Greet.<String>sayHello("Bob");
Greet.<Integer>sayHello(123);

两者都提供相同的输出。

Hello Bob
Hello 123

答案 4 :(得分:0)

来自 javadoc

通用方法

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

泛型方法的语法包括一个类型参数列表,在尖括号内,它出现在方法的返回类型之前。对于静态泛型方法,类型参数部分必须出现在方法的返回类型之前。

Util 类包含一个通用方法 compare,它比较两个 Pair 对象:

public class Util {
    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());
    }
}


public class Pair<K, V> {

private K key;
private V value;

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

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; }
}

调用这个方法的完整语法是:

Pair<Integer, String> p1 = new Pair<>(1, "apple");
Pair<Integer, String> p2 = new Pair<>(2, "pear");
boolean same = Util.<Integer, String>compare(p1, p2);

类型已明确提供,如粗体所示。通常,这可以省略,编译器会推断出所需的类型:

Pair<Integer, String> p1 = new Pair<>(1, "apple");
Pair<Integer, String> p2 = new Pair<>(2, "pear");
boolean same = Util.compare(p1, p2);

此功能称为类型推断,允许您将泛型方法作为普通方法调用,而无需在尖括号之间指定类型。

在理解了这个文档之后,你的问题答案是:

public static <I> I[] appendToArray(I[] array, I item)