2017-08-15 543 views
0

關於返回泛型類型的Java方法有很多問題,但目前爲止他們都沒有幫助我。返回兩個或多個泛型類型的Java方法

因此,這裏是我的代碼:

interface DAO<K, T> { 
    void insert(T t); 
    void update(K k, T t); 
    void delete(K k); 
    void delete(); 
    T  select(K k); 
    List<T> select(); 
} 

public class CourseDAO implements DAO<String, Course> { 
    public void   insert(Course t) {} 
    public void   update(String k, Course t) {} 
    public void   delete(String k) {} 
    public void   delete() {} 
    public Course  select(String k) {} 
    public List<Course> select() {} 
} 

public class StudentDAO implements DAO<Long, Student> { 
    public void   insert(Student t) {} 
    public void   update(Long k, Student t) {} 
    public void   delete(Long k) {} 
    public void   delete() {} 
    public Student  select(Long k) {} 
    public List<Student> select() {} 
} 

public enum EntityType { COURSE, STUDENT } 

現在我想它接受一個EntityType參數和返回根據參數值CourseDAOStudentDAO實例的工廠方法。

我嘗試下面的代碼沒有成功:

public <K,T> DAO<K,T> createDAOFactory(EntityType type) { 
    switch (type) { 
     case COURSE : return (K,T) new CourseDAO(); break; 
     case STUDENT : return (K,T) new StudentDAO(); break; 
    } 
    return null; 
} 

誰能幫我寫,並調用此方法???

乾杯,
Romualdo。

+2

你試圖用這種工廠方法解決什麼問題?據我所知,使用這種方法沒有明智的方法(假設它可以編譯開始)。 – Steven

+0

如果我從保留DAO作爲返回類型的方法簽名中刪除,並且從返回值中刪除了(K,T),但是Eclipse會顯示警告:「DAO是原始類型,對泛型類型DAO 的引用應該被參數化」。 –

+0

是的,這是編譯它的一種方法。但是,您打算如何調用此方法並使用它返回的DAO? – Steven

回答

1

您正在尋找的演員是(DAO<K,T>)。但是你會得到一個警告,因爲泛型擦除使得它不安全。 switch工廠的另一個固有風險是,當您添加新的EntityType時,您可能會忘記創建相應的case。一個更安全的替代方法是用泛型重新定義EntityType,並讓它成爲工廠。不幸的是,這是不可能的適當枚舉,但你可以模擬這樣的:

abstract class EntityType<K, T> { 
    public abstract DAO<K, T> createDAO(); 

    public static final EntityType<String, Course> COURSE = new EntityType<String, Course>() { 
     @Override 
     public DAO<String, Course> createDAO() { 
      return new CourseDAO(); 
     } 
    }; 
    public static final EntityType<Long, Student> STUDENT = new EntityType<Long, Student>() { 
     @Override 
     public DAO<Long, Student> createDAO() { 
      return new StudentDAO(); 
     } 
    }; 
} 

或者你可以使用lambda表達式來減少樣板:

class EntityType<K, T> { 
    private final Supplier<DAO<K, T>> constructor; 

    private EntityType(Supplier<DAO<K, T>> constructor) { 
     this.constructor = constructor; 
    } 

    public DAO<K, T> createDAO() { 
     return constructor.get(); 
    } 

    public static final EntityType<String, Course> COURSE = new EntityType<>(CourseDAO::new); 
    public static final EntityType<Long, Student> STUDENT = new EntityType<>(StudentDAO::new); 
} 

現在,而不是調用createDAOFactory(EntityType.COURSE),你只需撥打EntityType.COURSE.createDAO()即可。

+0

嗨Shmosel,在你的第一個例子中,你能告訴我們工廠如何使用這個抽象類 –

+0

@ScaryWombat它是**工廠。編輯澄清。 – shmosel

+0

*你只需要調用*'EntityType.COURSE.createDAO()'OK,這很有道理 –

0

也許你可以這樣做?

public class StudentDAO<Long,Student> implements DAO<Long, Student> { 
    public void   insert(Student t) {} 
    public void   update(Long k, Student t) {} 
    public void   delete(Long k) {} 
    public void   delete() {} 
    public Student  select(Long k) {return null;} 
    public List<Student> select() {return null;} 
} 

public <K,T> DAO<K,T>createDAOFactory(EntityType type) { 
    switch (type) { 
     case COURSE : return new CourseDAO(); 
     case STUDENT : return new StudentDAO(); 
    } 
    return null; 
} 

第一個答案

你不需要使用泛型,因爲實現類指定的類型。

public DAO createDAOFactory(EntityType type) { 
    switch (type) { 
     case COURSE : return new CourseDAO(); 
     case STUDENT : return new StudentDAO(); 
    } 
    return null; 
} 
+0

謝謝flytosea,我正在這樣做。 Plz閱讀了Steven的評論(上圖)。 –