java泛型T.class的擷取

來源:互聯網
上載者:User

   很早之前寫過利用泛型和反射機制抽象DAO ,對其中擷取子類泛型的class一直不是很理解。關鍵的地方是HibernateBaseDao的構造方法中的

Type genType = getClass().getGenericSuperclass();<br />Type[] params = ((ParameterizedType) genType).getActualTypeArguments();<br />entityClass = (Class)params[0];<br />

 

但是這個相對子類才會有用,而且那篇文章的HibernateBaseDao還不是abstract,如果一不小心執行個體化的話就會報異常。感覺java中通過反射取泛型的class還是挺複雜的,不過一旦取到的話就可以做很多事情了。

 

改進的例子和測試:

1.先定義介面(這裡寫的比較簡單就一個方法,具體可以再增加)

public interface BaseDao<T> {<br />T get(String id);</p><p>}

2.定義抽象類別實現介面

import java.lang.reflect.ParameterizedType;<br />import java.lang.reflect.Type;</p><p>public abstract class HibernateBaseDao<T> implements BaseDao<T> {<br />private Class<T> entityClass;</p><p>/**<br /> * 這個通常也是hibernate的取得子類class的方法<br /> *<br /> * @author "yangk"<br /> * @date 2010-4-11 下午01:51:28<br /> */<br />public HibernateBaseDao() {<br />Type genType = getClass().getGenericSuperclass();<br />Type[] params = ((ParameterizedType) genType).getActualTypeArguments();<br />entityClass = (Class) params[0];<br />}</p><p>@Override<br />public T get(String id) {<br />try {<br />return entityClass.newInstance();<br />} catch (InstantiationException e) {<br />// TODO Auto-generated catch block<br />e.printStackTrace();<br />} catch (IllegalAccessException e) {<br />// TODO Auto-generated catch block<br />e.printStackTrace();<br />}<br />return null;<br />}</p><p>}

 

子類的建構函式會調用父類的建構函式,所以當子類執行個體化的時候,父類的entityClass 已經得到了T.class。

3.定義一個entity

public class Entity {</p><p>private String name;</p><p>public String getName() {<br />return name;<br />}</p><p>public void setName(String name) {<br />this.name = name;<br />}<br />}

 

4.定義entity的DAO

 public class EntityDao extends HibernateBaseDao<Entity> {</p><p>public void otherOperation() {</p><p>}</p><p>}

 

可以在裡面定義父類沒有的,針對具體子類特殊的方法。

5.測試

import static org.junit.Assert.assertNotNull;</p><p>import org.junit.After;<br />import org.junit.AfterClass;<br />import org.junit.Before;<br />import org.junit.BeforeClass;<br />import org.junit.Test;</p><p>public class JunitTest {<br />@BeforeClass<br />public static void setUpClass() throws Exception {<br />}</p><p>@AfterClass<br />public static void tearDownClass() throws Exception {<br />}</p><p>@Before<br />public void setUp() {<br />}</p><p>@After<br />public void tearDown() {<br />}</p><p>/**<br /> * Test of getEClass method, of class tmp.<br /> */<br />@Test<br />public void testNewClass() {<br />EntityDao testDao = new EntityDao();<br />Entity e = testDao.get(null);<br />assertNotNull(e);<br />}</p><p>}

 

運行,可以看到測試順利通過。

注意:上面子類DAO的寫法public class EntityDao extends HibernateBaseDao<Entity>

一定要在父類後面帶上泛型,負責編譯就會出錯。

 

 附:這是泛型擦拭法使得Generic無法擷取自己的Generic Type類型。實際上BadClass<String>()執行個體化以後Class裡面就不包括T的資訊了,對於Class而言T已經被擦拭為Object,而真正的T參數被轉到使用T的方法(或者變數聲明或者其它使用T的地方)裡面(如果沒有那就沒有存根),所以無法反射到T的具體類別,也就無法得到T.class。而getGenericSuperclass()是Generic繼承的特例,對於這種情況子類會儲存父類的Generic參數類型,返回一個ParameterizedType,這時可以擷取到父類的T.class了,這也正是子類確定應該繼承什麼T的方法。

 

 

 

 

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.