Java Generic yöntemi nasıl statik hale getirilir?


174

Aşağıda, bir diziye tek bir öğe eklemek için java genel sınıfının nasıl oluşturulacağı hakkında bir pasaj bulunmaktadır. AppendToArray öğesini statik bir yöntem haline nasıl getirebilirim. Yöntem imzasına statik eklemek derleme hatalarına neden olur.

public class ArrayUtils<E> {

        public E[] appendToArray(E[] array, E item) {
            E[] result = (E[])new Object[array.length+1];
            result[array.length] = item;
            return result;
        }
}

Hangi derleme hatalarını alıyorsunuz? Ayrıca, neden sadece standart kütüphane kaplarından birini kullanmıyorsunuz?
Karl Knechtel

1
Derleme Hatası: Aslında statik değiştirici yanlış ekliyordu .. Koleksiyonlar kullanma: Evet bir koleksiyon kullanarak ideal olurdu ama soru koleksiyonları vs dizi's hakkında değil, benim kullanım durumum bir dizi gerektirir.
Chris Johnson

İstemci kodunun her durumda olmasa da bazı durumlarda istisna atmasını durdurmak için (EVIL) yansımasını kullanmanız gerekeceğini unutmayın (güzel). Referans dizilerinden kaçınmak en iyisidir.
Tom Hawtin - taktik

Yanıtlar:


284

yapabileceğiniz tek şey imzanızı değiştirmek

public static <E> E[] appendToArray(E[] array, E item)

Önemli ayrıntılar:

Dönüş değerinden önceki genel ifadeler her zaman yeni bir genel tür değişkeni getirir (bildirir).

Ayrıca, type ( ArrayUtils) ve statik yöntemler ( appendToArray) arasındaki tip değişkenleri asla birbirini etkilemez.

Yani, bu anlama geliyor?: Benim cevap olarak <E>saklanırdı Egelen ArrayUtils<E>yöntem olmaz eğer static. VE <E>ile ilgisi yoktur Eden ArrayUtils<E>.

Bu gerçeği daha iyi yansıtabilmek için daha doğru bir cevap:

public static <I> I[] appendToArray(I[] array, I item)

30
Ayrıca, sınıf düzeyi tür değişkeni Eile statik yöntem türü değişkeni arasında kesinlikle bir ilişki olmadığını da unutmayın E. Genel sınıflar içinde, statik veya başka bir şekilde genel yöntemler bildirirken farklı bir değişken adı kullanmak çok daha iyi bir uygulama olarak değerlendirilir.
Yargıç Zihin

ancak bu durumda farklı türden bir nesneyi parametrelere geçirebilirim. İlk param ve Çift öğe olarak Integer [] dizisini geçebilir gibi.
pinkpanther

pinkpanther: Doğru, ancak herhangi bir zarar vermez, çünkü statik yöntem yalnızca bir parametre aracılığıyla kendisine iletilen bir dizi nesnesinde çalışır, bu nedenle öğeleri doğru türde olduğundan emin olur.
Dabbler

80
public static <E> E[] appendToArray(E[] array, E item) { ...

Not edin <E>.

Statik genel yöntemler public static <E>, sınıfın genel bildiriminden ( ) ayrı olarak kendi genel bildirimine ( ) ihtiyaç duyar public class ArrayUtils<E>.

Derleyici, statik bir genel yöntem çağırmadaki bir tür belirsizliğinden şikayet ederse (yine de durumunuzda olası değildir, ancak genel olarak konuşursak, belirli bir tür ( _class_.<_generictypeparams_>_methodname_) kullanarak statik bir genel yöntemi nasıl açıkça çağıracağınız aşağıda açıklanmıştır :

String[] newStrings = ArrayUtils.<String>appendToArray(strings, "another string");

Bu yalnızca derleyici genel türü belirleyemezse olur, çünkü genel tür yöntem bağımsız değişkenleriyle ilişkili değildir.


10

Generic sınıfından ziyade genel bir yönteminiz olduğunu belirtmek için type parametresini yöntem düzeyine taşımanız gerekir:

public class ArrayUtils {
    public static <T> E[] appendToArray(E[] array, E item) {
        E[] result = (E[])new Object[array.length+1];
        result[array.length] = item;
        return result;
    }
}

1
Bu, E genel türünü tanımlamadığınız için işe yaramaz. Bu durumda, sınıf tanımında hala <E> genel türüne sahip olmanız gerekir.
George Xavier

0

Basit bir şekilde açıklayacağım.

Sınıf düzeyinde tanımlanan jenerikler (statik) yöntem seviyesinde tanımlanan jeneriklerden tamamen farklıdır.

class Greet<T> {

    public static <T> void sayHello(T obj) {
        System.out.println("Hello " + obj);
    }
}

Yukarıdaki kodu herhangi bir yerde gördüğünüzde, sınıf düzeyinde tanımlanan T'nin statik yöntemde tanımlanan T ile hiçbir ilgisi olmadığını lütfen unutmayın. Aşağıdaki kod da tamamen geçerlidir ve yukarıdaki koda eşdeğerdir.

class Greet<T> {

    public static <E> void sayHello(E obj) {
        System.out.println("Hello " + obj);
    }
}

Statik yöntemin neden kendi jeneriklerinin Sınıfdakilerden ayrı olması gerekir?

Bunun nedeni, Statik yöntem Sınıfı örneklemeden bile çağrılabilir. Eğer Sınıf henüz somutlaştırılmamışsa, T'nin ne olduğunu henüz bilmiyoruz. Bu, statik yöntemlerin kendi jeneriklerine sahip olmasının nedenidir.

Yani, statik yöntemi her çağırdığınızda,

Greet.sayHello("Bob");
Greet.sayHello(123);

JVM bunu aşağıdaki gibi yorumlar.

Greet.<String>sayHello("Bob");
Greet.<Integer>sayHello(123);

Her ikisi de aynı çıktıları veriyor.

Hello Bob
Hello 123
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.