小編給大家分享一下java泛型基本知識(shí)的示例分析,希望大家閱讀完這篇文章之后都有所收獲,下面讓我們一起去探討吧!
白山網(wǎng)站制作公司哪家好,找創(chuàng)新互聯(lián)!從網(wǎng)頁設(shè)計(jì)、網(wǎng)站建設(shè)、微信開發(fā)、APP開發(fā)、成都響應(yīng)式網(wǎng)站建設(shè)等網(wǎng)站項(xiàng)目制作,到程序開發(fā),運(yùn)營維護(hù)。創(chuàng)新互聯(lián)于2013年成立到現(xiàn)在10年的時(shí)間,我們擁有了豐富的建站經(jīng)驗(yàn)和運(yùn)維經(jīng)驗(yàn),來保證我們的工作的順利進(jìn)行。專注于網(wǎng)站建設(shè)就選創(chuàng)新互聯(lián)。
泛型的基本使用
泛型是Java SE 1.5的新特性, 泛型的本質(zhì)是參數(shù)化類型, 也就是說所操作的數(shù)據(jù)類型被指定為一個(gè)參數(shù). 這種參數(shù)類型可以用在類、接口和方法的創(chuàng)建中, 分別稱為泛型類、泛型接口、泛型方法. Java語言引入泛型的好處是安全簡單.
今天就從以下幾個(gè)方面介紹一下java的泛型: 基礎(chǔ), 泛型關(guān)鍵字, 泛型方法, 泛型類和接口.
基礎(chǔ):
通過集合的泛型了解泛型的基本使用
public void testBasis(){ List<String> list = new ArrayList<String>(); // new ArrayList<int>(); } //這是最基本的泛型使用, 就不多說了, 不過要注意的是泛型只能是引用數(shù)據(jù)類型, 不能是基本類型, 而且泛型只在編譯期有效, 在編譯后的class文件中是不存在泛型信息的
注意: 泛型只在編譯期有效, 在編譯后的class文件中是不存在泛型信息的
泛型關(guān)鍵字:
通配符?表示任意引用類型, extends關(guān)鍵字表示子類及其本身, super關(guān)鍵字是表示父類及其本身. 通過一個(gè)例子看一下, 解釋說明都在例子中
public void testKeyWord() throws Exception { //實(shí)例化參數(shù)類型必須指明具體類型 List<?> list = new ArrayList<String>(); //由于list中類型不明確, 所以不能進(jìn)行添加操作 // list.add("sk"); //通配符?表示任意引用類型 List<List<?>> list1 = new ArrayList<List<?>>(); //list1的參數(shù)化類型是一個(gè)List, 而這個(gè)List也是一個(gè)參數(shù)化類型, 它的類型是任意類型, 所以list1可以添加任意List類型對(duì)象 list1.add(new ArrayList<Object>()); list1.add(new ArrayList<String>()); //實(shí)例化list2時(shí)指明了類型參數(shù)List, 只不過這個(gè)List是一個(gè)泛型類型 //從這里可以看到關(guān)鍵字extends的用法, 其實(shí)就是繼承, 如下這里的list2中的參數(shù)化類型List(在這里記為paramList)的參數(shù)化類型是繼承自Number的 //所以在list2在添加的時(shí)候只能添加參數(shù)化類型為Number及其子類的paramList List<Integer> l1 = new ArrayList<Integer>(); List<Number> l2 = new ArrayList<Number>(); List<Object> l3 = new ArrayList<Object>(); List<List<? extends Number>> list2 = new ArrayList<List<? extends Number>>(); list2.add(l1); list2.add(l2); // list2.add(l3); //這里使用了extends關(guān)鍵字, 所以不能添加Number的父類 //相信大家也猜到了, 既然extends關(guān)鍵字表示子類及其本身, 那么super關(guān)鍵字是表示父類及其本身, 是的, 沒錯(cuò) //和上面的不一樣了, l1不能添加, 因?yàn)镮nteger是Number的子類, 并不是Number的父類 List<List<? super Number>> list3 = new ArrayList<List<? super Number>>(); // list3.add(l1); //這里使用了super關(guān)鍵字, 所以不能添加Number的子類 list3.add(l2); list3.add(l3); }
泛型方法:
java中任何類型必須先定義才能使用, 泛型也是如此. 既然要使用泛型作為參數(shù), 所以要先定義, 泛型的定義在訪問修飾符和返回類型之間, 注意不要掉了尖括號(hào)
//無返回值有參的方法, 參數(shù)為泛型 public <T> void show(T t){ System.out.println("t-=-=" + t); } //有返回值的有參方法, 只有一個(gè)參數(shù)化類型, 這里定義泛型的方式和上面一樣, 也是先定義后使用, 只不過這里的返回類型是泛型 public <T> T get(T t){ return t; } //有返回值的有參方法, 有多個(gè)參數(shù)化類型, 這里以兩個(gè)為例 public <T, K> K get(T t, K k){ return k; } @Test public void testGeneric() throws Exception { show(3); show("generic"); System.out.println("----------------"); System.out.println("我返回Integer類型-" + get(4)); System.out.println("我返回String類型-" + get("returnGeneric")); System.out.println("------------------"); System.out.println("我返回String類型-" + get(1, "a")); System.out.println("我返回Integer類型-" + get("b", 2)); }
本來想寫無參的泛型方法, 可是寫著寫著感覺那樣沒有什么意義, 不知道各位有什么見解.
泛型類和接口:
寫泛型類的時(shí)候只需要在類名后面加上泛型即可, 就像這樣
public class GenericClass<T> { public T get(T t){ return t; } public void scr(T t){ System.out.println(t); } public void show(){ GenericClass<Integer> gc = new GenericClass<Integer>(); // GenericClass<T> gc1 = new GenericClass<T>(); gc.get(3); gc.scr(5); //下面2個(gè)會(huì)報(bào)錯(cuò) // gc1.get(3); // gc1.scr(5); } }
從上面的例子中可以看到, 參數(shù)化類型是在創(chuàng)建對(duì)象的時(shí)候具體化的, 那么除此之外, 還可以再什么時(shí)候具體化參數(shù)化類型呢?
如果是在繼承或?qū)崿F(xiàn)中, 可以在子類或?qū)崿F(xiàn)類中確定具體類型
使用java泛型設(shè)計(jì)通用方法
泛型是Java SE 1.5的新特性, 泛型的本質(zhì)是參數(shù)化類型, 也就是說所操作的數(shù)據(jù)類型被指定為一個(gè)參數(shù). 因此我們可以利用泛型和反射來設(shè)計(jì)一些通用方法. 現(xiàn)在有2張表, 一張user表和一張student表.
user:
student:
如果要根據(jù)id查詢數(shù)據(jù), 你會(huì)怎么做呢?寫2個(gè)方法分別查詢user和student?其實(shí)這時(shí)候我們就可以使用泛型和反射寫一個(gè)通用的方法.
user的實(shí)體類:
private Integer id; private String username; private String password; private String hobby; //getXxx方法和setXxx方法
student實(shí)體類:
private Integer id; private String name; private Integer age; //getXxx方法和setXxx方法
BaseDao接口:
public interface BaseDao<T> { //根據(jù)id查詢的方法 T findById(Integer id); }
BaseDaoImpl類, 實(shí)現(xiàn)了BaseDao接口, 通用方法就在這里面完成:
//設(shè)置為抽象的, 不讓他實(shí)例化, 讓其子類實(shí)例化就行了 //通過泛型設(shè)計(jì)通用方法的關(guān)鍵就是利用反射拿到泛型的具體類型 public abstract class BaseDaoImpl<T> implements BaseDao<T> { private String tableName; //表名 private Class<T> actualType;//真實(shí)類型 /** * findById(Integer id)這個(gè)方法被子類繼承了, 假設(shè)我們?cè)赨serDaoImpl中操作, 此時(shí)參數(shù)化類型T為User * 下面的講解都假設(shè)是在UserDaoImpl中進(jìn)行的 */ //把公共部分可以放到構(gòu)造方法中 @SuppressWarnings("unchecked") public BaseDaoImpl() { //返回類型是Type 是 Java 編程語言中所有類型的公共高級(jí)接口. 它們包括原始類型、參數(shù)化類型、數(shù)組類型、類型變量和基本類型. //Type的已知子接口: ParameterizedType 表示參數(shù)化類型, 如 Collection<String>. //getClass()得到UserDaoImpl的Class, 得到Class一般有3中方式: getClass(), 類名.class, Class.forName() Type type = getClass().getGenericSuperclass();//獲取UserDaoImpl<User>的參數(shù)化類型的父類BaseDaoImpl<User> //由于我們得到的是一個(gè)參數(shù)化類型, 所以轉(zhuǎn)成ParameterizedType, 因?yàn)樾枰褂美锩娴姆椒? ParameterizedType pt = (ParameterizedType) type;//強(qiáng)轉(zhuǎn) Type[] actualTypeArr = pt.getActualTypeArguments();//獲取真實(shí)參數(shù)類型數(shù)組[User.class], 可以調(diào)試看到這里的值 actualType = (Class<T>) actualTypeArr[0];//數(shù)組只有一個(gè)元素 tableName = actualType.getSimpleName(); } @Override public T findById(Integer id) { String sql = "select * from " + tableName + " where id = ?"; try { return QRUtils.getQueryRunner().query(sql, new BeanHandler<T>(actualType), id); } catch (SQLException e) { e.printStackTrace(); } return null; } }
連接數(shù)據(jù)庫操作是用的c3p0和dbutils, 有關(guān)這方面的內(nèi)容可以參看我以前的隨筆.
UserDao接口, 繼承BaseDao接口:
public interface UserDao<T> extends BaseDao<T> { }
UserDaoImpl類, 實(shí)現(xiàn)UserDao接口, 繼承BaseDaoImpl類, 可以看到里面什么方法也沒有:
public class UserDaoImpl extends BaseDaoImpl<User> implements UserDao<User> { }
StudentDao接口, 繼承BaseDao接口:
public interface StudentDao<T> extends BaseDao<T> { }
StudentDaoImpl類, 實(shí)現(xiàn)StudentDao接口, 繼承BaseDaoImpl類, 也可以看到里面什么方法也沒有:
public class StudentDaoImpl extends BaseDaoImpl<Student> implements StudentDao<Student> { }
從以上dao可以看到, 我是在繼承BaseDaoImpl類時(shí)把泛型具體化了.
測(cè)試:
@Test public void testGeneric() throws Exception { UserDao<User> userDao = new UserDaoImpl(); System.out.println(userDao.findById(1)); System.out.println("-------------------"); StudentDao<Student> studentDao = new StudentDaoImpl(); System.out.println(studentDao.findById(1)); }
看一下測(cè)試的結(jié)果: 同一個(gè)方法把2張表中的數(shù)據(jù)都查出來了
看完了這篇文章,相信你對(duì)“java泛型基本知識(shí)的示例分析”有了一定的了解,如果想了解更多相關(guān)知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝各位的閱讀!
本文名稱:java泛型基本知識(shí)的示例分析
URL網(wǎng)址:http://www.ekvhdxd.cn/article40/gscpho.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供自適應(yīng)網(wǎng)站、網(wǎng)站內(nèi)鏈、網(wǎng)站導(dǎo)航、虛擬主機(jī)、做網(wǎng)站、品牌網(wǎng)站設(shè)計(jì)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)