Java'daki genel joker karakterlerle ilgili birkaç sorum var:
Arasındaki fark nedir
List<? extends T>
veList<? super T>
?Sınırlı joker karakter nedir ve sınırsız joker karakter nedir?
Java'daki genel joker karakterlerle ilgili birkaç sorum var:
Arasındaki fark nedir List<? extends T>
ve List<? super T>
?
Sınırlı joker karakter nedir ve sınırsız joker karakter nedir?
Yanıtlar:
İlk sorunuzda <? extends T>
ve <? super T>
sınırlı joker karakterlere örnekler. Sınırsız bir joker karakter gibi görünür <?>
ve temelde anlamına gelir <? extends Object>
. Bu, genel olarak herhangi bir tür olabileceği anlamına gelir. Sınırlı bir joker karakter ( <? extends T>
veya <? super T>
), belirli bir türü genişletmesi gerektiğini ( <? extends T>
üst sınır olarak bilinir) veya belirli bir türün atası olması gerektiğini ( <? super T>
alt sınır olarak bilinir ) söyleyerek türe bir kısıtlama getirir. .
Java Tutorials, Wildcards and More Fun with Wildcards makalelerinde jenerikler hakkında oldukça iyi açıklamalara sahiptir .
<? super C>
türünüzün, C
tür hiyerarşisinde yukarıdaki bir şeyle sınırlı olduğu anlamına gelir . (Son derece geç cevap verdiğim için özür dilerim. Sanırım 2 yıl önce yorum bildirimimiz yoktu?)
A sınıf hiyerarşiniz varsa, B, A'nın bir alt sınıfıdır ve C ve D'nin her ikisi de aşağıdaki gibi B'nin alt sınıfıdır.
class A {}
class B extends A {}
class C extends B {}
class D extends B {}
Sonra
List<? extends A> la;
la = new ArrayList<B>();
la = new ArrayList<C>();
la = new ArrayList<D>();
List<? super B> lb;
lb = new ArrayList<A>(); //fine
lb = new ArrayList<C>(); //will not compile
public void someMethod(List<? extends B> lb) {
B b = lb.get(0); // is fine
lb.add(new C()); //will not compile as we do not know the type of the list, only that it is bounded above by B
}
public void otherMethod(List<? super B> lb) {
B b = lb.get(0); // will not compile as we do not know whether the list is of type B, it may be a List<A> and only contain instances of A
lb.add(new B()); // is fine, as we know that it will be a super type of A
}
Sınırlı bir joker karakter, ? extends B
B'nin bir tür olduğu yer gibidir . Yani, tür bilinmemektedir, ancak üzerine bir "sınır" yerleştirilebilir. Bu durumda, B'nin bir alt sınıfı olan bir sınıfla sınırlanmıştır.
List<? super B>
olarak tanımladığı Liste B sınıfı ebeveyn sınıfıdır türünü kabul ? C ve D'nin hmm'yi derlememesinin nedeni nedir?
Josh Bloch'un ayrıca ne zaman kullanılacağına dair iyi bir açıklaması var super
ve extends
bu google io video konuşmasında Üretici Tüketiciden bahsettiğiextends
super
anımsatıcısından .
Sunum slaytlarından:
Şuna toplu yöntemler eklemek istediğinizi varsayalım:
Stack<E>
void pushAll(Collection<? extends E> src);
- src bir E üreticisidir
void popAll(Collection<? super E> dst);
- dst bir E tüketicisidir
Bir tür parametresine geçirilmesine izin verilen tür türlerini kısıtlamak isteyeceğiniz zamanlar olabilir. Örneğin, sayılar üzerinde çalışan bir yöntem, yalnızca Number veya alt sınıflarının örneklerini kabul etmek isteyebilir. Sınırlı tip parametreleri bunun içindir.
Collection<? extends MyObject>
MyObject ile IS-A ilişkisi olan tüm nesneleri (yani bir myObject türü olan herhangi bir nesneyi veya MyObject'in herhangi bir alt sınıfından herhangi bir nesneyi söyleyebiliriz) veya MyObject sınıfının bir nesnesini kabul edebileceği anlamına gelir .
Örneğin:
class MyObject {}
class YourObject extends MyObject{}
class OurObject extends MyObject{}
Sonra,
Collection<? extends MyObject> myObject;
yalnızca MyObject veya MyObject alt sınıflarını kabul eder (yani, OurObject veya YourObject veya MyObject türündeki herhangi bir nesneyi, ancak MyObject’in üst sınıfının herhangi bir nesnesini kabul etmeyecektir).
Genel olarak,
Bir yapı, form türünde öğeler içeriyorsa
? extends E
, yapıdan öğeler çıkarabiliriz, ancak yapıya öğeler koyamayız.
List<Integer> ints = new ArrayList<Integer>();
ints.add(1);
ints.add(2);
List<? extends Number> nums = ints;
nums.add(3.14); // compile-time error
assert ints.toString().equals("[1, 2, 3.14]");
Yapıya eleman eklemek için başka bir tür joker karaktere ihtiyacımız var Wildcards with super
,
List<Object> objs = Arrays.<Object>asList(2, 3.14, "four");
List<Integer> ints = Arrays.asList(5, 6);
Collections.copy(objs, ints);
assert objs.toString().equals("[5, 6, four]");
public static <T> void copy(List<? super T> dst, List<? extends T> src) {
for (int i = 0; i < src.size(); i++) {
dst.set(i, src.get(i));
}
}
Koleksiyon üzerinde çalışan yöntemleri daha yeniden kullanılabilir hale getirmek için genel joker karakterler oluşturulur.
Örneğin, bir yöntemin bir parametresi varsa List<A>
, sadece List<A>
bu yönteme verebiliriz . Bu yöntemin işlevi bazı durumlarda israftır :
List<A>
, List<A-sub>
bu yönteme vermemize izin verilmelidir . (Çünkü A-sub, bir A'dır)List<A>
, List<A-super>
bu yönteme vermemize izin verilmelidir . (Çünkü A, A-süperdir)