zoukankan      html  css  js  c++  java
  • java泛型、反射与注解

    通常我们在开发的时候会遇到各种相似的问题,这种问题如果不用一种方法解决的话,会造成代码冗余。

    例如,我们在审批的时候,有些简单的流程只需要改变状态,我们可以有以下方法解决:

    一、泛型类

    public class UpdateEntityUtils<T,V extends IService<T>>{
    
        public T setStatus(V v,String id,String status){
            T t = v.getById(id);
            Class clazz = t.getClass();
            try{
                Method method = clazz.getDeclaredMethod("setStatus",String.class);
                method.setAccessible(true);
                method.invoke(t,status);
                return t;
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }finally {
                return t;
            }
        }
    }

    这种在类名后面加上泛型的就是泛型类,实例化该类时需要传入对应的类型。

    二、泛型方法

    public class UpdateEntityUtils{
    
        public <T,V extends IService<T>> T setStatus(V v,String id,String status){
            T t = v.getById(id);
            Class clazz = t.getClass();
            try{
                Method method = clazz.getDeclaredMethod("setStatus",String.class);
                method.setAccessible(true);
                method.invoke(t,status);
                return t;
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }finally {
                return t;
            }
        }
    }

    这种在方法的返回值前面加上泛型的就是泛型方法,而泛型方法可以传入任何满足的类型。

    三、泛型类和泛型方法的使用区别

    1、IService

    public interface IService<T> {
    
        /**
         * 根据ID返回实体
         * @param id
         * @return
         */
        T getById(String id);
    }

    2、StudentServiceImpl

    public class StudentServiceImpl implements IService<Student> {
        @Override
        public Student getById(String id) {
            Student student = new Student();
            student.setStudentName("student");
            student.setStudentNo("666");
            student.setStatus("studying");
            return student;
        }
    }

    3、TeacherServiceImpl

    public class TeacherServiceImpl implements IService<Teacher> {
        @Override
        public Teacher getById(String id) {
            Teacher teacher = new Teacher();
            teacher.setTeacherName("teacher");
            teacher.setTeacherNo("888");
            teacher.setStatus("teaching");
            return teacher;
        }
    }

    Main(泛型类)

    public class Main {
        public static void main(String[] args) {
            StudentServiceImpl studentService = new StudentServiceImpl();
            TeacherServiceImpl teacherService = new TeacherServiceImpl();
            UpdateEntityUtils<Student,StudentServiceImpl> studentUtils = new UpdateEntityUtils<>();
            studentUtils.setStatus(studentService,"666","playing");
            UpdateEntityUtils<Teacher,TeacherServiceImpl> teacherUtils = new UpdateEntityUtils<>();
            teacherUtils.setStatus(teacherService,"888","playing");
        }
    }

    如果使用泛型类的的话,里面的方法(非泛型方法)对只能对特定的类使用。

    如果要改变不同实体类的状态的话,需要实例话多次。


    Main(泛型方法)

    public class Main {
        public static void main(String[] args) {
            StudentServiceImpl studentService = new StudentServiceImpl();
            TeacherServiceImpl teacherService = new TeacherServiceImpl();
            UpdateEntityUtils updateEntityUtils = new UpdateEntityUtils();
            updateEntityUtils.setStatus(studentService,"666","playing");
            updateEntityUtils.setStatus(teacherService,"888","playing");
        }
    }

    如果使用泛型方法的话,类只需要实例化一次即可,可以通过泛型方法改变不同实体类的状态。

     四、泛型类和泛型方法总结

    泛型类更偏向于对类其中的方法(非泛型方法)做出一种限制,泛型方法则没得这种限制,泛型类中也可以有泛型方法。

    类名后面加上泛型的就是泛型类,方法的返回值前面加上泛型的就是泛型方法。

    五、泛型通配符

    我们在定义泛型类,泛型方法时会碰见很多不同的通配符,如 T,E,K,V 等等。

    本质上这些个都是通配符,没啥区别,只不过是编码时的一种约定俗成的东西。

    比如上述代码中的 T ,我们可以换成 A-Z 之间的任何一个 字母都可以,并不会影响程序的正常运行。

    泛型通配符可分为两类,上界通配符和下界通配符:

    上界通配符:用 extends 关键字声明,表示参数化的类型可能是所指定的类型,或者是此类型的子类。

    下界通配符:用 super 进行声明,表示参数化的类型可能是所指定的类型,或者是此类型的父类型。

    六、?和T的区别

    比如上面的例子,我们使用了 <T,V extends IService<T>>,然后通过V调用了getById方法。

    而如果我们使用<T,? extends IService<T>>,实际上这是行不通的,因为不能 ? 一个变量出来。

    T表示一种确定的类型,而?表示不在意该类型是什么,也不会用到它。

    7、Class<?>和Class<T>的区别

    如果不是在抽象类里面,Class<T> tClass会报错,但是Class<?> aClass 不会。

    因为T代表一种类型,而?可以代表任何类型,另外Class是一个泛型类,但是他的构造方法都是私有的。

    八、反射

    在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;

    对于任意一个对象,都能够调用它的任意一个方法和属性。

    九、注解概念

     我们在日常开发中,经常会用到各种注解,可能我们已经习以为常了,但是你是否注意到它是如何生效的呢。

    Ⅰ、注解的格式

    public @interface AnnotationName {
        //属性列表
        public String name();
        public String code();
        public String msg();
    }

    Ⅱ、注解能使用的类型

    ①、八大基本数据类型(boolean,byte,char,short,int,long,float,double)

    ②、String

    ③、String和八大基本类型的一维数组

    ④、Class

    ⑤、枚举

    ⑥、其他的注解

    Ⅲ、注解的分类

    注解大致可分为三类:自定义注解、JDK内置注解、第三方框架提供的注解。

    要想注解起作用必然有三步曲:定义注解,使用注解,然后读取注解。

    通常我们在使用第三方框架提供的注解时,往往只能看到前两步,却不知道它在哪儿读取注解。

    每个注解都像是一个标签,贴在类、方法上或者字段上,以表示它的特征。

    十、总结

    许多优秀的框架都是泛型、反射和注解一起使用的,它们封装好我们就可以使用了。

    他们编写的注解解析器我们通常看不到,但是一定是存在的,因为看不到,所以我们用起来会感觉很美观。

    他们和我们编写的注解解析器其实差不多,只是我们编写的代码少,可以很快追溯到根源。

    反正我们记住要使注解起作用,必然存在注解解析器。

  • 相关阅读:
    Java经典逻辑编程50题 (转)
    Programmingbydoing
    前端测试框架jest 简介
    puppeteer入门
    面向对象编程
    Java常识
    JS 变量
    jmeter 压力测试
    jmeter 安装
    Java 数据驱动测试
  • 原文地址:https://www.cnblogs.com/M-Anonymous/p/14599551.html
Copyright © 2011-2022 走看看