程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA綜合教程 >> 使用java泛型設計通用方法,java泛型通用

使用java泛型設計通用方法,java泛型通用

編輯:JAVA綜合教程

使用java泛型設計通用方法,java泛型通用


泛型是Java SE 1.5的新特性, 泛型的本質是參數化類型, 也就是說所操作的數據類型被指定為一個參數. 因此我們可以利用泛型和反射來設計一些通用方法. 現在有2張表, 一張user表和一張student表.

user:

student:

  如果要根據id查詢數據, 你會怎麼做呢?寫2個方法分別查詢user和student?其實這時候我們就可以使用泛型和反射寫一個通用的方法.

  user的實體類:

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

 

  student實體類:

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

 

  BaseDao接口:

public interface BaseDao<T> {
    //根據id查詢的方法
    T findById(Integer id);
}
View Code

 

  BaseDaoImpl類, 實現了BaseDao接口, 通用方法就在這裡面完成:

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

    /**
     * findById(Integer id)這個方法被子類繼承了,  假設我們在UserDaoImpl中操作,  此時參數化類型T為User
     * 下面的講解都假設是在UserDaoImpl中進行的
     */
    //把公共部分可以放到構造方法中
    @SuppressWarnings("unchecked")
    public BaseDaoImpl() {
        //返回類型是Type 是 Java 編程語言中所有類型的公共高級接口. 它們包括原始類型、參數化類型、數組類型、類型變量和基本類型.  
        //Type的已知子接口: ParameterizedType 表示參數化類型, 如 Collection<String>.  
        //getClass()得到UserDaoImpl的Class,  得到Class一般有3中方式: getClass(),  類名.class,  Class.forName()
        Type type = getClass().getGenericSuperclass();//獲取UserDaoImpl<User>的參數化類型的父類BaseDaoImpl<User>
        //由於我們得到的是一個參數化類型,  所以轉成ParameterizedType,  因為需要使用裡面的方法
        ParameterizedType pt = (ParameterizedType) type;//強轉
        Type[] actualTypeArr = pt.getActualTypeArguments();//獲取真實參數類型數組[User.class],  可以調試看到這裡的值
        actualType = (Class<T>) actualTypeArr[0];//數組只有一個元素
        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;
    }
}

  連接數據庫操作是用的c3p0和dbutils, 有關這方面的內容可以參看我以前的隨筆.      

  UserDao接口, 繼承BaseDao接口:

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

  UserDaoImpl類, 實現UserDao接口, 繼承BaseDaoImpl類, 可以看到裡面什麼方法也沒有:

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

  StudentDao接口, 繼承BaseDao接口:

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

 

  StudentDaoImpl類, 實現StudentDao接口, 繼承BaseDaoImpl類, 也可以看到裡面什麼方法也沒有:

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

  從以上dao可以看到, 我是在繼承BaseDaoImpl類時把泛型具體化了.

測試:

 

    @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));
    }

  看一下測試的結果: 同一個方法把2張表中的數據都查出來了

  

 有關泛型的基本使用, 請參考java泛型基礎

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved