我收到以下错误"无法对非静态类型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();
}
现在我知道执行以下操作将解决错误,但我不明白&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));
}
}
答案 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);
}
}