泛型筆記整理

1、泛型-參數化類型
即:將類型由原來的具體的類型參數化
比如一個方法,方法參數是什麼類型,返回值就是什麼類型,由於寫方法之前並不知道調用者會傳入什麼類型的參數,所以就將參數的類型參數化;
    A.帶泛型的方法-泛型方法
        <E> 爲定義泛型,在修飾符與返回值之間
        private <E> E getMethod(E e){
            return e;
        }

    B.帶泛型的類-泛型類
        <T> 爲定義泛型,在類名之後
    public class MyDataList<T>{
        private List<T> data;
    }

    C.帶泛型的接口-泛型接口
        <T> 爲定義泛型,在類名之後
    public interface myinterface<T>{
        public void method1(T t);
    }
    實現接口的時候可以指定泛型的具體類型,也可以仍然使用泛型
2、泛型的好處
    A.避免類型轉換
    B.將運行期異常提前在編譯期檢查出來
3、特性
    泛型只在編譯期有效,編譯之後程序會採取去泛型化的措施,泛型信息不會進入到運行階段。
4、注意:泛型的類型只能是類類型,不能是簡單類型,比如只能是Integer,不能夠是int。
5、泛型通配符-?
    public void method1(?){

    }
    通配符-指定上限類型和下限類型(詳情見com.huangliwei.generic.GenericTest.method1Test)

泛型小demo——利用jdbc實現簡單的sql查詢和對象的自動封裝

查詢類:JDBCHandler 

package com.huangliwei.generic;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;

public class JDBCHandler {

    private String username;

    private String password;

    private String url;

    private Connection connection;

    static {
        //加載jdbc驅動
        try {
            Class.forName("com.mysql.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    public JDBCHandler(String username, String password, String url) {
        this.username = username;
        this.password = password;
        this.url = url;
        //初始化連接
        try {
            connection = DriverManager.getConnection(url, username, password);
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    /**
     * 執行查詢sql返回一個查詢對象
     *
     * @param sql
     * @param clazz
     * @param <T>
     * @return
     */
    public <T> T queryOne(String sql, Class<T> clazz) throws SQLException, IllegalAccessException, InstantiationException, InvocationTargetException {
        Statement statement = connection.createStatement();
        ResultSet rs = statement.executeQuery(sql);
        while (rs.next()) {
            return parseResultSetToObj(rs, clazz);
        }
        return null;
    }

    /**
     * 執行查詢sql返回多個對象
     *
     * @param sql
     * @param clazz
     * @param <T>
     * @return
     * @throws SQLException
     * @throws IllegalAccessException
     * @throws InstantiationException
     * @throws InvocationTargetException
     */
    public <T> List<T> queryMany(String sql, Class<T> clazz) throws SQLException, IllegalAccessException, InstantiationException, InvocationTargetException {
        Statement statement = connection.createStatement();
        ResultSet rs = statement.executeQuery(sql);
        ArrayList<T> result = new ArrayList<>();
        while (rs.next()) {
            result.add(parseResultSetToObj(rs, clazz));
        }
        return result;
    }

    /**
     * 查詢結果封裝成對象
     *
     * @param rs
     * @param clazz
     * @param <T>
     * @return
     * @throws IllegalAccessException
     * @throws InstantiationException
     * @throws SQLException
     * @throws InvocationTargetException
     */
    private <T> T parseResultSetToObj(ResultSet rs, Class<T> clazz) throws IllegalAccessException, InstantiationException, SQLException, InvocationTargetException {
        //實例化對象
        T t = clazz.newInstance();
        //獲取所有的public方法
        Method[] methods = clazz.getMethods();
        String[] columns = getColumns(rs);
        for (int i = 0; i < methods.length; i++) {
            Method method = methods[i];
            String methodName = method.getName();
            if (methodName.startsWith("set")) {
                for (int j = 0; j < columns.length; j++) {
                    String columnName = columns[j];
                    if (methodName.equalsIgnoreCase("set" + columnName)) {
                        //假設簡單類型的封裝,粗糙處理
                        method.invoke(t, rs.getObject(columnName));
                        break;
                    }
                }
            }
        }
        return t;
    }

    /**
     * 獲取查詢返回的所有列名
     *
     * @param rs
     * @return
     * @throws SQLException
     */
    private String[] getColumns(ResultSet rs) throws SQLException {
        ResultSetMetaData metaData = rs.getMetaData();
        int columnCount = metaData.getColumnCount();
        String[] columns = new String[columnCount];
        for (int i = 0; i < columnCount; i++) {
            columns[i] = metaData.getColumnName(i + 1);
        }
        return columns;
    }
}

測試類:JDBCHandlerTest 

package com.huangliwei.generic;

import com.huangliwei.entity.UserInfo;
import org.junit.Test;

import java.util.List;

public class JDBCHandlerTest {

    @Test
    public void queryOneTest() throws Exception {
        String username = "root";
        String sql = "select * from userinfo limit 1;";
        String password = "123456";
        String url = "jdbc:mysql://localhost:3306/yuleishangran?useUnicode=true&characterEncoding=utf8";
        JDBCHandler handler = new JDBCHandler(username, password, url);
        UserInfo userInfo = handler.queryOne(sql, UserInfo.class);
        System.out.println(userInfo);
    }

    @Test
    public void queryManyTest() throws Exception {
        String username = "root";
        String sql = "select * from userinfo;";
        String password = "123456";
        String url = "jdbc:mysql://localhost:3306/yuleishangran?useUnicode=true&characterEncoding=utf8";
        JDBCHandler handler = new JDBCHandler(username, password, url);
        List<UserInfo> userInfos = handler.queryMany(sql, UserInfo.class);
        System.out.println(userInfos);
    }
}

實體:UserInfo

package com.huangliwei.entity;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Objects;

public class UserInfo {
    private String username;

    private String password;

    private Date birthday;

    public UserInfo() {
    }

    public UserInfo(String username, String password, Date birthday) {
        this.username = username;
        this.password = password;
        this.birthday = birthday;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        UserInfo userInfo = (UserInfo) o;
        //用戶名相同就認爲對象一樣
        return Objects.equals(username, userInfo.username);
    }

    @Override
    public int hashCode() {

        return Objects.hash(username, password, birthday);
    }

    @Override
    public String toString() {
        return "UserInfo{" +
                "username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", birthday=" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(birthday) +
                '}';
    }
}

建表sql:

CREATE TABLE `userinfo` (
`username` VARCHAR ( 100 ) NOT NULL,
`password` VARCHAR ( 200 ) DEFAULT NULL,
`birthday` datetime DEFAULT NULL,
PRIMARY KEY ( `username` ) 
) ENGINE = INNODB DEFAULT CHARSET = utf8;
INSERT INTO userinfo
VALUES
	( '張三', '123456', now( ) );
INSERT INTO userinfo
VALUES
	( '李四', '654321', now( ) );

 泛型通配符-GenericTest 

package com.huangliwei.generic;

import java.util.ArrayList;

public class GenericTest {
    public static void main(String[] args) {
        GenericClass<Integer> gc = new GenericClass<>();
        ArrayList<Integer> list1 = new ArrayList<>();
        list1.add(123);
        gc.setData(list1);
    }

    public void method1Test(){
        GenericClass<String> gc1 = new GenericClass<String>();
        GenericClass<Integer> gc2 = new GenericClass<Integer>();
        //method1入參gc1、gc2都可以
        method1(gc1);
        method1(gc2);
        //method2的參數只能是gc2,因爲方法入參指定了具體的類型爲Integer
        //method2(gc1); 編譯報錯
        method2(gc2);
    }

    // 泛型通配符-使用通配符
    private static void method1(GenericClass<?> e){
    }
    // 泛型通配符-指定具體類型
    private static void method2(GenericClass<Integer> e){
    }
    //泛型通配符-指定上限類型(必須是Number本身或其子類)
    private static void method3(GenericClass<? extends Number> e){
    }
    //泛型通配符-指定下限類型(必須是Number本身或其父類)
    private static void method4(GenericClass<? super Number> e){
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章