泛型Genericity
简介
泛型Genericity是程序语言的一种特性(不单是java中独有)。是指在强类型程序设计语言(例如:java)中,允许程序员在写程序时写一些可变部分,但是在使用时,必须明确类型。这么做可以提高代码复用性,从而提高开发效率。
类泛型实战
简单用法
package com.aaa.genericity.class1;
import java.util.Date;
/**
* @FileName: Person
* @Description:
* @Author: zhz
* @CreateTime: 2024/11/20 15:12
* @Version: 1.0.0
*/
//<A> 可以是任意字符,但必须大写,只起到占位符的作用 泛指任意类型
// 类型如果是基本数据类型,必须是封装类(不能写int,需要写Integer)
public class Person <A>{
//写程序时,不确定A是什么类型
private A name;
/* private String name;
private Date name;
private Integer name;*/
public void printName() {
System.out.println(name);
}
public Person(A name) {
this.name = name;
}
public A getName() {
return name;
}
public void setName(A name) {
this.name = name;
}
}
复杂用法
泛型类
package com.aaa.genericity.class2;
/**
* @FileName: Person
* @Description:
* @Author: zhz
* @CreateTime: 2024/11/21 8:54
* @Version: 1.0.0
*/
public class Person <A,B,C,D,E>{
private A a;
private B b;
private C c;
private D d;
private E e;
/**
* 打印信息
*/
public void printMsg(){
System.out.println(a+" "+b+" "+c+" "+d+" "+e);
}
public Person(A a, B b, C c, D d, E e) {
this.a = a;
this.b = b;
this.c = c;
this.d = d;
this.e = e;
}
public A getA() {
return a;
}
public void setA(A a) {
this.a= a;
}
public B getB() {
return b;
}
public void setB(B b) {
this.b = b;
}
public C getC() {
return c;
}
public void setC(C c) {
this.c = c;
}
public D getD() {
return d;
}
public void setD(D d) {
this.d = d;
}
public E getE() {
return e;
}
public void setE(E e) {
this.e = e;
}
}
测试
package com.aaa.genericity.class2;
import com.aaa.genericity.entity.Dept;
/**
* @FileName: Test
* @Description:
* @Author: zhz
* @CreateTime: 2024/11/21 8:57
* @Version: 1.0.0
*/
public class Test {
public static void main(String[] args) {
// 泛型类
//Integer=int Character=char
Person<String,Integer,Double,Boolean,Character> person = new Person<>("aaa", 1, 2.2, true, 'a');
person.printMsg();
//在使用float或者short的时候,需要使用包装类 后面填充值时,注意一定是float和short类型
Person<Long, Dept,Double,Float,Short> person1 = new Person<>(11l, new Dept(), 2.2, 2.2f, Short.valueOf("1"));
person1.printMsg();
}
}
方法泛型实战
需求
把一个整型数组转换了list
实战
方法泛型代码
package com.aaa.genericity.method;
import java.util.ArrayList;
import java.util.List;
/**
* @FileName: ProjectUtil
* @Description: 为项目提供很多通用方法 //Hutools 工具类
* @Author: zhz
* @CreateTime: 2024/11/21 9:07
* @Version: 1.0.0
*/
public class ProjectUtil {
/**
* 通用的数组转List方法
* @param tArray
* @return
* @param <T>
*/
//<T> 定义后面集合或者参数中使用的泛型的标识
public static <T> List<T> arrayToList(T[] tArray){
//判断数组是否为空
if(tArray==null||tArray.length==0){
return null;
}
//定义返回集合
List<T> tList = new ArrayList<>();
//循环遍历数组,将数组中的元素添加到list中
for (T t : tArray) {
tList.add(t);
}
return tList;
}
//后面还有其他方法
}
测试
package com.aaa.genericity.method;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
/**
* @FileName: Test
* @Description:
* @Author: zhz
* @CreateTime: 2024/11/21 9:12
* @Version: 1.0.0
*/
public class Test {
public static void main(String[] args) {
Integer[] integerArray = {1,2,3,4,5};
List<Integer> integerList = ProjectUtil.arrayToList(integerArray);
System.out.println(integerList);
String[] stringArray = {"a","b","c","d","e"};
List<String> stringList = ProjectUtil.arrayToList(stringArray);
System.out.println(stringList);
Date date = new Date();
// 获取时间戳 从1970年到现在的毫秒数
long time = date.getTime();
Date date1 = new Date(time + 1000);
Date date2 = new Date(time + 2000);
Date[] dateArray = {date,date1,date2};
/*List<Date> dateList1 = Arrays.asList(dateArray);
System.out.println(dateList1);*/
List<Date> dateList = ProjectUtil.arrayToList(dateArray);
System.out.println(dateList);
}
}
泛型?的用法
注意事项
?和T有啥区别:?代表未知类型,不能用于类泛型或者方法泛型,只能在参数或者返回值中使用。T代表一种类型,可以任意地方使用。
用法
需求
遍历并打印集合
代码
package com.aaa.genericity.wh;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* @FileName: PrintList
* @Description:
* @Author: zhz
* @CreateTime: 2024/11/21 9:35
* @Version: 1.0.0
*/
//public class PrintList<?> { //不能用于类泛型
public class PrintList {
//泛型方法 ?不可用
/*public <?> void printList1(List<?> list){
System.out.println("打印集合元素");
}*/
public void printList(List<?> list){
System.out.println("打印集合元素");
if(list!=null&&list.size()>0) {
for (Object o : list) {
System.out.println(o);
}
}else {
System.out.println("集合为空!");
}
}
public static void main(String[] args) {
PrintList printList = new PrintList();
List<String> list = Arrays.asList("aaa","bbb","ccc");
printList.printList(list);
List<Integer> integerList =new ArrayList<>();
integerList.add(11);
integerList.add(22);
integerList.add(33);
integerList.add(44);
printList.printList(integerList);
}
}
泛型?在继承中的用法
上界通配符
语法:List<? extends T>:代表T本身或者T的子孙类
下界通配符
语法:List<? super T>:代表T本身或者T的父类
实战
需求
某主人喂养一群宠物,宠物之间有继承关系
代码
编写宠物类,并有继承关系
大猫
package com.aaa.genericity.wh1;
/**
* @FileName: BigCat
* @Description:
* @Author: zhz
* @CreateTime: 2024/11/21 9:55
* @Version: 1.0.0
*/
public class BigCat {
/**
* 吃方法
*/
public void eat(){
System.out.println("大猫吃大鱼");
}
}
中猫
package com.aaa.genericity.wh1;
/**
* @FileName: BigCat
* @Description:
* @Author: zhz
* @CreateTime: 2024/11/21 9:55
* @Version: 1.0.0
*/
public class MediumCat extends BigCat{
/**
* 吃方法
*/
public void eat(){
System.out.println("中猫吃中鱼");
}
}
小猫
package com.aaa.genericity.wh1;
/**
* @FileName: BigCat
* @Description:
* @Author: zhz
* @CreateTime: 2024/11/21 9:55
* @Version: 1.0.0
*/
public class SmallCat extends MediumCat{
/**
* 吃方法
*/
public void eat(){
System.out.println("小猫吃小鱼");
}
}
小小猫
package com.aaa.genericity.wh1;
/**
* @FileName: BigCat
* @Description:
* @Author: zhz
* @CreateTime: 2024/11/21 9:55
* @Version: 1.0.0
*/
public class TinyCat extends SmallCat{
/**
* 吃方法
*/
public void eat(){
System.out.println("小小猫吃小小鱼");
}
}
编写主人类,编写喂养方法
package com.aaa.genericity.wh1;
import java.util.List;
/**
* @FileName: Master
* @Description:
* @Author: zhz
* @CreateTime: 2024/11/21 9:59
* @Version: 1.0.0
*/
public class Master {
//主人名字
private String name;
public Master(String name) {
this.name = name;
}
/**
* 喂养宠物
* @param catList
*/
//上界通配符例子
//public void feed(List<? extends MediumCat> catList){
//下界通配符例子
public void feed(List<? super MediumCat> catList){
System.out.println("主人" + name + "开始喂养宠物!");
if(catList!=null&&catList.size()>0){
for (Object o : catList) {
//因为BigCat的父类是Object 所以这里需要强转
BigCat bigCat = (BigCat)o;
bigCat.eat();
}
}
}
}
测试
package com.aaa.genericity.wh1;
import java.util.ArrayList;
import java.util.List;
/**
* @FileName: Test
* @Description:
* @Author: zhz
* @CreateTime: 2024/11/21 10:02
* @Version: 1.0.0
*/
public class Test {
public static void main(String[] args) {
//实例化主任类
Master master = new Master("华安");
//实例化大猫集合
List<BigCat> bigCatList =new ArrayList<>();
//实例化大猫
BigCat bigCat1 = new BigCat();
BigCat bigCat2 = new BigCat();
BigCat bigCat3 = new BigCat();
bigCatList.add(bigCat1);
bigCatList.add(bigCat2);
bigCatList.add(bigCat3);
//喂养
master.feed(bigCatList);
//实例化中猫集合
List<MediumCat> mediumCatList =new ArrayList<>();
//实例化中猫
MediumCat mediumCat1 = new MediumCat();
MediumCat mediumCat2 = new MediumCat();
MediumCat mediumCat3 = new MediumCat();
mediumCatList.add(mediumCat1);
mediumCatList.add(mediumCat2);
mediumCatList.add(mediumCat3);
//喂养
master.feed(mediumCatList);
//实例化小猫集合
List<SmallCat> smallCatList =new ArrayList<>();
//实例化小猫
SmallCat smallCat1 = new SmallCat();
SmallCat smallCat2 = new SmallCat();
SmallCat smallCat3 = new SmallCat();
smallCatList.add(smallCat1);
smallCatList.add(smallCat2);
smallCatList.add(smallCat3);
//喂养
//master.feed(smallCatList);
//实例化小小猫集合
List<TinyCat> tinyCatList =new ArrayList<>();
//实例化小小猫
TinyCat tinyCat1 = new TinyCat();
TinyCat tinyCat2 = new TinyCat();
TinyCat tinyCat3 = new TinyCat();
tinyCatList.add(tinyCat1);
tinyCatList.add(tinyCat2);
tinyCatList.add(tinyCat3);
//喂养
//master.feed(tinyCatList);
}
}
测试结论:上界能喂养中猫,小猫和小小猫;
下界能喂养大猫,中猫。
综合实战
需求
学习了反射,注解和泛型,拿三个技术编写一个类ORM(对象关系映射)框架(ORM框架的代表hibernate和mybatis,mybatis-plus)。模仿和hirbernate和mybatis-plus很类似!
例如:根据Dept查询 List
Dept dept =new Dept();
dept.setDeptNo(101) 查询时,查询编号为101的部门
dept.setDeptName("开") 查询时,查询名字中含有开的
或者 dept.setDeptName("开,部") 查询时,会查询部门名称中含有开或者部
条件没有就查询全部
并返回List
准备工作
数据库使用:db_qy178
** 项目中加入mysql的驱动jar包**
<dependencies>
<!--masql驱动包-->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>8.0.32</version>
</dependency>
</dependencies>
编写自定义注解
package com.aaa.demo.anno;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @FileName: Table
* @Description:ORM的接口上使用的的注解
* @Author: zhz
* @CreateTime: 2024/11/21 10:59
* @Version: 1.0.0
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Table {
//库名称
String dbName() default "mysql";
//表名
String tableName() default "user";
}
package com.aaa.demo.anno;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @FileName: Column
* @Description:
* @Author: zhz
* @CreateTime: 2024/11/21 11:01
* @Version: 1.0.0
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Column {
//数据库的列名称
String name() default "";
}
编写实体类
package com.aaa.demo.entity;
import com.aaa.demo.anno.Column;
import com.aaa.demo.anno.Table;
/**
* @FileName: Dept
* @Description:
* @Author: zhz
* @CreateTime: 2024/11/21 11:04
* @Version: 1.0.0
*/
@Table(dbName = "db_qy178", tableName = "tb_dept")
public class Dept {
@Column(columnName = "dept_no")
private Integer deptNo;
@Column(columnName = "dept_name")
private String deptName;
@Column(columnName = "loc")
private String loc;
public Integer getDeptNo() {
return deptNo;
}
public void setDeptNo(Integer deptNo) {
this.deptNo = deptNo;
}
public String getDeptName() {
return deptName;
}
public void setDeptName(String deptName) {
this.deptName = deptName;
}
public String getLoc() {
return loc;
}
public void setLoc(String loc) {
this.loc = loc;
}
}
编写公共的DAO接口
package com.aaa.demo.dao;
import java.util.List;
/**
* @FileName: PublicDao
* @Description: 公共接口
* @Author: zhz
* @CreateTime: 2024/11/21 11:10
* @Version: 1.0.0
*/
public interface PublicDao {
/**
* 通用查询接口
* @param t 传入的任意类对象
* @return 传入实体的结合
* @param <T>
*/
public <T> List<T> executeQuery(T t);
}
编写DAO实现类
package com.aaa.demo.dao.impl;
import com.aaa.demo.anno.Column;
import com.aaa.demo.anno.Table;
import com.aaa.demo.dao.PublicDao;
import java.lang.reflect.Field;
import java.sql.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* @FileName: PublicDaoImpl
* @Description:
* @Author: zhz
* @CreateTime: 2024/11/21 11:13
* @Version: 1.0.0
*/
public class PublicDaoImpl implements PublicDao {
//定义常量 不再发生改变
private static final String DRIVER_CLASS = "com.mysql.cj.jdbc.Driver";
private static final String URL = "jdbc:mysql://localhost:3306/db_qy178?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimeZone=Asia/Shanghai&allowPublicKeyRetrieval=true";
private static final String USER_NAME = "root";
private static final String PASSWORD = "root";
/**
* 封装获取Connection方法
* @return
*/
public static Connection getMyConnection() {
try {
//加载驱动
Class.forName(DRIVER_CLASS);
//获取Connection并返回
return DriverManager.getConnection(URL, USER_NAME, PASSWORD);
} catch (Exception e) {
e.printStackTrace();
}
//有任何异常,返回空
return null;
}
/**
* 统一关闭资源封装方法
* 后打开的先关闭 ,每个都处理异常,上面的关闭失败不影响下面关闭
* @param connection
* @param statement
* @param resultSet
*/
public static void closeAll(Connection connection, Statement statement, ResultSet resultSet){
try {
if(resultSet!=null){
resultSet.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
try {
if(statement!=null){
statement.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
try {
if(connection!=null){
connection.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
@Override
public <T> List<T> executeQuery(T t) {
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
try {
//假如要查询全部数据 根据传入的t对象(dept) 使用反射拿到库名,表名 就可以拼接查询全部的语句
//获取t的class对象 (例如 dept的class对象)
Class<?> clazz = t.getClass();
//判断是否含有@Table注解
if(clazz.isAnnotationPresent(Table.class)){
//获取注解对象
Table table = clazz.getAnnotation(Table.class);
//获取库名和表名
String dbName = table.dbName();
String tableName = table.tableName();
//拼接sql语句
String sql = "select * from "+dbName+"."+tableName+" where 1=1 ";
//判断传入的对象t的属性是否有值,如果有值,就拼接where条件
StringBuilder executeSql = new StringBuilder(sql);
//获取t的所有属性 //deptNo deptName loc
Field[] declaredFields = clazz.getDeclaredFields();
//循环
for (Field declaredField : declaredFields) {
//定义列名称
String columnName = "";
//判断属性是否含有@Column注解
if(declaredField.isAnnotationPresent(Column.class)){
//获取注解对象
Column column = declaredField.getAnnotation(Column.class);
//获取注解对象中的columnName
columnName = column.columnName();
}
//让私有属性可以访问
declaredField.setAccessible(true);
//获取属性值
Object fieldValue = declaredField.get(t);
//判断是否有值
if(fieldValue!=null){
//select * from db_qy178.tb_dept where 1=1
//判断fieldValue是什么类型
if(fieldValue instanceof Integer){ //判断是否是整数类型
//拼接where条件
executeSql.append(" and "+columnName+" = "+fieldValue);
}else if (fieldValue instanceof String){//判断是否是字符串类型
String s = fieldValue.toString();
//判断字符串是否为空,如果为空,就忽略 不拼接 如果不空,就判断字符串中是否含有逗号
if (s.length()>0){
if(s.contains(",")) {
//拼接开始括号
executeSql.append(" and (");
//分割字符串
String[] sArray = s.split(",");
//循环拼接
for (String s1 : sArray) {
executeSql.append(" "+columnName + " like '%" + s1 + "%' or");
}
//从字符串开始截取到长度-2
String substring = executeSql.substring(0, executeSql.length() - 2);
//重新拼接
executeSql = new StringBuilder(substring);
executeSql.append(")");
}else {
executeSql.append(" and "+columnName+" like '%"+fieldValue+"%'");
}
}
}/*else if (fieldValue instanceof Double){//判断是否是浮点类型
}else if (fieldValue instanceof Date){
}*/
}
}
//拼接完了sql 执行sql
System.out.println("要执行的sql为:"+executeSql);
//获取Connection
connection = getMyConnection();
//获取执行sql对象
preparedStatement = connection.prepareStatement(executeSql.toString());
//执行sql
resultSet = preparedStatement.executeQuery();
//获取元数据信息
ResultSetMetaData metaData = preparedStatement.getMetaData();
//获取列数
int columnCount = metaData.getColumnCount();
//定义返回结果
List<T> tList =new ArrayList<>();
//定义泛型对象
T t1 = null;
//遍历结果
while (resultSet.next()){
//实例化一个新的
t1 = (T) clazz.newInstance();
for (int i = 1; i <= columnCount; i++) {
//获取列名 select dept_no,dept_name,loc from tb_dept
String columnName = metaData.getColumnName(i);
//获取属性名 dept_no->deptNo
String fieldName = stringFirstLetterToUpperCase(columnName);
//获取列对象
Field declaredField = clazz.getDeclaredField(fieldName);
//让私有属性可以访问
declaredField.setAccessible(true);
//反射给列赋值
declaredField.set(t1,resultSet.getObject(columnName));
}
//添加到集合
tList.add(t1);
}
return tList;
}
} catch (Exception e) {
e.printStackTrace();
}finally {
closeAll(connection,preparedStatement,resultSet);
}
return null;
}
/**
* 字符串转换
* @param columnName user_name_aaa_bbb
* @return userNameAaaBbb
*/
public static String stringFirstLetterToUpperCase(String columnName) {
//判断columnName是否含有_
//没有直接返回
if(!columnName.contains("_")){
return columnName;
}
//存在就转换 user_name_aaa_bbb=["user","name","aaa","bbb"]
String[] columnNameArray = columnName.split("_");
//拼接字符串 stringBuilder="user"
StringBuilder stringBuilder =new StringBuilder(columnNameArray[0]);
for (int i = 1; i < columnNameArray.length; i++) {
//第1次 columnNameArray[1]=name
//第2次 columnNameArray[2]=aaa
//第3次 columnNameArray[2]=bbb
//...
String newString = columnNameArray[i].substring(0,1).toUpperCase()+columnNameArray[i].substring(1);
stringBuilder.append(newString);
}
return stringBuilder.toString();
}
public static void main(String[] args) {
String executeSql="select * from tb_dept where 1=1 and ( dept_name like '%开%' or dept_name like '%部%' or";
String substring = executeSql.substring(0,executeSql.length() - 2);
System.out.println(substring);
}
}
测试
package com.aaa.demo.test;
import com.aaa.demo.dao.PublicDao;
import com.aaa.demo.dao.impl.PublicDaoImpl;
import com.aaa.demo.entity.Dept;
import java.util.List;
/**
* @FileName: PublicDaoTest
* @Description:
* @Author: zhz
* @CreateTime: 2024/11/21 12:00
* @Version: 1.0.0
*/
public class PublicDaoTest {
public static void main(String[] args) {
//实例化dao
PublicDao publicDao =new PublicDaoImpl();
//实例化参数
Dept dept =new Dept();
//dept.setDeptNo(11);
//dept.setDeptName("开,部");
dept.setDeptName("开");
//执行
List<Dept> deptList = publicDao.executeQuery(dept);
System.out.println(deptList);
}
}
浙公网安备 33010602011771号