java注解和泛型

注解和泛型

            面试题
               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 自动打印日志
思路分析:
85bb1f3525204eb6aad74ec280e86b92.png

 

日志注解:
@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版权协议,转载请附上原文出处链接和本声明。