繁体   English   中英

Java-为什么有时需要 <E> 在静态方法声明中?

[英]java - why do we sometimes need <E> in static method declarations?

对于以下方法,我收到以下错误“无法对非静态类型E进行静态引用”:

public static void reverse(E[] a) {
       Stack<E> buffer = new Lab8<>(a.length); 

       for (int i=0; i < a.length; i++)
          buffer.push(a[i]);

       for (int i=0; i < a.length; i++)
          a[i] = buffer.pop();
}

现在我知道执行以下操作可以修复该错误,但是我不明白<E>的含义(在这种情况下为什么要使用它),并且在这样的方法中定义它没有意义吗? 我确实在声明泛型类和实例时获得了如何使用它,但这是我第一次看到它以这种方式使用...

public static <E> void reverse(E[] a) {
       Stack<E> buffer = new Lab8<>(a.length); 

       for (int i=0; i < a.length; i++)
          buffer.push(a[i]);

       for (int i=0; i < a.length; i++)
          a[i] = buffer.pop();
}

这是完整的代码供参考:

 package labs;

import java.util.Arrays;

public class Lab8<E> implements Stack<E> {

 public static final int CAPACITY=1000;
 private E[] data;
 private int t = -1;
 public Lab8() { this(CAPACITY); }
 public Lab8(int capacity) {
// default array capacity
// generic array used for storage
// index of the top element in stack
// constructs stack with default capacity // constructs stack with given capacity // safe cast; compiler may give warning
   data = (E[ ]) new Object[capacity];

 }
 public int size() { return (t + 1); }
 public boolean isEmpty() { return (t == -1); }
 public void push(E e) throws IllegalStateException {
      if (size() == data.length) throw new IllegalStateException("Stack is full");
      data[++t] = e;
 }

 public E top() {
     if (isEmpty()) return null;
        return data[t];
 }

 public E pop() {
     if (isEmpty( )) return null;
     E answer = data[t];
     data[t] = null;
     t--;
     return answer;
 }

 public static void reverse(E[] a) {
        Stack<E> buffer = new Lab8<>(a.length); 

        for (int i=0; i < a.length; i++)
          buffer.push(a[i]);

        for (int i=0; i < a.length; i++)
          a[i] = buffer.pop();
 }

 public static void main(String[] args) {
            Integer[] a = {4, 8, 15, 16, 23, 42}; // autoboxing allows this 
            String[] s = {"maryam", "ricardo", "Mostafa", "Ahmend", "Hitler"};
            System.out.println("a = " + Arrays.toString(a)); 
            System.out.println("s = " + Arrays.toString(s)); 
            System.out.println("Reversing...");
            reverse(a);
            reverse(s);
            System.out.println("a = " + Arrays.toString(a)); System.out.println("s = " + Arrays.toString(s));
 }
}

通用参数E仅可用于特定实例,因此编译错误。

方法签名中的<E>用于表示类型参数,否则,编译器将不知道E[] a是类型参数还是具体的类型声明。

如果您未在方法声明中添加<E> ,则编译器将无法理解您是否要创建泛型方法,或者您是否试图引用名为E的实际类而忘记了导入它。 在没有类型参数的情况下,编译器只能采用第二个选项并抱怨,因为它无法在任何地方找到E类。

<E>对于静态方法是必需的 ,而<E>对于非静态方法是可选的。

在类或接口声明中,泛型类型参数是非静态的:类型参数指变量或字段的特定类型声明(例如List<String> l;List<Integer> l )。 相反,可以在没有变量/字段声明的情况下使用静态方法,因此Java语言规范规定了类/接口类型参数范围不包括静态方法 换句话说,在通用静态方法中,必须显式声明类型参数,例如, static <E> void foo (E e) {}

参见Java语言规范§8.1.2。

8.1.2。 通用类和类型参数

...
在以下任何情况下引用通用类C的类型参数都是编译时错误:
-C的静态成员的声明(第8.3.1.1节,第8.4.3.2节,第8.5.1节)。
-...

8.4.3.2。 static方法

例子:

public class C<E> {

    // non-static   
    void foo1(E e) {}
    <F> void foo2(F f) {}
    <E> void foo3(E e) {}
//   ^ WARNING: The type parameter E is hiding the type E

    // static
    static <F> void bar1 (F f) {}
    static <E> void bar2 (E e) {}
//  static void bar3 (E e) {}
//                    ^ ERROR: Cannot make a static reference to the non-static type E

    public static void main(String[] args) {

        // non-static
        C<String> c = new C<>();
        c.foo1("42");
//      c.foo1(42);
//        ^^^^ ERROR: The method foo1(String) in the type C<String> is not applicable for the arguments (int)
        c.foo2("42");
        c.foo2(42);
        c.foo3("42");
        c.foo3(42);

        // static
        C.bar1("42");
        C.bar1(42);
        C.bar2("42");
        C.bar2(42);

    }

}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM