什么是泛型
概述:JDK5以后, Java引入了“参数化类型(parameterized type)”的概念, 该概念也称之为泛型(Generic)。所谓泛型就是允许在定义类、接口或方法时使用类型形参,该类型形参将在声明变量、创建对象或者调用方法时动态指定(即传入实际的类型参数,可称为类型实参)
优点:泛型的出现简化了代码,提高了程序的健性。
用法:泛型的用法有泛型接口、泛型类、泛型方法这几种。
①泛型接口,Java5改写了集合框架中的全部接口,下面以List和Map接口中的部分代码为例展示泛型接口的定义:
定义接口时指定一个类型形参E,在此处定义好后可在整个接口体中当做类型使用。
定义Map接口时指定了两个类型参数一个类型形参K,V,在此处定义好后可在整个接口体中当做类型使用
②泛型类
泛型类,泛型不仅仅可以在定义接口是可以使用,定义类时同样可以使用,下面以Map接口实现类HashMap中的部分代码为例展示泛型类的定义:
③泛型方法
指声明一个带有定义一个或多个类型形参的方法.
如何定义泛型方法
访问控制符 [修饰符] <类型形参1,类型形参2,…… > 返回值类型 方法名( [参数] ) {
//方法体……
}
泛型位置:如果定义的泛型方法有修饰符,则泛型方法中的类型形参列表必须放在方法返回值类型之前,修饰符之后;如果定义的泛型方法没有修饰符,则泛型方法中的类型形参列表必须放在方法返回值类型之前,访问控制符之后;
作用范围:泛型方法中定义的类型形参只能在该方法中使用,而定义接口和类时定义的类型形参可以在整个接口和类中使用。
泛型在连接数据库时的使用
/**
* 连接数据库
*
*@author caiwenchuan
*/
public class DBlink<E>{
static {
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
} catch (ClassNotFoundException e1) {
e1.printStackTrace();
}
}
/**
* 获取数据库连接
*
* @author caiwenchuan
*/
private Connection getConnection() {
try {
return DriverManager.getConnection(PropertiesUtil.getValue("url"), PropertiesUtil.getValue("user_name"),PropertiesUtil.getValue("password"));
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
/**
* 释放资源
*
* @author caiwenchuan
*/
private void close(Connection connection,Statement statement,ResultSet rs) {
if(rs!=null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(statement!=null) {
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(connection!=null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
/**
* 查询数据库
*
* @author caiwenchuan
*/
public <E> E select(String sql,IRowMapper<E> rowmapper) {
Connection connection=new DBlink().getConnection();
Statement statement=null;
ResultSet rs=null;
try {
statement=connection.createStatement();
rs=statement.executeQuery(sql);
return rowmapper.dealResult(rs);
} catch (SQLException e) {
e.printStackTrace();
}finally {
new DBlink().close(connection, statement, rs);
}
return null;
}
/**
* 查询数据库
*
* @author caiwenchuan
*/
public <E> E select(String sql,IRowMapper<E> rowmapper,Object...values) {
Connection connection=new DBlink().getConnection();
PreparedStatement ps=null;
ResultSet rs=null;
try {
ps=connection.prepareStatement(sql);
for(int i=1;i<=values.length;i++) {
ps.setObject(i, values[i-1]);
}
rs=ps.executeQuery();
return rowmapper.dealResult(rs);
} catch (SQLException e) {
e.printStackTrace();
}finally {
new DBlink().close(connection,ps, rs);
}
return null;
}
}
我们定义了一个DBlink类可以用于操作数据库,在类名后加上泛型<E>,当我们在创建这个类对象时,给E传一个具体的数据类型值,那么这个类中所有的E就会代指这个数据类型
例如:new DBlink<String>().select 此时DBlink类中的select方法中的E就会变为String,我们可以尝试用这种方式通过用户名获取密码。
import java.sql.ResultSet;
public interface IRowMapper<E>{
E dealResult(ResultSet rs);
}
import java.sql.ResultSet;
import java.sql.SQLException;
import javax.swing.tree.RowMapper;
import javax.swing.tree.TreePath;
public class Test {
public static void main(String[] args) {
String sql="select * from user_info where user_name=?";
String password=new DBlink<String>().select(sql, new IRowMapper<String>() {
public String dealResult(ResultSet rs) {
try {
if(rs.next()) {
return rs.getString("password");
}
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
}, "kjiap");
System.out.println(password);
}
}
select方法参数中有IRowMapper接口类型的对象,我们在具体使用时,要传入它的实现类对象并重写抽象方法
如果我们定义一个有名内部类,代码显得繁琐,我们通过泛型和使用匿名内部类可以很大程度上简化代码。