ジェネリッククラスの静的メソッド?
-
06-09-2019 - |
質問
Javaでは、私はのように何かを持っているしたいと思います:
class Clazz<T> {
static void doIt(T object) {
// shake that booty
}
}
しかし、私は取得
Cannot make a static reference to the non-static type T
私は基本的な用途を超えたジェネリックを理解していないので、そのあまり意味がないことができます。それは私が主題について、インターネット上で多くの情報を見つけることができなかったことを助けていません。
このような使用は、同様の方法により、可能であるならば、誰かが明確にもらえますか?また、なぜ私のオリジナルの試みは成功しなかった?
解決
あなたは、静的メソッドや静的フィールドにクラスのジェネリック型パラメータを使用することはできません。クラスの型パラメータには、インスタンスメソッドとインスタンスフィールドにのみ適用範囲内にあります。静的フィールドおよび静的メソッドのために、それらはクラスのすべてのインスタンス、異なる種類のパラメータであってもインスタンス間で共有されているので、明らかに、彼らは、特定のタイプのパラメータに依存することはできません。
あなたの問題は、クラスの型パラメータを使用して要求すべきであるようにこれは思えません。あなたは、より詳細にやろうとしているかを説明する場合は、多分私達は、あなたがそれを行うには良い方法を見つけることができます。
他のヒント
Javaはあなたがタイプをインスタンス化されるまで、何T
を知りません。
たぶん、あなたはClazz<T>.doit(something)
を呼び出すことにより、静的メソッドを実行することができますが、あなたができないように思えます。
物事を処理するための他の方法は、メソッド自体に型パラメータを置くことです
static <U> void doIt(U object)
これはあなたのU上の権利制限を得るが、それは何もないよりはましだしません....
私はこの同じ問題に遭遇しました。私は、JavaフレームワークでCollections.sort
のソースコードをダウンロードして私の答えを見つけました。私が使用した答えはないクラス定義では、この方法では一般的な<T>
を入れていた。
だから、これは働いていた。
public class QuickSortArray {
public static <T extends Comparable> void quickSort(T[] array, int bottom, int top){
//do it
}
}
もちろん、上記の答えを読んだ後、私は、これは一般的なクラスを使用することなく、許容の代替になることを実現します:
public static void quickSort(Comparable[] array, int bottom, int top){
//do it
}
あなたのdoIt()
メソッドを宣言するとき(<T>
のメソッドのシグネチャでstatic
とvoid
間doIt()
の追加を気付か)ジェネリックメソッドの構文を使用して、あなたが欲しいものを行うことが可能です。
class Clazz<T> {
static <T> void doIt(T object) {
// shake that booty
}
}
私はCannot make a static reference to the non-static type T
エラーなしで上記のコードを受け入れるようにEclipseのエディタを持って、次の作業プログラム(やや年齢に応じた文化参照して完成)にそれを拡張します:
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);
}
}
私はそれを実行すると、コンソールに以下の行を印刷し、どのます:
その戦利品を振る 'クラスcom.eclipseoptions.datamanager.Clazz $ KC' !!!
その戦利品 'クラスcom.eclipseoptions.datamanager.Clazz $ SunshineBand' を振る!!!
私はこの構文は(あなたは、引数なしでメソッドをしたい場合には)まだmentionnedされていないと考えます:
class Clazz {
static <T> T doIt() {
// shake that booty
}
}
と呼びます:
String str = Clazz.<String>doIt();
は、これが誰かを助けるホープます。
これは正しくエラーに記載されている:あなたは非静的型Tへの静的な参照を作ることができない理由は、型パラメータT
は、型引数のいずれかで置き換えることができ、例えばありますClazz<String>
またはClazz<integer>
などしかし、静的フィールド/メソッドは、クラスのすべての非静的オブジェクトによって共有されています。
以下の抜粋は、 DOCするから取られます。
クラスの静的フィールドは、すべてで共有クラスレベルの変数であります クラスの非静的オブジェクト。タイプのため、静的フィールド パラメータが許可されていません。次のクラスを考えてみます:
public class MobileDevice<T> { private static T os; // ... }
型パラメータの静的フィールドが許可された場合、次のコードが混同される:
静磁場OSは携帯電話、ポケットベル、およびPCで共有されているので、MobileDevice<Smartphone> phone = new MobileDevice<>(); MobileDevice<Pager> pager = new MobileDevice<>(); MobileDevice<TabletPC> pc = new MobileDevice<>();
、OSの実際の型は何ですか?これは、スマートフォン、ポケットベル、およびすることはできません 同時にタブレットPC。あなたは、それゆえ、静的フィールドを作成することはできません。 型パラメータのます。
として当然あなたがこの中にクラスとメソッドで型パラメータを使用していないする必要がに答えるhref="https://stackoverflow.com/a/7890292">彼の
static <E> void doIt(E object)
/ <その他は、すでにあなたの質問に答えましたが、加えて、私は徹底的にオライリー Javaのジェネリックをrecommentすることができます>本。それは時には繊細で複雑なテーマだし、多くの場合、無意味な制限を持っていると思われる場合は、しかし、この本は、Javaのジェネリックは、彼らがされている方法である理由を説明するのはかなり良い仕事をしていません。
次のようなものは、
あなたが近づくでしょうclass Clazz
{
public static <U extends Clazz> void doIt(U thing)
{
}
}
EDIT:詳細で更新例
public abstract class Thingo
{
public static <U extends Thingo> void doIt(U p_thingo)
{
p_thingo.thing();
}
protected abstract void thing();
}
class SubThingoOne extends Thingo
{
@Override
protected void thing()
{
System.out.println("SubThingoOne");
}
}
class SubThingoTwo extends Thingo
{
@Override
protected void thing()
{
System.out.println("SuThingoTwo");
}
}
public class ThingoTest
{
@Test
public void test()
{
Thingo t1 = new SubThingoOne();
Thingo t2 = new SubThingoTwo();
Thingo.doIt(t1);
Thingo.doIt(t2);
// compile error --> Thingo.doIt(new Object());
}
}
あなたはクラスのジェネリック型を指定すると、JVMは、それだけであなたのクラスではなく、定義のインスタンスを持っていることについて知っています。それぞれの定義は、タイプのみをパラメータ化しています。
ジェネリックはC ++でのテンプレートのように動作し、あなたが最初に指定されているタイプの機能を使用し、その後、あなたのクラスをインスタンス化する必要があります。
また、簡単な言葉でそれを置くために、それが理由generics.Whichの「消去」プロパティで起こる我々はArrayList<Integer>
とArrayList<String>
を定義しますが、コンパイル時に、それは二つの異なる具体的な種類としてではなく、実行時にとどまることを意味JVMは、ジェネリック型を消去し、代わりに、二つのクラスの唯一のArrayListクラスを作成します。私たちは、一般的なため、静的な型のメソッドまたは何かを定義するときに、それはそのジェネリックのすべてのインスタンスで共有され、私の例では、それはあなたがクラスのerror.Aジェネリック型パラメータを取得する理由です.That両方ArrayList<Integer>
とArrayList<String>
によって共有されています静的コンテキストで許可されていません!
Rivenhillで@BD:この古い質問は、昨年再び注目を得ているので、私たちはちょうど議論のために、ビットに行ってみましょう。
あなたの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()
+ "' !!!");
}
// ...
}
[OK]をクリックします。しかし、のが近い元の問題に戻って取得してみましょう。クラス宣言の最初の型変数は冗長です。唯一の方法の二つが必要とされています。ここではまだ、我々は再び行くが、それは最終的な答えではありません。
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";
}
}
静的変数は、クラスのすべてのインスタンスで共有されているので。たとえばあなたが
次のコードを持っている場合class Class<T> {
static void doIt(T object) {
// using T here
}
}
Tは、インスタンスが作成された後にのみ使用可能です。しかし、静的メソッドはインスタンスが利用可能であっても前に使用することができます。だから、ジェネリック型パラメータは静的メソッドと変数内で参照することができません。