泛型

前言:先說兩個快捷鍵sql

1. Ctrl + Shift + R :查找當前項目中的類編程

2. Ctrl + Shift + T:查找源碼JAR包中的類數組

1、概述編程語言

1.泛型是JDK1.5之後纔有的, 能夠在編譯時期進行類型檢查,且能夠避免頻繁類型轉化!函數

2.泛型擦除:泛型只在編譯時期有效,編譯後的字節碼文件中不存在有泛型信息!下面兩個方法不是方法重寫測試

public void save( List<Person> p ){}

public void save( List<Data> d ){}

3.聲明泛型集合,集合兩端類型必須一致;泛型類型必須是引用類型,不能爲基本類型。this

2、泛型方法/泛型類/泛型接口/泛型關鍵字spa

1.做用:設計公用的類、方法,對公用的業務實現進行抽取;使程序更靈活。設計

2.泛型方法:code

public class GenericDemo {
    // 定義泛型方法,<K,T>表示類型定義
    public <K, T> T save(T t, K k) {
        return null;
    }

    // 測試方法
    @Test
    public void testSave() {
        // 使用泛型方法: 在使用泛型方法的時候,肯定泛型類型
        save(1.0f, 1);

    }
}

3.泛型類:

public class GenericDemo<T> {
    // 定義泛型方法,<K,T>表示類型定義
    public <K> T save(T t, K k) {
        return null;
    }

    public void update(T t) {

    }

    // 測試方法
    @Test
    public void testSave() {
        // 泛型類: 在建立泛型類對象的時候,肯定類型
        GenericDemo<String> demo = new GenericDemo<String>();
        demo.save("test", 1);
    }
}

4.泛型接口

public interface IBaseDao<T> {
    void save(T t);

    void update(T t);
}

泛型接口類型肯定: 實現泛型接口的類也是抽象,那麼類型在具體的實現中肯定或建立泛型類的時候肯定

public class BaseDao<T> implements IBaseDao<T> {

泛型接口類型肯定: 在業務實現類中直接肯定接口的類型

public class PersonDao implements IBaseDao<Person> {

5.泛型關鍵字

泛型中:

  ?                  指定只是接收值

  extends        元素的類型必須繼承自指定的類

  super           元素的類型必須是指定類的父類

1)關鍵字:?

public class App_extends_super {

    // 只帶泛型特徵的方法
    public void save(List<?> list) {
        // 只能獲取、迭代list; 不能編輯list
    }

    @Test
    public void testGeneric() throws Exception {

        // ? 能夠接收任何泛型集合, 可是不能編輯集合值; 因此通常在方法參數中用
        List<?> list = new ArrayList<String>();
        // list.add("");// 報錯
    }
}

2)關鍵字:extends

public class App_extends_super {

    /**
     * list集合只能處理 Double/Float/Integer等類型 限定元素範圍:元素的類型要繼承自Number類 (上限)
     * 
     * @param list
     */
    public void save(List<? extends Number> list) {
    }

    @Test
    public void testGeneric() throws Exception {
        List<Double> list_1 = new ArrayList<Double>();
        List<Float> list_2 = new ArrayList<Float>();
        List<Integer> list_3 = new ArrayList<Integer>();

        List<String> list_4 = new ArrayList<String>();

        // 調用
        save(list_1);
        save(list_2);
        save(list_3);
        // save(list_4);//報錯
    }
}

3)關鍵字:super

public class App_extends_super {

    /**
     * super限定元素範圍:必須是String父類 【下限】
     * 
     * @param list
     */
    public void save(List<? super String> list) {
    }

    @Test
    public void testGeneric() throws Exception {
        // 調用上面方法,必須傳入String的父類
        List<Object> list1 = new ArrayList<Object>();
        List<String> list2 = new ArrayList<String>();

        List<Integer> list3 = new ArrayList<Integer>();
        save(list1);
        save(list2);
        // save(list3);//報錯
    }
}

3、泛型的反射

設置通用方法,會用到反射泛型!

1.反射泛型涉及的API:

Type:Type 是 Java 編程語言中全部類型的公共高級接口。它們包括原始類型、參數化類型、數組類型、類型變量和基本類型。

例如:

List<String>  list   =  new   ArrayList<String>();

泛型集合:list

集合元素定義:new   ArrayList<String>()中的String

參數化類型(ParameterizedType):ArrayList<String>爲參數化類型

2.反射泛型案例

public class AdminDao extends BaseDao<Admin> {}
public class AccountDao extends BaseDao<Account> {}




/**
 * 全部dao的公用的方法,都在這裏實現
 * @author 
 *
 */
public class BaseDao<T>{
    
    // 保存當前運行類的參數化類型中的實際的類型
    private Class clazz;
    // 表名
    private String tableName;
    
    
    
    // 構造函數: 1. 獲取當前運行類的參數化類型; 2. 獲取參數化類型中實際類型的定義(class)
    public BaseDao(){
        //  this  表示當前運行類  (AccountDao/AdminDao)
        //  this.getClass()  當前運行類的字節碼(AccountDao.class/AdminDao.class)
        //  this.getClass().getGenericSuperclass();  當前運行類的父類,即爲BaseDao<Account>
        //                                           其實就是「參數化類型」, ParameterizedType   
        Type type = this.getClass().getGenericSuperclass();
        // 強制轉換爲「參數化類型」  【BaseDao<Account>】
        ParameterizedType pt = (ParameterizedType) type;
        // 獲取參數化類型中,實際類型的定義  【new Type[]{Account.class}】
        Type types[] =  pt.getActualTypeArguments();
        // 獲取數據的第一個元素:Accout.class
        clazz = (Class) types[0];
        // 表名  (與類名同樣,只要獲取類名就能夠)
        tableName = clazz.getSimpleName();
    }
    

    /**
     * 主鍵查詢
     * @param id    主鍵值
     * @return      返回封裝後的對象
     */
    public T findById(int id){
        /*
         * 1. 知道封裝的對象的類型
         * 2. 表名【表名與對象名稱同樣, 且主鍵都爲id】
         * 
         * 即,
         *       ---》獲得當前運行類繼承的父類  BaseDao<Account>
         *   ----》 獲得Account.class
         */
        
        String sql = "select * from " + tableName + " where id=? ";
        try {
            return JdbcUtils.getQuerrRunner().query(sql, new BeanHandler<T>(clazz), id);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
    
    
    /**
     * 查詢所有
     * @return
     */
    public List<T> getAll(){
        String sql = "select * from " + tableName ;
        try {
            return JdbcUtils.getQuerrRunner().query(sql, new BeanListHandler<T>(clazz));
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
}
相關文章
相關標籤/搜索