[英]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.