2011-11-11 29 views
1

編譯時,此?擴展TSubject擴展主題 - 不是類型安全的,或只是Java無法處理它?

import java.util.List; 

public class Test { 
    public static class Subject { 
    } 

    public static class MySubject extends Subject { 
    } 

    public static class Step<TSubjectA extends Subject> { 
     public void doWork(TSubjectA subject) { 
     } 
    } 

    public static class Worker { 
     public static <TSubjectB extends Subject> void doWork(TSubjectB subject, List<Step<? extends TSubjectB>> steps) { 
      for (Step<? extends TSubjectB> step : steps) { 
       step.doWork(subject); 
      } 
     } 
    } 

    public static void main(String[] args) { 
     MySubject subject; 
     List<Step<? extends Subject>> steps; 

     Worker.doWork(subject, steps); 
    } 
} 

我得到的錯誤

Test.java:18:的doWork(捕獲#95擴展TSubjectB?)在Test.Step不能適用於(TSubjectB)

從我所看到的,subject是類型TSubjectB,其延伸Subject。類型TSubjectA是延伸TSubjectB的類型,其延伸Subject。所以我應該能夠通過subjectdoWork它應該都是類型安全的。

我錯過了什麼,它實際上不是類型安全的,或者這僅僅是Java的泛型的限制嗎?

回答

1

雖然類型參數TSubjectATSubjectB各自保證是某種類型的延伸Subject,它們不必是相同的類型 - 一個可能是MySubject而另一個可能是MyOtherSubject。這是當前代碼不被編譯器視爲類型安全的原因。

如果你需要的功能是嚴格依賴於Subject基本實現,只是刪除類型參數,並依靠多態性

public static class Step { 
    public void doWork(Subject subject) { 
     //do Subject stuff 
    } 
} 

public static class Worker { 
    public static void doWork(Subject subject, List<Step> steps) { 
     for (Step step : steps) { 
      step.doWork(subject); 
     } 
    } 
} 

public static void main(String[] args) { 

    List<Step> steps = ...; 

    //all valid 
    Worker.doWork(new Subject(), steps); 
    Worker.doWork(new MySubject(), steps); 
    Worker.doWork(new MyOtherSubject(), steps); 
} 

如果不是,那就是如果doWork實現根據不同在Subject的子類型上,那麼泛型不會對您有所幫助,您需要進行一些設計更改。請記住,Java中的泛型不是動態魔術,而是語法糖來幫助編譯時類型安全。如果您尚未理解此限制,請閱讀type erasure