2012-01-31 75 views
4

我是新來的Java所以道歉,如果我有完全的棍子的錯誤結束。的Java和泛型

我試圖寫一個通用的(在這個詞的英語語感!)數據訪問類。 比如我現在有:

public class DA<T> { 
public static Dao getAccountDao() throws NamingException, SQLException { 
    Context ctx = new InitialContext(); 
    DataSource dataSource = (DataSource)ctx.lookup("java:comp/env/jdbc/test"); 
    ConnectionSource connectionSource = new DataSourceConnectionSource(dataSource, new MysqlDatabaseType());    
    Dao<Account, Integer> accountDao = DaoManager.createDao(connectionSource, Account.class); 
    return accountDao; 
} 
} 

我可以調用此方法:

Dao<Account, Integer> accountDao = DA.getAccountDao(); 

但我需要一個版本,這對於每道/模型。所以我試圖做一些可以這樣稱呼的東西:

Dao<SomeClass, Integer> someClassDao = DA.getDao(SomeClass); 

這是可能的嗎?

我已經試過了諸如:

public class DA { 
public static Dao getDao(<T>) throws NamingException, SQLException { 
    Context ctx = new InitialContext(); 
    DataSource dataSource = (DataSource)ctx.lookup("java:comp/env/jdbc/test"); 
    ConnectionSource connectionSource = new DataSourceConnectionSource(dataSource, new MysqlDatabaseType());    
    Dao<T, Integer> accountDao = DaoManager.createDao(connectionSource, T.class); 
    return accountDao; 
} 

}

但Netbeans中給出了錯誤:illegal start of type

我的大腦與泛型掙扎,就是這個東西,他們可以做的?

編輯:從崗位幫助下我已經有了:

public class DA<T> { 
public static Dao<T, Integer> getDao(T daoType) throws NamingException, SQLException { 
    Dao<T, Integer> accountDao = DaoManager.createDao(T.class); 
    return accountDao; 
} 

}

產生兩個錯誤: non-static type variable T cannot be referenced from a static context ,如果我刪除了static關鍵字,我得到: cannot select from a type variable 我需要如何泛型和靜態工作讀了起來,但第二個看起來像擦除的結果(http://www.coderanch.com/t/386358/java/java/Converting-type-parameters-class ),所以不知道它是否會發生可能。早期

應該提到,該道的東西是由一種叫做ORMLite的ORM庫,所以createDao等是不是我的代碼。

+0

我需要實現你的一個相似的目的和打算原路和你一樣。但是你使用的圖書館ORMLite,提出了一個不同的方式來解決這個問題。此評論不回答您的問題,但可能會幫助您以更好的方式實現您的整體目標。看到這個[所以問題的更多細節](http://stackoverflow.com/questions/8273675/how-to-extend-the-basedaoimpl-class-of-ormlite-on-android-to-extend-functionalit)。希望能幫助到你。 – 2013-12-09 00:55:32

回答

2

要訪問您T.class的意思,你必須對類對象傳遞給方法:

class Account {} 

class Dao<TEntity, TId> {} 

class DA { 
    // your DaoManager.createDao() will also need a similar signature 
    public static <TEntity> Dao<TEntity, Integer> getDao(Class<TEntity> daoType) { 
     /// yadda blah, create DAO as appropriate 
     return new Dao<TEntity, Integer>(); 
    } 
} 

public class Test { 
    public static void main(String[] args) { 
     // Pass the class literal for what you want TEntity to be as a parameter 
     Dao<Account, Integer> dao = DA.getDao(Account.class); 
    } 
} 
+2

這是爲什麼呢?編譯器知道T是什麼類型。爲什麼必須傳遞另一個參數?在C#中,你可以使用'typeof(T)',並且不需要額外的無用參數。 – 2014-03-02 02:43:34

+0

@GregEnnis Java和C#的泛型實現之間絕對根本的**區別在於,在Java中,「typeof(T)」不存在。爲了向後兼容,Java有意地在執行類型擦除之後爲通用方法生成代碼。編譯器只知道在'getDao()'的調用位置有什麼'T' - 這個信息不會以任何方式傳播到該方法的調用中。 – millimoose 2014-03-02 03:54:52

+0

@GregEnnis C#在這種特定情況下的不同之處在於,它以某種方式自動地將'typeof(T)'的* runtime *值從調用者傳播到被調用者。 (可以通過在方法中自動插入Type參數來實現,也可以通過爲每個類型/方法所需的實例生成不同的代碼,或者完全不同的代碼來實現,機制並不重要。然而,這樣會破壞很多兼容性 - 「非泛型」代碼無法調用Generified API。 – millimoose 2014-03-02 04:04:12

2

您希望您的DA類有兩種類型(例如,<Account, Integer>),但在你的類聲明你只指定一個類型<T>。看看一些文檔和示例,如這些:

http://en.wikipedia.org/wiki/Generics_in_Java#Generic_class_definitions
http://docs.oracle.com/javase/tutorial/java/generics/index.html

+0

對我來說,他只是想讓第二個參數始終爲整數。我假設它是一個實體的主鍵的類型,在這種情況下,Integer或Long是一個合理的硬編碼工具。 – millimoose 2012-01-31 22:54:19

+0

@Inddial - 正確! – Mark 2012-01-31 23:50:26

-1

如果需要指定需要一個模板參數類型的方法,模板自帶的返回類型之前:

<T> void foo(T param) { ... } 
+0

「模板參數」是一個可怕的名字。泛型和模板是截然不同的概念,它們在實現方式上有一些重疊。 – millimoose 2012-01-31 22:47:55

+0

另外,僅僅爲方法添加一個類型參數將不會完成OP想要的操作。 – millimoose 2012-01-31 22:48:47

1

你必須做這種方式:

public class DA { 
     public static <T> Dao<T,Integer> getDao(Class<T> clazz) throws NamingException, SQLException { 
      Context ctx = new InitialContext(); 
      DataSource dataSource = (DataSource)ctx.lookup("java:comp/env/jdbc/test"); 
      ConnectionSource connectionSource = new DataSourceConnectionSource(dataSource, new MysqlDatabaseType());    
      Dao<T, Integer> accountDao = DaoManager.createDao(connectionSource, clazz); 
      return accountDao; 
     } 
    } 

而且createDao方法都會有這樣的簽名:

public static <T> Dao<T,Integer> createDao(ConnectionSource source,Class<T> clazz) { 
... 
}