java - 为什么我们有时需要在静态方法声明中使用<e>?

时间:2017-11-11 17:49:58

标签: java eclipse

我收到以下错误&#34;无法对非静态类型E&#34;进行静态引用对于以下方法:

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

现在我知道执行以下操作将解决错误,但我不明白&lt; 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));
 }
}

3 个答案:

答案 0 :(得分:3)

泛型参数E仅适用于特定实例,因此编译错误。

方法签名中的<E>用于表示类型参数,如果没有这个,编译器就不会知道E[] a是类型参数还是具体类型声明。

答案 1 :(得分:3)

如果你没有将<E>放在方法声明中,编译器就无法理解你是想制作一个泛型方法,还是想要引用一个实际的方法名为E的类,只是忘了导入它。 如果没有type参数,编译器只能假设第二个选项并抱怨,因为它无法在任何地方找到E类。

答案 2 :(得分:0)

静态方法需要

<E> ,而非静态方法则<E>是可选的。

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

请参阅Java Language Specification §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);

    }

}
相关问题