下面是一个关于如何创建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;
        }
}

你唯一能做的就是把你的签名改成

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

重要的细节:

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

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

那么,这意味着什么呢? 在我的回答中,如果方法不是静态的,<E>将从ArrayUtils<E>中隐藏E。AND <E>与ArrayUtils<E>中的E无关。

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

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

你需要将类型参数移动到方法级别,以表明你有一个泛型方法而不是泛型类:

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

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

注意<E>。

静态泛型方法需要独立于类的泛型声明(公共类ArrayUtils<E>)的泛型声明(公共类Static <E>)。

如果编译器在调用静态泛型方法时抱怨类型模糊(在您的情况下也不太可能,但一般来说,只是以防万一),下面是如何使用特定类型显式调用静态泛型方法(_class_.<_generictypeparams_>_methodname_):

String[] newStrings = ArrayUtils.<String>appendToArray(strings, "another string");

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


我用简单的方式解释一下。

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

class Greet<T> {

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

当您在任何地方看到上面的代码时,请注意在类级别上定义的T与在静态方法中定义的T没有任何关系。下面的代码也完全有效,与上面的代码等价。

class Greet<T> {

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

为什么静态方法需要有自己的泛型与类的那些分离?

这是因为,静态方法可以被调用 实例化类。所以如果Class还没有实例化,我们 还不知道t是什么,这就是为什么采用静态方法的原因吗 需要有自己的泛型。

当你调用静态方法时,

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

JVM将其解释如下。

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

两者都给出相同的输出。

Hello Bob
Hello 123

从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)

如何使appendToArray成为静态方法?

要使它成为静态的,你需要:

添加静态修饰符 将泛型类型E添加到方法签名中

特别是对于你的例子,这意味着改变方法签名:

public E[] appendToArray(E[] array, E item) {

:

// same as above, but with "static <E>" before return type E[]
public static <E> E[] appendToArray(E[] array, E item) {

很容易忽略的关键部分:泛型类型应该添加到签名中,出现在返回类型之前。以下节选自 Java泛型方法教程:

Generic methods are methods that introduce their own type parameters. This is similar to declaring a generic type, but the type parameter's scope is limited to the method where it is declared. Static and non-static generic methods are allowed, as well as generic class constructors. The syntax for a generic method includes a list of type parameters, inside angle brackets, which appears before the method's return type. For static generic methods, the type parameter section must appear before the method's return type.