在Java中,我想有如下的东西:
class Clazz<T> {
static void doIt(T object) {
// ...
}
}
但是我知道
Cannot make a static reference to the non-static type T
除了基本用途之外,我不了解泛型,因此无法理解它。我在网上找不到很多关于这个主题的信息,这也无济于事。
有人能澄清一下这种使用是否可能,以类似的方式?还有,为什么我最初的尝试失败了?
在Java中,我想有如下的东西:
class Clazz<T> {
static void doIt(T object) {
// ...
}
}
但是我知道
Cannot make a static reference to the non-static type T
除了基本用途之外,我不了解泛型,因此无法理解它。我在网上找不到很多关于这个主题的信息,这也无济于事。
有人能澄清一下这种使用是否可能,以类似的方式?还有,为什么我最初的尝试失败了?
当前回答
T不在静态方法的范围内,因此不能在静态方法中使用T。您需要为静态方法定义一个不同的类型参数。我会这样写:
class Clazz<T> {
static <U> void doIt(U object) {
// ...
}
}
例如:
public class Tuple<T> {
private T[] elements;
public static <E> Tuple<E> of(E ...args){
if (args.length == 0)
return new Tuple<E>();
return new Tuple<E>(args);
}
//other methods
}
其他回答
Also to put it in simple terms, it happens because of the "Erasure" property of the generics.Which means that although we define ArrayList<Integer> and ArrayList<String> , at the compile time it stays as two different concrete types but at the runtime the JVM erases generic types and creates only one ArrayList class instead of two classes. So when we define a static type method or anything for a generic, it is shared by all instances of that generic, in my example it is shared by both ArrayList<Integer> and ArrayList<String> .That's why you get the error.A Generic Type Parameter of a Class Is Not Allowed in a Static Context!
错误中正确地提到:您不能对非静态类型T进行静态引用。原因是类型参数T可以被任何类型参数替换,例如Clazz<String>或Clazz<integer>等。但是静态字段/方法由类的所有非静态对象共享。
以下内容摘自纪录片:
A class's static field is a class-level variable shared by all non-static objects of the class. Hence, static fields of type parameters are not allowed. Consider the following class: public class MobileDevice<T> { private static T os; // ... } If static fields of type parameters were allowed, then the following code would be confused: MobileDevice<Smartphone> phone = new MobileDevice<>(); MobileDevice<Pager> pager = new MobileDevice<>(); MobileDevice<TabletPC> pc = new MobileDevice<>(); Because the static field os is shared by phone, pager, and pc, what is the actual type of os? It cannot be Smartphone, Pager, and TabletPC at the same time. You cannot, therefore, create static fields of type parameters.
正如chris在他的回答中正确指出的那样,在这种情况下,你需要与方法一起使用类型参数,而不是与类一起使用。你可以这样写:
static <E> void doIt(E object)
直到实例化一个类型,Java才知道T是什么。
也许你可以通过调用Clazz<T>.doit(一些东西)来执行静态方法,但听起来你不能。
另一种处理方法是将类型参数放在方法本身中:
static <U> void doIt(U object)
这并不能让你对U有正确的限制,但总比没有好....
T不在静态方法的范围内,因此不能在静态方法中使用T。您需要为静态方法定义一个不同的类型参数。我会这样写:
class Clazz<T> {
static <U> void doIt(U object) {
// ...
}
}
例如:
public class Tuple<T> {
private T[] elements;
public static <E> Tuple<E> of(E ...args){
if (args.length == 0)
return new Tuple<E>();
return new Tuple<E>(args);
}
//other methods
}
@BD at Rivenhill:由于这个老问题在去年重新引起了关注,让我们继续讨论一下,只是为了讨论。 doIt方法的主体根本不做任何t特定的事情。下面就是:
public class Clazz<T> {
static <T> void doIt(T object) {
System.out.println("shake that booty '" + object.getClass().toString()
+ "' !!!");
}
// ...
}
所以你可以完全放弃所有类型变量,只写代码
public class Clazz {
static void doIt(Object object) {
System.out.println("shake that booty '" + object.getClass().toString()
+ "' !!!");
}
// ...
}
好的。让我们回到最开始的问题。类声明中的第一个类型变量是多余的。只需要关于方法的第二个步骤。我们又来了,但这还不是最终答案:
public class Clazz {
static <T extends Saying> void doIt(T object) {
System.out.println("shake that booty "+ object.say());
}
public static void main(String args[]) {
Clazz.doIt(new KC());
Clazz.doIt(new SunshineBand());
}
}
// Output:
// KC
// Sunshine
interface Saying {
public String say();
}
class KC implements Saying {
public String say() {
return "KC";
}
}
class SunshineBand implements Saying {
public String say() {
return "Sunshine";
}
}
然而,这太小题大做了,因为下面的版本以同样的方式工作。它所需要的只是方法参数上的接口类型。任何地方都看不到类型变量。这真的是最初的问题吗?
public class Clazz {
static void doIt(Saying object) {
System.out.println("shake that booty "+ object.say());
}
public static void main(String args[]) {
Clazz.doIt(new KC());
Clazz.doIt(new SunshineBand());
}
}
interface Saying {
public String say();
}
class KC implements Saying {
public String say() {
return "KC";
}
}
class SunshineBand implements Saying {
public String say() {
return "Sunshine";
}
}