泛型类中的静态方法?

And*_*lla 190 java generics static-methods

在Java中,我想有一些东西:

class Clazz<T> {
  static void doIt(T object) {
    // shake that booty
  }
}
Run Code Online (Sandbox Code Playgroud)

但我明白了

Cannot make a static reference to the non-static type T

我不了解基本用途之外的泛型,因此无法理解这一点.我无法在互联网上找到有关该主题的更多信息,这没有任何帮助.

有人可以通过类似的方式澄清这种使用是否可行?另外,为什么我的原始尝试不成功?

new*_*cct 259

您不能在静态方法或静态字段中使用类的泛型类型参数.类的类型参数仅在实例方法和实例字段的范围内.对于静态字段和静态方法,它们在类的所有实例之间共享,甚至是不同类型参数的实例,因此显然它们不能依赖于特定的类型参数.

看起来您的问题似乎不需要使用类的类型参数.如果您更详细地描述您想要做的事情,也许我们可以帮助您找到更好的方法.

  • "对于静态字段和静态方法,它们在类的所有实例之间共享,甚至是不同类型参数的实例......"哎哟!再次通过类型擦除来破坏坚果! (32认同)
  • Upvoted,这个答案实际上解释了海报的问题,而不仅仅是提供一个解决方法. (9认同)
  • @Andre:你的直觉并非没有根据; C#确实以这种方式处理泛型. (7认同)
  • 我认为他解释了他想做的事情.很明显他正试图撼动数据战利品!嘿 (3认同)
  • 我认为每个类型参数都会有一个完全不同的类,因此 Clazz&lt;Integer&gt;.doIt() 不会与 Clazz&lt;Long&gt;.doIt() 相同。我想我错了。确实需要更深入地阅读有关泛型的内容。 (2认同)
  • 如果您将了解编译后泛型类/方法的外观,您将看到删除了泛型属性.编译后的List <Integer>看起来像"List".因此编译后List <Integer>和List <Long>之间没有区别 - 两者都成为List. (2认同)

Jas*_*n S 137

T在实例化类型之前,Java不知道是什么.

也许你可以通过调用来执行静态方法,Clazz<T>.doit(something)但听起来你不能.

处理事物的另一种方法是将type参数放在方法本身中:

static <U> void doIt(U object)
Run Code Online (Sandbox Code Playgroud)

哪个不能让你对U有正确的限制,但它总比没有好....

  • 使用Clazz.<Object> doIt(object).我认为这是奇怪的语法,与C++的Clazz <int> :: doIt(1)相比 (8认同)
  • 我试过 Clazz&lt;Object&gt;.doIt(object) 并得到一个编译时错误!“令牌上的语法错误,错位的构造”。Clazz.doIt(object) 工作正常,甚至没有警告。 (2认同)

小智 45

我遇到了同样的问题.我通过Collections.sort在java框架中下载源代码找到了我的答案.我使用的答案是将<T>泛型放在方法中,而不是放在类定义中.

所以这有效:

public class QuickSortArray  {
    public static <T extends Comparable> void quickSort(T[] array, int bottom, int top){
//do it
}

}
Run Code Online (Sandbox Code Playgroud)

当然,在阅读了上面的答案之后,我意识到如果不使用泛型类,这将是一个可接受的替代方案:

public static void quickSort(Comparable[] array, int bottom, int top){
//do it
}
Run Code Online (Sandbox Code Playgroud)

  • 虽然接受的答案在技术上是正确的:这实际上是我在谷歌引导我提出这个问题时所寻求的. (8认同)
  • @Chris既然你正在使用泛型,你也可以一直使用它们 - 即不使用像`Comparable`这样的原始类型.试试`<T extends Comparable <?超级T >>`而不是. (3认同)

BD *_*ill 15

在声明方法时,可以通过使用泛型方法的语法来执行您想要的操作doIt()(注意在方法签名<T>之间static和之间添加):voiddoIt()

class Clazz<T> {
  static <T> void doIt(T object) {
    // shake that booty
  }
}
Run Code Online (Sandbox Code Playgroud)

我让Eclipse编辑器在没有Cannot make a static reference to the non-static type T错误的情况下接受上面的代码,然后将其扩展到以下工作程序(完全具有适合年龄的文化参考):

public class Clazz<T> {
  static <T> void doIt(T object) {
    System.out.println("shake that booty '" + object.getClass().toString()
                       + "' !!!");
  }

  private static class KC {
  }

  private static class SunshineBand {
  }

  public static void main(String args[]) {
    KC kc = new KC();
    SunshineBand sunshineBand = new SunshineBand();
    Clazz.doIt(kc);
    Clazz.doIt(sunshineBand);
  }
}
Run Code Online (Sandbox Code Playgroud)

我在运行时将这些行打印到控制台:

摇动那个战利品'com.eclipseoptions.datamanager.Clazz $ KC'!!!
摇动那个战利品'class com.eclipseoptions.datamanager.Clazz $ SunshineBand'!!!


Ore*_*ron 11

我认为还没有提到这种语法(如果你想要一个没有参数的方法):

class Clazz {
  static <T> T doIt() {
    // shake that booty
  }
}
Run Code Online (Sandbox Code Playgroud)

电话:

String str = Clazz.<String>doIt();
Run Code Online (Sandbox Code Playgroud)

希望这能有所帮助.


i_a*_*ero 6

它是在错误正确提到的:你不能让一个静态引用非静态类型T的原因是类型参数T可以通过任何类型参数例如更换Clazz<String>Clazz<integer>等,但静态字段/方法的所有非共享 - 类的静态对象.

以下摘录摘自doc:

类的静态字段是类的所有非静态对象共享的类级变量.因此,不允许使用类型参数的静态字段.考虑以下课程:

public class MobileDevice<T> {
    private static T os;

    // ...
}
Run Code Online (Sandbox Code Playgroud)

如果允许类型参数的静态字段,则以下代码将混淆:

MobileDevice<Smartphone> phone = new MobileDevice<>();
MobileDevice<Pager> pager = new MobileDevice<>();
MobileDevice<TabletPC> pc = new MobileDevice<>();
Run Code Online (Sandbox Code Playgroud)

因为静态字段os由电话,寻呼机和PC共享,所以os的实际类型是什么?它不能同时是Smartphone,Pager和TabletPC.因此,您无法创建类型参数的静态字段.

正如克里斯在他的回答中正确指出的那样,你需要在方法中使用类型参数,而不是在这种情况下使用类.你可以这样写:

static <E> void doIt(E object) 
Run Code Online (Sandbox Code Playgroud)