2009-03-07 30 views
3

Bu question'da, TofuBeer, bir jenerikleştirilmiş IterableEnumeration oluşturma sorunları yaşıyordu.Bu Java genericics joker hatası nasıl giderilir?

Cevabı jcrossley3'ten gelen bu sorunu işaret eden http://www.javaspecialists.eu/archive/Issue107.html bu problemi oldukça çözdü.

Hala elde edemeyeceğim bir şey var. Asıl sorun olarak etkin Erickson tarafından işaret olmasıydı:

You cannot specify a wildcard when constructing a parameterized type

Ama bildiriminde joker çıkarmadan da işe yaramadı: Aşağıdaki hata

final IterableEnumeration<ZipEntry> iteratable 
        = new IterableEnumeration<ZipEntry>(zipFile.entries()); 

Sonuçlar:

Main.java:19: cannot find symbol 
symbol : constructor IterableEnumeration(java.util.Enumeration<capture#469 of ? extends java.util.zip.ZipEntry>) 
location: class IterableEnumeration<java.util.zip.ZipEntry> 
     final IterableEnumeration<ZipEntry> iteratable = new IterableEnumeration<ZipEntry>( zipFile.entries()); 
                 ^
1 error 

Ama JavaSpecialist içinde numuneler yaptığım iş:

IterableEnumeration<String> ie = 
       new IterableEnumeration<String>(sv.elements()); 
public Enumeration<E> elements() 

başarısız bir ZipFile kimin imzası gelen ise

geçerli::

public Enumeration<? extends ZipEntry> entries() 
Ben spot

Tek fark JavaSpecialists blog, Enumeration kimin imzası olan bir Vector geliyor olmasıdır

Son olarak, bunların tümü, her yapı için ve

for(final ZipEntry entry : IterableEnumeration.make(zipFile.entries())) { 
    if(!(entry.isDirectory())) { 
     names.add(entry.getName()); 
    } 
} 
numaralı belgede önerilen statik yöntem yöntemiyle absorbe edilir.

Ama !! Bu haber bültenindeki nokta bu sorunu çözmek değildi, ancak sözdizimi çirkin görünüyor çünkü genel bir tür belirtme ihtiyacını önlemek için!

Yani

.. sorularım geçerli: Ne oluyor

?

örneği neden, Enumeration türü <? extends SomeClass> olan bir çalışma ortamı oluşturuyor? Ve neden her yapı için problemi yutuyor?

Neden bu iş vermez:

for(final ZipEntry entry : IterableEnumeration.make(zipFile.entries())) { 

ama bu işe? Aşağıda

final IterableEnumeration<ZipEntry> iteratable 
        = IterableEnumeration.make(zipFile.entries()); 

TofuBeer orijinal bir kod (hafifçe) değiştirilmiş bir versiyonu:

import java.util.Enumeration; 
import java.util.HashSet; 
import java.util.Iterator; 
import java.util.Set; 
import java.util.zip.ZipEntry; 
import java.util.zip.ZipFile; 
import java.util.Vector; 

public class Main { 
    private ZipFile zipFile; 

    public Set<String> entries() { 

     final Vector<ZipEntry> vector = new Vector<ZipEntry>(); 
     // why this works. 
     //final IterableEnumeration<ZipEntry> iteratable = new IterableEnumeration<ZipEntry>(vector.elements()); 

     // but this do not. 
     //final IterableEnumeration<ZipEntry> iteratable = new IterableEnumeration<ZipEntry>(zipFile.entries()); 

     // nor this 
     final IterableEnumeration<ZipEntry> iteratable = IterableEnumeration.make(zipFile.entries()); 

     // And what's with the for-each that doesn't care about the type?  
     final Set<String> names = new HashSet<String>(); 

     for(final ZipEntry entry : IterableEnumeration.make(zipFile.entries())) { 
      if(!(entry.isDirectory())) { 
       names.add(entry.getName()); 
      } 
     } 

     return (names); 
    } 
} 

class IterableEnumeration<T> implements Iterable<T> { 
    private final Enumeration<T> enumeration; 

    public IterableEnumeration(final Enumeration<T> e) { 
     enumeration = e; 
    } 

    public Iterator<T> iterator() { 
     return new Iterator<T>() { 
      public boolean hasNext() { 
       return (enumeration.hasMoreElements()); 
      } 

      public T next() { 
       return (enumeration.nextElement()); 
      } 

      public void remove() { 
       throw new UnsupportedOperationException("Cannot remove via an Enumeration"); 
      } 
     }; 
    } 
    // As suggested by http://www.javaspecialists.eu/archive/Issue107.html 
    // but doesn't help with: final IterableEnumeration<ZipEntry> iteratable = IterableEnumeration.make(zipFile.entries()); 
    public static <T> Iterable<T> make(Enumeration<T> en) { 
     return new IterableEnumeration<T>(en); 
    } 
} 

bunu anlamak istiyorum !!

cevap

3

Foreach döngüsüyle ne olduğundan emin değilim, ancak ZipFile.entries() 'den döndürülen belirtilmemiş türü kabul etmek için IterableEnumeration bildiriminize joker karakteri eklemeniz gerekir.

muhtemelen bu yüzden (burada

private final Enumeration<? extends T> enumeration; 

    public IterableEnumeration(final Enumeration<? extends T> e) { 
     enumeration = e; 
    } 

    public static <T> Iterable<T> make(Enumeration<? extends T> en) { 
     return new IterableEnumeration<T>(en); 
    } 
+0

: -O Bunu denedim! Ben yapmadım: -/ – OscarRyz

+0

: - O. . . ... – OscarRyz

+0

Evet, ancak make() yöntemini de değiştirdim. – Matthew

0

altta yatan sorun ile

private final Enumeration<T> enumeration; 

    public IterableEnumeration(final Enumeration<T> e) { 
     enumeration = e; 
    } 

    public static <T> Iterable<T> make(Enumeration<T> en) { 
     return new IterableEnumeration<T>(en); 
    } 

ZipFile jeneriği destekleyecek şekilde değiştirilmiştir zaman, sürdürücü entries() yöntemlerin Enumeration<? extends ZipEntry> dönüş türünü yapmak seçti olmasıdır Değiştir JarFile alt sınıfındaki yöntemin Enumeration<JarEntry> değerini döndürebileceğini. Bu, gördüğünüz soruna neden olur.

Enumeration<T> eşanlamlı olarak kullanıldığı için (her zaman olduğu gibi - her zaman değerleri döndürür), her zaman yöntem argümanlarının Enumeration<? extends T> değerini almasını sağlamanız gerekir.

İlgili konular