Java Jenerikleri (Joker Karakterler)


Yanıtlar:


123

İ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 .


Sadece doğru yapmak için, eğer A <B ve B <C ise: <A, C'yi genişletir> yanlış mı?
Pablo Fernandez

A <B ile, A'nın B'yi genişlettiğini kastediyorsunuz, o zaman A, C'yi genişletiyor. C A veya B birine seçimlerinizi sınırlamak için> uzanır
Bill Lizard

ve bu durumda <? süper C> fark ne olurdu?
Pablo Fernandez

3
Java Generics hakkında başka bir referans önermek istedim: angelikalanger.com/GenericsFAQ/JavaGenericsFAQ.html
Zach Scrivena

3
@Pablo: <? super C>türünüzün, Ctü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?)
Bill the Lizard

49

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 BB'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.


Ben varsayalım 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?
Volkan Güven

38

Josh Bloch'un ayrıca ne zaman kullanılacağına dair iyi bir açıklaması var superve extendsbu google io video konuşmasında Üretici Tüketiciden bahsettiğiextendssuper 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


Bloch'un kitabını okudum, ancak bu özel durumda hala extends ve super arasındaki farkı göremiyorum.
Pablo Fernandez

Videoyu izleyin, bence oldukça açık. Ayrıca, bu "Liste <? Extends T> ile Liste <? Super T> arasındaki fark nedir" üzerine başka bir soru sormanız gerektiğini düşünüyorum, burada daha fazla cevap alacaksınız. (yaparsanız, buradan bir bağlantı ekleyin)
boş

2
Yataklar - tam ve tek başına olması için neden bu cevaba örneği dahil etmiyorsunuz? Bağlantılar geçicidir.
James Schek

3

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).


1

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));
         }
    }

1

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 :

  1. Bu yöntem sadece nesnelerden okursa List<A>, List<A-sub>bu yönteme vermemize izin verilmelidir . (Çünkü A-sub, bir A'dır)
  2. Bu yöntem yalnızca nesneler eklerse List<A>, List<A-super>bu yönteme vermemize izin verilmelidir . (Çünkü A, A-süperdir)
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.