如何使Java Generic方法静态?

Chr*_*son 156 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;
        }
}
Run Code Online (Sandbox Code Playgroud)

sch*_*eld 262

你唯一能做的就是改变你的签名

public static <E> E[] appendToArray(E[] array, E item)
Run Code Online (Sandbox Code Playgroud)

重要细节:

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

此外,types(ArrayUtils)和static methods(appendToArray)之间的类型变量永远不会相互干扰.

那么,这意味着什么:在我的回答<E>E,ArrayUtils<E>如果方法不存在,则会隐藏from static.和<E>E来自无关ArrayUtils<E>.

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

public static <I> I[] appendToArray(I[] array, I item)
Run Code Online (Sandbox Code Playgroud)

  • 还要注意,类级变量`E`和静态方法类型变量`E`之间绝对没有关系.我认为在泛型类中声明泛型或其他方法时,使用不同的变量名更好. (27认同)

Ber*_*t F 76

public static <E> E[] appendToArray(E[] array, E item) { ...
Run Code Online (Sandbox Code Playgroud)

请注意<E>.

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

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

String[] newStrings = ArrayUtils.<String>appendToArray(strings, "another string");
Run Code Online (Sandbox Code Playgroud)

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


axt*_*avt 10

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

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;
    }
}
Run Code Online (Sandbox Code Playgroud)


Vis*_*vek 7

我会用简单的方式解释它。

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

class Greet<T> {

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

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

class Greet<T> {

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

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

这是因为,甚至可以在不实例化 Class 的情况下调用静态方法。所以如果Class还没有被实例化,我们还不知道什么是T。这就是静态方法需要有自己的泛型的原因。

因此,每当您调用静态方法时,

Greet.sayHello("Bob");
Greet.sayHello(123);
Run Code Online (Sandbox Code Playgroud)

JVM 将其解释如下。

Greet.<String>sayHello("Bob");
Greet.<Integer>sayHello(123);
Run Code Online (Sandbox Code Playgroud)

两者都给出相同的输出。

Hello Bob
Hello 123
Run Code Online (Sandbox Code Playgroud)


kaa*_*aan 5

如何使appendToArray成为静态方法?

要使其静态,您需要:

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

具体来说,对于您的示例,这意味着更改方法签名:

public E[] appendToArray(E[] array, E item) {
Run Code Online (Sandbox Code Playgroud)

对此:

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

很容易错过的关键部分:泛型类型应该添加到签名中,出现在返回类型之前。下面摘录自《Java泛型方法教程》:

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

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