欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

java泛型基本知識(shí)及通用方法

 更新時(shí)間:2019年04月02日 10:26:11   作者:眺望小寒山  
這篇文章主要介紹了java泛型基礎(chǔ)知識(shí)及通用方法,從以下幾個(gè)方面介紹一下java的泛型: 基礎(chǔ), 泛型關(guān)鍵字, 泛型方法, 泛型類(lèi)和接口,感興趣的可以了解一下

泛型的基本使用

泛型是Java SE 1.5的新特性, 泛型的本質(zhì)是參數(shù)化類(lèi)型, 也就是說(shuō)所操作的數(shù)據(jù)類(lèi)型被指定為一個(gè)參數(shù). 這種參數(shù)類(lèi)型可以用在類(lèi)、接口和方法的創(chuàng)建中, 分別稱(chēng)為泛型類(lèi)、泛型接口、泛型方法.  Java語(yǔ)言引入泛型的好處是安全簡(jiǎn)單.

今天就從以下幾個(gè)方面介紹一下java的泛型: 基礎(chǔ), 泛型關(guān)鍵字, 泛型方法, 泛型類(lèi)和接口.

基礎(chǔ):

  通過(guò)集合的泛型了解泛型的基本使用

public void testBasis(){
 List<String> list = new ArrayList<String>();
// new ArrayList<int>();
 }
 
 //這是最基本的泛型使用, 就不多說(shuō)了, 不過(guò)要注意的是泛型只能是引用數(shù)據(jù)類(lèi)型, 不能是基本類(lèi)型, 而且泛型只在編譯期有效, 在編譯后的class文件中是不存在泛型信息的

 注意: 泛型只在編譯期有效, 在編譯后的class文件中是不存在泛型信息的

泛型關(guān)鍵字:

  通配符?表示任意引用類(lèi)型, extends關(guān)鍵字表示子類(lèi)及其本身, super關(guān)鍵字是表示父類(lèi)及其本身. 通過(guò)一個(gè)例子看一下, 解釋說(shuō)明都在例子中

public void testKeyWord() throws Exception {
 //實(shí)例化參數(shù)類(lèi)型必須指明具體類(lèi)型
 List<?> list = new ArrayList<String>();
 //由于list中類(lèi)型不明確, 所以不能進(jìn)行添加操作
// list.add("sk");
 
 //通配符?表示任意引用類(lèi)型
 List<List<?>> list1 = new ArrayList<List<?>>();
 //list1的參數(shù)化類(lèi)型是一個(gè)List, 而這個(gè)List也是一個(gè)參數(shù)化類(lèi)型, 它的類(lèi)型是任意類(lèi)型, 所以list1可以添加任意List類(lèi)型對(duì)象
 list1.add(new ArrayList<Object>());
 list1.add(new ArrayList<String>());
 
 //實(shí)例化list2時(shí)指明了類(lèi)型參數(shù)List, 只不過(guò)這個(gè)List是一個(gè)泛型類(lèi)型
 //從這里可以看到關(guān)鍵字extends的用法, 其實(shí)就是繼承, 如下這里的list2中的參數(shù)化類(lèi)型List(在這里記為paramList)的參數(shù)化類(lèi)型是繼承自Number的
 //所以在list2在添加的時(shí)候只能添加參數(shù)化類(lèi)型為Number及其子類(lèi)的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的父類(lèi)
 
 //相信大家也猜到了, 既然extends關(guān)鍵字表示子類(lèi)及其本身, 那么super關(guān)鍵字是表示父類(lèi)及其本身, 是的, 沒(méi)錯(cuò)
 //和上面的不一樣了, l1不能添加, 因?yàn)镮nteger是Number的子類(lèi), 并不是Number的父類(lèi)
 List<List<? super Number>> list3 = new ArrayList<List<? super Number>>();
// list3.add(l1); //這里使用了super關(guān)鍵字, 所以不能添加Number的子類(lèi)
 list3.add(l2);
 list3.add(l3);
 }

泛型方法:

  java中任何類(lèi)型必須先定義才能使用, 泛型也是如此. 既然要使用泛型作為參數(shù), 所以要先定義, 泛型的定義在訪問(wèn)修飾符和返回類(lèi)型之間, 注意不要掉了尖括號(hào)

//無(wú)返回值有參的方法, 參數(shù)為泛型
 public <T> void show(T t){
 System.out.println("t-=-=" + t);
 }
 
 //有返回值的有參方法, 只有一個(gè)參數(shù)化類(lèi)型, 這里定義泛型的方式和上面一樣, 也是先定義后使用, 只不過(guò)這里的返回類(lèi)型是泛型
 public <T> T get(T t){
 return t;
 }
 
 //有返回值的有參方法, 有多個(gè)參數(shù)化類(lèi)型, 這里以?xún)蓚€(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類(lèi)型-" + get(4));
 System.out.println("我返回String類(lèi)型-" + get("returnGeneric"));
 System.out.println("------------------");
 
 System.out.println("我返回String類(lèi)型-" + get(1, "a"));
 System.out.println("我返回Integer類(lèi)型-" + get("b", 2));
 }

  本來(lái)想寫(xiě)無(wú)參的泛型方法, 可是寫(xiě)著寫(xiě)著感覺(jué)那樣沒(méi)有什么意義, 不知道各位有什么見(jiàn)解.

泛型類(lèi)和接口:

  寫(xiě)泛型類(lèi)的時(shí)候只需要在類(lèi)名后面加上泛型即可, 就像這樣

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ù)化類(lèi)型是在創(chuàng)建對(duì)象的時(shí)候具體化的, 那么除此之外, 還可以再什么時(shí)候具體化參數(shù)化類(lèi)型呢?

  如果是在繼承或?qū)崿F(xiàn)中, 可以在子類(lèi)或?qū)崿F(xiàn)類(lèi)中確定具體類(lèi)型

使用java泛型設(shè)計(jì)通用方法

泛型是Java SE 1.5的新特性, 泛型的本質(zhì)是參數(shù)化類(lèi)型, 也就是說(shuō)所操作的數(shù)據(jù)類(lèi)型被指定為一個(gè)參數(shù). 因此我們可以利用泛型和反射來(lái)設(shè)計(jì)一些通用方法. 現(xiàn)在有2張表, 一張user表和一張student表.

user:

student:

  如果要根據(jù)id查詢(xún)數(shù)據(jù), 你會(huì)怎么做呢?寫(xiě)2個(gè)方法分別查詢(xún)user和student?其實(shí)這時(shí)候我們就可以使用泛型和反射寫(xiě)一個(gè)通用的方法.

  user的實(shí)體類(lèi):

private Integer id;
 private String username;
 private String password;
 private String hobby;
 //getXxx方法和setXxx方法

  student實(shí)體類(lèi):

 private Integer id;
 private String name;
 private Integer age;
 //getXxx方法和setXxx方法

  BaseDao接口:

public interface BaseDao<T> {
 //根據(jù)id查詢(xún)的方法
 T findById(Integer id);
}

  BaseDaoImpl類(lèi), 實(shí)現(xiàn)了BaseDao接口, 通用方法就在這里面完成:

//設(shè)置為抽象的, 不讓他實(shí)例化, 讓其子類(lèi)實(shí)例化就行了
//通過(guò)泛型設(shè)計(jì)通用方法的關(guān)鍵就是利用反射拿到泛型的具體類(lèi)型
public abstract class BaseDaoImpl<T> implements BaseDao<T> {
 private String tableName;  //表名
 private Class<T> actualType;//真實(shí)類(lèi)型

 /**
 * findById(Integer id)這個(gè)方法被子類(lèi)繼承了, 假設(shè)我們?cè)赨serDaoImpl中操作, 此時(shí)參數(shù)化類(lèi)型T為User
 * 下面的講解都假設(shè)是在UserDaoImpl中進(jìn)行的
 */
 //把公共部分可以放到構(gòu)造方法中
 @SuppressWarnings("unchecked")
 public BaseDaoImpl() {
 //返回類(lèi)型是Type 是 Java 編程語(yǔ)言中所有類(lèi)型的公共高級(jí)接口. 它們包括原始類(lèi)型、參數(shù)化類(lèi)型、數(shù)組類(lèi)型、類(lèi)型變量和基本類(lèi)型. 
 //Type的已知子接口: ParameterizedType 表示參數(shù)化類(lèi)型, 如 Collection<String>. 
 //getClass()得到UserDaoImpl的Class, 得到Class一般有3中方式: getClass(), 類(lèi)名.class, Class.forName()
 Type type = getClass().getGenericSuperclass();//獲取UserDaoImpl<User>的參數(shù)化類(lèi)型的父類(lèi)BaseDaoImpl<User>
 //由于我們得到的是一個(gè)參數(shù)化類(lèi)型, 所以轉(zhuǎn)成ParameterizedType, 因?yàn)樾枰褂美锩娴姆椒?
 ParameterizedType pt = (ParameterizedType) type;//強(qiáng)轉(zhuǎn)
 Type[] actualTypeArr = pt.getActualTypeArguments();//獲取真實(shí)參數(shù)類(lèi)型數(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ù)庫(kù)操作是用的c3p0和dbutils, 有關(guān)這方面的內(nèi)容可以參看我以前的隨筆.     

  UserDao接口, 繼承BaseDao接口:

public interface UserDao<T> extends BaseDao<T> {
}

  UserDaoImpl類(lèi), 實(shí)現(xiàn)UserDao接口, 繼承BaseDaoImpl類(lèi), 可以看到里面什么方法也沒(méi)有:

public class UserDaoImpl extends BaseDaoImpl<User> implements UserDao<User> {
}

  StudentDao接口, 繼承BaseDao接口:

public interface StudentDao<T> extends BaseDao<T> {
}

  StudentDaoImpl類(lèi), 實(shí)現(xiàn)StudentDao接口, 繼承BaseDaoImpl類(lèi), 也可以看到里面什么方法也沒(méi)有:

public class StudentDaoImpl extends BaseDaoImpl<Student> implements StudentDao<Student> {
}

  從以上dao可以看到, 我是在繼承BaseDaoImpl類(lèi)時(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ù)都查出來(lái)了

  

相關(guān)文章

  • Java HashSet(散列集),HashMap(散列映射)的簡(jiǎn)單介紹

    Java HashSet(散列集),HashMap(散列映射)的簡(jiǎn)單介紹

    這篇文章主要介紹了Java HashSet(散列集),HashMap(散列映射)的簡(jiǎn)單介紹,幫助大家更好的理解和學(xué)習(xí)Java集合框架的相關(guān)知識(shí),感興趣的朋友可以了解下
    2021-01-01
  • Java數(shù)組的特性_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    Java數(shù)組的特性_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    數(shù)組是基本上所有語(yǔ)言都會(huì)有的一種數(shù)據(jù)類(lèi)型,它表示一組相同類(lèi)型的數(shù)據(jù)的集合,具有固定的長(zhǎng)度,并且在內(nèi)存中占據(jù)連續(xù)的空間。在C,C++等語(yǔ)言中,數(shù)組的定義簡(jiǎn)潔清晰,而在Java中確有一些會(huì)讓人迷惑的特性。本文就嘗試分析這些特性
    2017-04-04
  • Nacos服務(wù)發(fā)現(xiàn)并發(fā)啟動(dòng)scheduleUpdate定時(shí)任務(wù)的流程分析

    Nacos服務(wù)發(fā)現(xiàn)并發(fā)啟動(dòng)scheduleUpdate定時(shí)任務(wù)的流程分析

    這篇文章主要介紹了Nacos服務(wù)發(fā)現(xiàn)并發(fā)啟動(dòng)scheduleUpdate定時(shí)任務(wù),本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-02-02
  • Maven依賴(lài)管理之parent與dependencyManagement深入分析

    Maven依賴(lài)管理之parent與dependencyManagement深入分析

    首先我們來(lái)說(shuō)說(shuō)parent標(biāo)簽,其實(shí)這個(gè)不難解釋?zhuān)褪歉傅囊馑迹琾om也有繼承的。比方說(shuō)我現(xiàn)在有A,B,C,A是B,C的父級(jí)?,F(xiàn)在就是有一個(gè)情況B,C其實(shí)有很多jar都是共同的,其實(shí)是可以放在父項(xiàng)目里面,這樣,讓B,C都繼承A就方便管理了
    2022-10-10
  • 詳解IDEA中Debug的使用和進(jìn)制轉(zhuǎn)換問(wèn)題

    詳解IDEA中Debug的使用和進(jìn)制轉(zhuǎn)換問(wèn)題

    這篇文章主要介紹了IDEA中Debug的使用和進(jìn)制轉(zhuǎn)換,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-11-11
  • 解決報(bào)java.lang.AssertionError錯(cuò)誤的問(wèn)題

    解決報(bào)java.lang.AssertionError錯(cuò)誤的問(wèn)題

    這篇文章主要介紹了解決報(bào)java.lang.AssertionError錯(cuò)誤的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-05-05
  • Java單鏈表的簡(jiǎn)單操作實(shí)現(xiàn)教程

    Java單鏈表的簡(jiǎn)單操作實(shí)現(xiàn)教程

    這篇文章主要給大家介紹了關(guān)于Java單鏈表的簡(jiǎn)單操作實(shí)現(xiàn)教程,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-11-11
  • 在?Spring?Boot?中使用?Quartz?調(diào)度作業(yè)的示例詳解

    在?Spring?Boot?中使用?Quartz?調(diào)度作業(yè)的示例詳解

    這篇文章主要介紹了在?Spring?Boot?中使用?Quartz?調(diào)度作業(yè)的示例詳解,在本文中,我們將看看如何使用Quartz框架來(lái)調(diào)度任務(wù),Quartz支持在特定時(shí)間運(yùn)行作業(yè)、重復(fù)作業(yè)執(zhí)行、將作業(yè)存儲(chǔ)在數(shù)據(jù)庫(kù)中以及Spring集成,需要的朋友可以參考下
    2022-07-07
  • Java 找不到或無(wú)法加載主類(lèi)的修復(fù)方法

    Java 找不到或無(wú)法加載主類(lèi)的修復(fù)方法

    這篇文章主要介紹了Java 找不到或無(wú)法加載主類(lèi)的修復(fù)方法,幫助大家更好的理解和使用Java,感興趣的朋友可以了解下
    2021-02-02
  • JAVA-4NIO之Channel之間的數(shù)據(jù)傳輸方法

    JAVA-4NIO之Channel之間的數(shù)據(jù)傳輸方法

    下面小編就為大家?guī)?lái)一篇JAVA-4NIO之Channel之間的數(shù)據(jù)傳輸方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-06-06

最新評(píng)論