有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

如何使Java泛型方法成为静态的?

下面是一个关于如何使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) 个答案

  1. # 1 楼答案

    来自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)
    
  2. # 2 楼答案

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

    请注意<E>

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

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

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

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

  3. # 3 楼答案

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

    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;
        }
    }
    
  4. # 4 楼答案

    我会用简单的方式解释

    在类级别定义的泛型与在(静态)方法级别定义的泛型完全不同

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

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

    This is because, the static method can be called without even instantiating the Class. So if the Class is not yet instantiated, we do not yet know what is T. This is the reason why the static methods needs to have its own generics.

    所以,无论何时调用静态方法

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

    JVM将其解释为:

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

    两者的输出相同

    Hello Bob
    Hello 123
    
  5. # 5 楼答案

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

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

    重要细节:

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

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

    那么,这意味着什么: 在我的回答中<E>会对ArrayUtils<E>隐藏E,如果方法不是static。而且<E>与来自ArrayUtils<E>E无关

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

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