1) İnternette ve StackOverflow'da jenerikler ve varargs ile ilgili belirli bir konu hakkında birçok örnek vardır. Temel olarak, bir type-parametre türünde değişken sayıda bağımsız değişkeniniz olduğunda:
<T> void foo(T... args);
Java'da varargs, derleme zamanında basit bir "yeniden yazma" geçiren sözdizimsel bir şekerdir: türdeki bir varargs parametresi, türdeki X...
bir parametreye dönüştürülür X[]
; ve bu varargs yöntemine her çağrı yapıldığında, derleyici varargs parametresine giren tüm "değişken argümanlarını" toplar ve aynen bir dizi oluşturur new X[] { ...(arguments go here)... }
.
Varargs tipi beton gibi olduğunda bu iyi çalışır String...
. Bu bir tür değişkeni T...
olduğunda T
, o çağrı için somut bir tür olduğu da bilinir. Örneğin, yukarıdaki yöntem bir sınıfın parçasıysa Foo<T>
ve bir Foo<String>
referansınız varsa, kodda bu noktada olduğunu foo
bildiğimiz T
için çağırmak uygun olacaktır String
.
Ancak, "değeri" T
başka bir tür parametresi olduğunda çalışmaz . Java'da, tür parametresi bileşen türünde ( new T[] { ... }
) bir dizi oluşturmak imkansızdır . Java bunun yerine kullanır new Object[] { ... }
(burada Object
üst sınır T
; üst sınır farklı bir şey olsaydı, bunun yerine olurdu Object
) ve sonra derleyici uyarısı verir.
Peki ya yaratma new Object[]
yerine yanlış olan new T[]
ne var? Java dizileri çalışma zamanında bileşen türlerini bilir. Böylece, iletilen dizi nesnesi çalışma zamanında yanlış bileşen türüne sahip olacaktır.
Muhtemelen en yaygın varargs kullanımı için, sadece öğeler üzerinde tekrarlamak için, bu sorun değildir (dizinin çalışma zamanı türünü umursamazsınız), bu yüzden güvenlidir:
@SafeVarargs
final <T> void foo(T... args) {
for (T x : args) {
// do stuff with x
}
}
Ancak, geçirilen dizinin çalışma zamanı bileşen türüne bağlı olan herhangi bir şey için güvenli olmaz. Güvensiz ve çöken bir şeyin basit bir örneği:
class UnSafeVarargs
{
static <T> T[] asArray(T... args) {
return args;
}
static <T> T[] arrayOfTwo(T a, T b) {
return asArray(a, b);
}
public static void main(String[] args) {
String[] bar = arrayOfTwo("hi", "mom");
}
}
Buradaki sorun biz türüne bağlıdır olmasıdır args
olmak T[]
olarak dönebilmek için T[]
. Ancak aslında çalışma sırasındaki argümanın türü bunun bir örneği değildir T[]
.
3) Yönteminizde bir tür bağımsız değişken varsa T...
(burada T herhangi bir tür parametresidir), o zaman:
- Güvenli: Metodunuz sadece dizinin elemanlarının
T
- Güvensiz: Dizinin,
T[]
Dizinin çalışma zamanı türüne bağlı olan şeyler şunlardır: tür olarak döndürme, tür T[]
parametresine bağımsız değişken olarak geçirme T[]
, dizi türünü kullanma .getClass()
, dizinin çalışma zamanı türüne bağlı yöntemlere geçirme, List.toArray()
ve Arrays.copyOf()
, vb.
2) Yukarıda bahsettiğim ayrım otomatik olarak kolayca ayırt edilemeyecek kadar karmaşık.