注解和泛型
面试题
1、注解是什么?
2、如何自定义注解?
3、java中的泛型是什么?有什么好处?
4、List<? extends T>和List <? super T>之间有什么区别?
5、如何编写一个泛型方法,让它能接受泛型参数并返回泛型类型?
学习目标
1、注解(注释):Annotation
2、泛型
泛型集合
泛型类,泛型接口,泛型方法
通配符:?
泛型擦除
一、 Annotation
1.1 什么是注解 ?
Java 注解(Annotation)又称 Java 标注,是 JDK5.0 引入的一种注释机制。
Java 语言中的类、方法、变量、参数和包等都可以被标注。Java标注可以通过 反射获取标注内容。在编译器生成类文件时,标注可以被嵌入到字节码中。
Java 虚拟机可以保留标注内容,在运行时可以获取到标注内容 。
Java 注解用于为 Java 代码提供元数据。作为元数据,注解不直接影响你的代码执行,但也有一些类型的注解实际上可以用于这一目的。
常见注解
@WebServlet @WebListener @WebFilter: servlet规范中的三大组件
@Override @Controller
解释:注释(说明,标签),不是单行注释,多行注释; 是让编译器, JVM, 通过反射去分析的注释;
1.2 注解的定义
注解通过 @interface 关键字进行定义。
public @interface TestAnnotation {
}它的形式跟接口很类似,不过前面多了一个 @ 符号。上面的代码就创建了一个名字为 TestAnnotaion 的注解。
1.3 注解分类
注解主要分为:
内置注解
元注解
自定义注解
1.3.1 内置注解
Java目前内置了三种注解:
@Override:在编译期检查方法是否符合重写的语法
@Deprecated:标注已过时
@SupressWarnings:抑制编译器警告
/**
* 注解是添加在类/方法/属性...以@符号开头,在编译时,运行时起到不同得作用。
*/
@SuppressWarnings("unused")
public class ChildDemo implements SuperDemo {
// 弃用,过时,声明方法/属性已经过时,不推荐使用,但是可以正常使用
@Deprecated
String a = "a";
// 抑制警告信息,取消警告提示,unchecked不检查,unuserd未使用,all所有
@SuppressWarnings("all")
public void m1(){
int i = 1/0;
}
@Deprecated
// 重写,表明当前得方法是重写得父类/接口中得方法,区分私有得方法
@Override
public int add() {
return 0;
}
public void m2(){
Date date = new Date();
int date1 = date.getDate();
}
}
1.3.2 元注解
用来声明(创建)的注解的一种注解
名称 | 说明 |
@Target | 明确注解在哪里使用(类,方法、属性、接口、局部变量) |
@Retention | 标识:注解的保留期 |
@Documented | 保存在javadoc中 |
@Inherited | 允许注解继承注解 |
@Retention:注解的保留位置
该阶段的注解,主要为了约定程序的规范,程序异常(编译时异常/运行时异常)及限制程序的
@Retention(RetentionPolicy.SOURCE) //注解仅存在于源码中,在class字节码文件中不包含
//比如@Override, @SuppressWarnings
//@Data 自动生成get set
/*<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.4</version>
<scope>provided</scope>
</dependency>*/
@Retention(RetentionPolicy.CLASS) // 默认的保留策略,注解会在class字节码文件中存在,但运行
时无法获得,
@Retention(RetentionPolicy.RUNTIME) // 注解会在class字节码文件中存在,在运行时可以通过反
射获取到
@Target:注解的作用目标
@Target(ElementType.TYPE) //接口、类、枚举
@Target(ElementType.FIELD) //字段、枚举的常量
@Target(ElementType.METHOD) //方法
@Target(ElementType.PARAMETER) //方法参数
@Target(ElementType.CONSTRUCTOR) //构造函数
@Target(ElementType.LOCAL_VARIABLE)//局部变量
@Target(ElementType.ANNOTATION_TYPE)//注解
@Target(ElementType.PACKAGE) ///包
@Document:说明该注解将被包含在javadoc中
@Inherited:说明子类可以继承父类中的该注解ElementType
枚举类型,封装的是一些特定的值,可读性强
public enum ElementType {
/** Class, interface (including annotation type), or enum declaration */
TYPE,
/** Field declaration (includes enum constants) */
FIELD,
/** Method declaration */
METHOD,
/** Formal parameter declaration */
PARAMETER,
/** Constructor declaration */
CONSTRUCTOR,
/** Local variable declaration 局部变量 */
LOCAL_VARIABLE,
/** Annotation type declaration 注解 */
ANNOTATION_TYPE,
/** Package declaration */
PACKAGE,
/**
* Type parameter declaration
*
* @since 1.8 java元注解
*/
TYPE_PARAMETER,
/**
* Use of a type
*
* @since 1.8
*/
TYPE_USE
}RetentionPolicy
.java文件先编译为.class文件,运行时执行.class文件得内容,注解有效期
public enum RetentionPolicy {
/**
* Annotations are to be discarded by the compiler.
源码阶段保留,会被编译器识别,不会保留在class文件中;编译期间起作用
*/
SOURCE,
/**
* Annotations are to be recorded in the class file by the compiler
* but need not be retained by the VM at run time. This is the default
* * behavior.
* 会保留到class文件中,不会被jvm识别(运行期间无法获取)(默认)
*/
*CLASS,
/**
* Annotations are to be recorded in the class file by the compiler and
* retained by the VM at run time, so they may be read reflectively.
* 在运行期间保留,可以通过反射去获取分析
* @see java.lang.reflect.AnnotatedElement
*/
RUNTIME
}1.3.3 自定义注解
创建
//标注该注解可以用在哪里(目标)
@Target(value={ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
String value() ;
int test();
int[] types();
}使用:
@MyAnnotation(value="test",test=1,types = {1,2,3})
public class Test {
}1.4 注解处理
单纯说注解,注解本身没有任何的作用。简单说和注释没啥区别,而它有作用的原因是: 注解解释类,也就是相关
对代码进行解释的特定类。一般这些类使用反射是可以拿到的。
因此,通过注解和反射这两者的结合使用,是可以做到很多功能的。
1.4.2 ORM 实现
自定义注解:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Table {
String name() default "";
}实体类使用注解:
@Table
public class Emp {
private Integer id;
private String name;
......
}注解解释类:
public class MyORM {
//实现查询数据表的功能 一个项目有30张数据表 30个
//写一个公共的方法实现对所有不同表的查询功能
//参数为不同表对应实体类的class实例
public static <T> List<T> queryAll(Class<T> clazz){
String sql ="";
//此时的 A.isAnnotationPresent(B.class);意思就是:注释B是否在此A上。如果在则返回true;
// 不在则返回false。
if(clazz.isAnnotationPresent(Table.class)){
Table annotation = clazz.getAnnotation(Table.class);
String tableName = annotation.name();
if(tableName.equals("")){
tableName = clazz.getSimpleName();//Emp emp
System.out.println(tableName);
}
sql = "select * from "+tableName;
}
System.out.println(sql);
return null;
}
}调用:
public static void main(String[] args) {
List<Emp> emps = MyORM.queryAll(Emp.class);
}1.4.2 自动打印日志
思路分析:

日志注解:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface LogAnocation {
}实验类:
@Service
@LogAnocation
public class EmpService {
public int add(int a,int b){
return 1;
}
public List select(){
return null;
}
}使用AOP完成注解分析类
@Component
@Aspect
public class LoggingAspect {
@Before("within(demo03.service.*)")
public void log(JoinPoint joinPoint) {
Signature signature = joinPoint.getSignature();
Class<?> targetClass = joinPoint.getTarget().getClass();
if (targetClass.isAnnotationPresent(LogAnocation.class)) {
System.out.println(new Date() + ":调用" + targetClass.getName() + "." + signature.getName());
Object[] args = joinPoint.getArgs();
System.out.println("\tparams:"+Arrays.toString(args));
}
}
}测试类:
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new
ClassPathXmlApplicationContext("classpath:applicationContext.xml");
EmpService empService = context.getBean(EmpService.class);
empService.add(1,2);
empService.select();
}完整示例:
实体类
import lombok.Builder;
import lombok.Data;
/*
@Data:注解在类上,将类提供的所有属性都添加get、set方法,并添加、equals、canEquals、hashCode、toString方法
@Setter:注解在类上,为所有属性添加set方法、注解在属性上为该属性提供set方法
@Getter:注解在类上,为所有的属性添加get方法、注解在属性上为该属性提供get方法
@NotNull:在参数中使用时,如果调用时传了null值,就会抛出空指针异常
@Synchronized 用于方法,可以锁定指定的对象,如果不指定,则默认创建一个对象锁定
@Log作用于类,创建一个log属性
@Builder:使用builder模式创建对象
@NoArgsConstructor:创建一个无参构造函数
@AllArgsConstructor:创建一个全参构造函数
@ToStirng:创建一个toString方法
@Accessors(chain = true)使用链式设置属性,set方法返回的是this对象。
@RequiredArgsConstructor:创建对象
@UtilityClass:工具类
@ExtensionMethod:设置父类
@FieldDefaults:设置属性的使用范围,如private、public等,也可以设置属性是否被final修饰。
@Cleanup: 关闭流、连接点。
@EqualsAndHashCode:重写equals和hashcode方法。
@toString:创建toString方法。
*/
@Data
@Builder
// 为Person类配置了刚刚定义的注解@Info
@Info(isDelete = true)
public class Person {
/**
* 姓名
*/
private String name;
/**
* 年龄
*/
private int age;
/**
* 是否有效
*/
private boolean isDelete;
}/*
注解是一种能被添加到java源代码中的元数据,方法、类、参数和包都可以用注解来修饰。
注解可以看作是一种特殊的标记,可以用在方法、类、参数和包上,
程序在编译或者运行时可以检测到这些标记而进行一些特殊的处理。
声明一个注解要用到的东西
修饰符
访问修饰符必须为public,不写默认为pubic;
关键字
关键字为@interface;
注解名称
注解名称为自定义注解的名称,使用时还会用到;
注解类型元素
注解类型元素是注解中内容,可以理解成自定义接口的实现部分;
使用元注解修饰注解:
JDK中有一些元注解,主要有@Target,@Retention,@Document,
@Inherited用来修饰注解。
@Target: 表明该注解可以应用的java元素类型
Target类型 描述
ElementType.TYPE 应用于类、接口(包括注解类型)、枚举
ElementType.FIELD 应用于属性(包括枚举中的常量)
ElementType.METHOD 应用于方法
ElementType.PARAMETER 应用于方法的形参
ElementType.CONSTRUCTOR 应用于构造函数
ElementType.LOCAL_VARIABLE 应用于局部变量
ElementType.ANNOTATION_TYPE 应用于注解类型
ElementType.PACKAGE 应用于包
ElementType.TYPE_PARAMETER 1.8版本新增,应用于类型变量)
ElementType.TYPE_USE 1.8版本新增,应用于任何使用类型的语句中(例如声明语句、泛型和强制转换语句中的类型)
@Retention:表明该注解的生命周期
生命周期类型 描述
RetentionPolicy.SOURCE 编译时被丢弃,不包含在类文件中
RetentionPolicy.CLASS JVM加载时被丢弃,包含在类文件中,默认值
RetentionPolicy.RUNTIME 由JVM 加载,包含在类文件中,在运行时可以被获取到
*/
/*
@Document
表明该注解标记的元素可以被Javadoc 或类似的工具文档化
@Inherited
表明使用了@Inherited注解的注解,所标记的类的子类也会拥有这个注解
*/
import java.lang.annotation.*;
@Target({ElementType.FIELD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Info {
String value() default "tracy";
boolean isDelete();
}测试类
/*
对于一个类或者接口来说,Class类(java.lang包下)中提供了一些方法用于反射注解,
当然对于字段、方法来说反射注解的方式很类似。
//返回指定的注解
getAnnotation
//判断当前元素是否被指定注解修饰
isAnnotationPresent
//返回所有的注解
getAnnotation s
*/
public class AnnotationTest {
public static void main(String[] args) {
try {
//获取Person的Class对象
Person person = Person.builder().build();
Class clazz = person.getClass();
//判断person对象上是否有Info注解
if (clazz.isAnnotationPresent(Info.class)) {
System.out.println("Person类上配置了Info注解!");
//获取该对象上Info类型的注解
Info infoAnno = (Info) clazz.getAnnotation(Info.class);
System.out.println("person.name :" + infoAnno.value() + ",person.isDelete:" + infoAnno.isDelete());
} else {
System.out.println("Person类上没有配置Info注解!");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
二、泛型
2.1 泛型简介
集合中的泛型:
List<String> list = new ArrayList<>();
泛型定义:
参数化的类型,将数据类型当成参数来使用,对类型进行约束(限制),在 编译期起作用;
优点:
1、提高效率: 限定数据类型,只存某一种特定的类型,减少类型转化的时间(其他类型--->object--->其他类型)
2、防止类型转换出现问题
推荐使用各种泛型接口,类
常用的 类型占位符:T E K V: 代表一种类型
2.2 泛型接口、泛型类
PageBean pb=new PageBean();
public class PageBean<T> {
private String name;
private List <T> resultLists;//存储每张表查询出来的分页数据集合
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public T getT() {
return t;
}
public void setT(T t) {
this.t = t;
}
public void show(Class<T> clz){
// clz.getDeclaredFields();
// clz.getDeclaredFields();
}
}
public class Test2 {
public static void main(String[] args) {
// 如果不指定类型,默认是Object类型
MyGeneric generic=new MyGeneric();
generic.setT("aa");
System.out.println(generic.getT());
MyGeneric<String> generic1=new MyGeneric<>();
generic1.setT("中国越来越强大");
System.out.println(generic1.getT());
}
}
2.3 泛型方法
// 在返回值类型前面:<类型占位符> ,定义类型的形参;方法中可以使用E当成一种数据类型来使用
public <E> E query(Class<E> clz) throws NoSuchMethodException,
IllegalAccessException, InvocationTargetException, InstantiationException {
// 获取构造方法,通过构造获取该类型的对象
E object= clz.getConstructor().newInstance();
// 获取所有的字段
Field[] fields = clz.getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
Field field = fields[i];
// 允许访问
field.setAccessible(true);
if(field.getName().equals("name")){
field.set(object,"张三"+Math.random());
}else if(field.getName().equals("age")){
field.set(object,18);
}
}
return object;
}
示例:
public class Test2 {
public static void main(String[] args) {
// 如果不指定类型,默认是Object类型
MyGeneric generic=new MyGeneric();
generic.setT("aa");
System.out.println(generic.getT());
MyGeneric<String> generic1=new MyGeneric<>();
generic1.setT("中国越来越强大");
System.out.println(generic1.getT());
try {
Emp emp = generic1.query(Emp.class);
System.out.println(emp);
Student student = generic1.query(Student.class);
System.out.println(student);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
}
}
2.4 泛型通配符
通配符:<?>: 真实的数据类型,泛指所有类型,不同于类型占位符
@CallerSensitive
public static Class<?> forName(String className)throws ClassNotFoundException {
Class<?> caller = Reflection.getCallerClass();
return forName0(className, true, ClassLoader.getClassLoader(caller), caller);
}通配符上限:<? extends T>: 限定的类型只能是T类型或者是T类型的子类型
// 限定:只能传进来 Number 集合 ,或者Number子类型的集合
public static void test6(List<? extends Number> list){
for (Number number : list) {
System.out.println(number);
}
}
通配符下限:<? super T>:限定的类型只能是T类型或者是T类型的父类型
示例:
public class Test3 {
public static void main(String[] args) {
test(Emp.class);
test(Student.class);
List<Emp> list1=new ArrayList<>();
List<Student> list2=new ArrayList<>();
List<String> list3=new ArrayList<>();
test2(list1);
test2(list2);
test2(list3);
List<Number> numbers=new ArrayList<>();
List<Integer> integers=new ArrayList<>();
test3(numbers);
test4(integers);
//
// test3(integers);
test6(numbers);
test6(integers);
Emp emp=new Emp();
test5(emp);
}
public static void test(Class<?> clz){
}
public static void test2(List<?> list){
for (Object o : list) {
System.out.println(o);
}
}
// Integer 继承自 Number 类型
public static void test3(List<Number> list){
for (Object o : list) {
System.out.println(o);
}
}
public static void test4(List<Integer> list){
for (Object o : list) {
System.out.println(o);
}
}
// 限定:只能传进来 Number 集合 ,或者Number子类型的集合
public static void test6(List<? extends Number> list){
for (Number number : list) {
System.out.println(number);
}
}
// 需要使用父类型的地方可以传进来子类型的实例,任何时候子类型都可以替换父类型
public static void test5(Person person){
System.out.println(person);
}
}
2.5 泛型擦除
泛型擦除:在编译泛型的时候,会将: 去掉,字节码种存储的泛型实际上是一种类型。
public class Test4 {
public static void main(String[] args) {
List<String> list0=show();
List list=show();
// 本质上是一种类型
System.out.println(list0.getClass()==list.getClass());
}
public static List show(){
List<String> list=new ArrayList<>();
return list;
}
}通过反射向泛型集合中存储任意类型的数据
最后附上一个泛型的完整案例
通过泛型封装一个简单的JDBC链接工具
package com.aaa.Reflect_Two_day;
import com.aaa.Reflect_Two.Goods_info;
import com.aaa.Reflect_Two.Type_info;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
public class BaseDao {
//jdbc连接数据的工具类
private static String driver="com.mysql.jdbc.Driver";
private static String url="jdbc:mysql://localhost:3306/goods?useSSL=false";
private static String userName="root";
private static String psdw="lian211314";
//数据库连接的获取方法
private static Connection getConn()
{
Connection conn = null;
try {
//第一步:加载驱动
Class.forName(driver);
//第二部:创建数据库连接对象
conn = DriverManager.getConnection(url,userName,psdw);
} catch (Exception e) {
e.printStackTrace();
}
return conn;
}
/**
* 增删改
*
* @param sql
* 执行sql语句
* @return
*/
public static int update(String sql, Object... objs) {
Connection conn = null;
PreparedStatement ptm = null;
int rs = 0;
try {
conn = getConn();
ptm = conn.prepareStatement(sql);
setParams(ptm, objs);
rs = ptm.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
} finally {
closeAll(null, ptm, conn);
}
return rs;
}
// 5.参数设置
private static void setParams(PreparedStatement ptm, Object... objs) {
if (null != objs) {
for (int i = 0; i < objs.length; i++) {
try {
ptm.setObject(i + 1, objs[i]);
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
//查询方法
public static <T> List<T> queryList(String sql, T t, Object ... objs)
{
//Class<? extends Object>:传递的对象可以是任何类型
Class <? extends Object > tClass = t.getClass();//getClass得到实体类对象的class实例
Connection conn = null;
PreparedStatement psmt=null;
ResultSet rs = null;
//使用泛型加上占位符(<T>)
List<T> list = new ArrayList<>();//存储查询结果集的集合
try {
conn =getConn();//连接数据库对象
psmt = conn.prepareStatement(sql);//执行sql
//如果执行对象不为空的话
if (null!=psmt&&null!=objs)
{
//循环遍历执行对象(sql)
for (int i = 0;i<objs.length;i++)
{
psmt.setObject(i+1,objs[i]);
}
}
// 获取查询结果
rs = psmt.executeQuery();
// 获取结果集结构(列的结构)
ResultSetMetaData metaData = rs.getMetaData();
// 获取结果集列数
int count = metaData.getColumnCount();// 获取所有列的个数,即所有字段的总个数
// 循环获取每一行
while (rs.next())
{
//封装每条数据对象,强转泛型。
// 并且newInstance()创建对象t1
T t1 = (T) tClass.newInstance();//利用class实例创建当前类的对象(newInstance) new Book
//循环获取当前每一列的值
for (int i = 0 ; i<count;i++)
{
//metaData.getColumnName(i+1)得到本列的字段名称的
String fieldName = metaData.getColumnName(i+1);
//每一行中的某一列(单个属性成员)
Field fi = tClass.getDeclaredField(fieldName);//获取指定字段属性的值
//利用getMethod得到里边的对应方法的对象,getSetter(fieldName)动态获取该属性对应的方法名字
//tClass.getMethod:得到指定名字的方法对象
Method method = tClass.getMethod(getSetter(fieldName),fi.getType());
method.invoke(t1,rs.getObject(i+1));//利用反射执行该方法
}
//将上边封装好的每条数据对象添加到最后的结果集里
list.add(t1);
}
} catch (Exception e) {
e.printStackTrace();
}finally {
closeAll(rs,psmt,conn);
}
//把查询到的结果集返回出去
return list;
}
//拼接设置该属性值的set方法的方法名字
public static String getSetter(String fieldName)
{
//查询到的数据的各个字段
return "set"+fieldName.substring(0,1).toUpperCase()+fieldName.substring(1);
}
//关闭数据库多个对象的方法
private static void closeAll(ResultSet rs , PreparedStatement pstmt,Connection conn) {
try {
if (rs!=null)
{
rs.close();
}
if (null!=pstmt)
{
pstmt.close();
}
if (conn!=null)
{
conn.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
String sql = "select * from goods_info ";
List<Goods_info> list= BaseDao.queryList(sql,new Goods_info());
for (Goods_info s : list)
{
System.out.println(s);
s.getGoods_name();
System.out.println(s.getGoods_name());
s.setGoods_id(1);
}
String sql2 ="insert into goods_info (goods_name,type_id,goods_spec,goods_price,goods_date ) values (1,1,1,1,'2012-12-12')";
BaseDao.update(sql2);
System.out.println("==========================");
String sql3 = "select * from type_info ";
List<Type_info> list3= BaseDao.queryList(sql3,new Type_info());
System.out.println(list3);
List<Type_info>list1 = new ArrayList<>();
list1.add(new Type_info());
List<Goods_info>list2 = new ArrayList<>();
list2.add(new Goods_info());
// BaseDao.queryList(sql,list1);
// System.out.println();
}
}
实体类
package com.aaa.comment;
import com.aaa.Reflect_Two.Type_info;
import java.util.Date;
@TableAnnotion(tName = "goods_info")
public class Goods_In extends Type_info {
private Integer goods_id;
private String goods_name;
private Integer type_id;
private String goods_spec;
private Double goods_price;
private Date goods_date;
public Goods_In() {
}
public Goods_In(Integer goods_id, String goods_name, Integer type_id, String goods_spec, Double goods_price, Date goods_date) {
this.goods_id = goods_id;
this.goods_name = goods_name;
this.type_id = type_id;
this.goods_spec = goods_spec;
this.goods_price = goods_price;
this.goods_date = goods_date;
}
public Integer getGoods_id() {
return goods_id;
}
public void setGoods_id(Integer goods_id) {
this.goods_id = goods_id;
}
public String getGoods_name() {
return goods_name;
}
public void setGoods_name(String goods_name) {
this.goods_name = goods_name;
}
public Integer getType_id() {
return type_id;
}
public void setType_id(Integer type_id) {
this.type_id = type_id;
}
public String getGoods_spec() {
return goods_spec;
}
public void setGoods_spec(String goods_spec) {
this.goods_spec = goods_spec;
}
public Double getGoods_price() {
return goods_price;
}
public void setGoods_price(Double goods_price) {
this.goods_price = goods_price;
}
public Date getGoods_date() {
return goods_date;
}
public void setGoods_date(Date goods_date) {
this.goods_date = goods_date;
}
@Override
public String toString() {
return "Goods_info{" +
"goods_id=" + goods_id +
", goods_name='" + goods_name + '\'' +
", type_id=" + type_id +
", goods_spec='" + goods_spec + '\'' +
", goods_price=" + goods_price +
", goods_date=" + goods_date +
'}';
}
}
泛型封装类
package com.aaa.utlis;
import com.aaa.Reflect_Two.Goods_info;
import com.aaa.Reflect_Two_day.BaseDao;
import com.aaa.comment.Goods_In;
import com.aaa.comment.TableAnnotion;
import java.util.ArrayList;
import java.util.List;
public class TableJdbc<K> {
//参数为不同表对应实体类的class实例
public static <K>List<K> queryAll(Class<K> kClass)
{
String sql="";
// System.out.println(clazz.isAnnotationPresent(TableAnnotation.class));
//此时的 T.isAnnotationPresent(TableAnnotation.class);意思就是:注释TableAnnotation是否在此T上。如果在则返回true;不在则返回false。
if (kClass.isAnnotationPresent(TableAnnotion.class))
{
TableAnnotion annotion = kClass.getAnnotation(TableAnnotion.class);//得到自定义注解对象TableAnnotation
String tableName = annotion.tName();//得到tName的属性值
if (tableName.equals(""))
{
tableName = kClass.getSimpleName();//得到class实例的类名字
System.out.println(tableName);
}
sql = "select * from "+tableName;
}
// System.out.println(sql);xd
List<Goods_In> list= BaseDao.queryList(sql,new Goods_In());
// List<K> list2= BaseDao.queryList(sql,kClass);
for (Goods_In s : list)
{
System.out.println(s);
// System.out.println(s.getGoods_name());
// s.setGoods_id(1);
}
// System.out.println(list);
// return BaseDao.queryList(sql,<K>);
// return (List<K>) list;
// List list1 = new ArrayList();
// return BaseDao.queryList(sql,(List<K>) list);
return null;
}
public static void main(String[] args) {
TableJdbc.queryAll(Goods_In.class);
// TableJdbc.queryAll(new Goods_In().getClass());
}
}
测试
package com.aaa.Test;
import com.aaa.Reflect_Two_day.BaseDao;
import com.aaa.comment.Goods_In;
import com.aaa.utlis.TableJdbc;
import java.util.List;
public class MyaJbdc<K> {
public static <K> List<K> queryAll(Class<K> kClass) {
String sql = "";
if (kClass.isAnnotationPresent(Mya.class)) {
Mya annotion = kClass.getAnnotation(Mya.class);//得到自定义注解对象TableAnnotation
String tableName = annotion.Mya();
if (tableName.equals("")) {
System.out.println("");
tableName = kClass.getSimpleName();
System.out.println(tableName);
}
sql = "select * from " + tableName;
}
List<Goods_In> list = BaseDao.queryList(sql, new Goods_In());
for (Goods_In a : list) {
System.out.println(a);
System.out.println();
}
return null;
}
public static void main(String[] args) {
TableJdbc.queryAll(Goods_In.class);
}
}总结
以上就是今天要讲的内容,本文仅仅简单介绍了注解和泛型的使用,当然,笔者深度欠缺,如有不足,还请指正。
版权声明:本文为m0_66278959原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。