Administrator
发布于 2023-02-10 / 11 阅读
0
0

Java入门(十四)——注解和反射

注解概念

注解又叫 Java 标注,是 JDK5.0 引入的一种注释机制。注解是元数据的一种形式,提供有关于程序但不属于程序本身的数据。注解对它们注解的代码的操作没有直接影响。

Annotation的作用

  • 不是程序本身 , 可以对程序作出解释.(这一点和注释(comment)没什么区别)
  • 可以被其他程序(比如:编译器等)读取

Annotation的格式

  • 注解是以"@注释名"在代码中存在的
  • 还可以添加一些参数值 , 例如:@SuppressWarnings(value="unchecked")

Annotation在哪里使用?

  • 可以附加在package , class , method , fifield 等上面 , 相当于给他们添加了额外的辅助信息
  • 我们可以通过反射机制实现对这些元数据的访问

3种注解

内置注解

java自己定义的注解

  • @Override: 检查该方法是否重写,如果父类没有该方法,报错。

  • @Deprecated: 标记已过时,不推荐使用的方法。(例 functionName)。java中经常有一些方法,当你输入时,会出现类似的模式,是告诉你已过时了,不推荐使用。你自己也可以定义已过时的方法。

  • @SuppressWarnings:让编译器去忽略注解中声明的警告。比如去忽略已过时方法警告。

元注解

注解其他注解

  • @Target:用于描述注解可以用在哪些地方。Target内部的值使用枚举ElementType表示。(例如{ElementType.FIELD, ElementType.LOCAL_VARIABLE, ElementType.METHOD} 用在属性,本地变量,方法上)。
  • @Retention:表示我们的注解在什么地方有效。在什么地方可以通过反射去使用。value可以为SOURCE < CLASS < RUNTIME。如果设置的为RUNTIME,那么它在SOURCE和CLASS也是有效的。
  • @Documented: 表示是否将我们的注解包含在javadoc中。
  • @Inherited:说明子类可以继承父类中的该注解。
  • @SafeVarargs:用在参数长度可变的方法或构造方法上,方法必须声明为static或final。也是抑制警告,比Retention更具体。
  • @FunctionalInterface: 标识一个匿名函数或函数式接口。java不会强求你去使用它来标记你的接口是函数式或者是匿名函数,是一个设计上的考虑,可以让用户明显知道这是一个函数式接口或匿名函数。
  • @Repeatable:标注一个注解可以在同一个地方使用多次。

自定义注解

使用@interface自定义注解

public class Test {

    @myAnnotation(name="matao")
    @myAnnotation2("test")
    public static void test(){

    }
}

@Target({ElementType.METHOD, ElementType.TYPE}) //可以使用在类或者方法上
@Retention(RetentionPolicy.RUNTIME) //在运行时有效
@interface myAnnotation{
    String name() default "MAa";  //可以填写默认值,当不赋值的时候,就为默认值
    int age() default 0;
    int id() default -1;
    String[] schools() default {"shanxidaxue","fsu"};
}

//如果@interface里只有一个值value,在用的时候可以不写value

@Target({ElementType.METHOD, ElementType.TYPE})   
@Retention(RetentionPolicy.RUNTIME) 
@interface myAnnotation2{
    String value();
}

反射(Reflection)

概念:是指计算机程序在运行时(runtime)可以访问、检测和修改它本身状态或行为的一种能力。用比喻来说,反射就是程序在运行的时候能够“观察”并且修改自己的行为。

因为我们不知道初始化类的对象是什么,无法用new来创建对象,可以通过反射去获得类的内部信息。(反编译)

Java 反射机制主要提供了以下功能:

  • 在运行时构造任意一个类的对象
  • 在运行时获取或者修改任意一个类所具有的成员变量和方法
  • 在运行时调用任意一个对象的方法或属性

java反射的知识点

反射框架

java反射核心技术框架

Class

反射基于 Class, Class 是一个类,封装了当前对象所对应的类的信息。一个类有属性,方法,构造器等,比如说有一个 Person 类,一个 Order 类,一个 Book 类,这些都是不同的类,现在需要一个类,用来描述类,这就是 Class,它应该有类名,属性,方法,构造器等。Class 是用来描述类的类。

对于每个类,都有一个不变的 Class 类型的对象,一个 Class 对象包含了特定某个类的有关信息。一个类(不是一个对象) 在 JVM 中只会有一个 Class 实例。

获取 Class 对象的三种方式

  • 通过类名获取
  • 通过对象获取
  • 通过全类名获取

常用方法

主要涉及类

反射技术的核心技术是Class对象,每个类在定义以后都有各自的Class对象

java反射的主要的类

反射操作泛型

  • Java采用泛型擦除的机制来引入泛型 , Java中的泛型仅仅是给编译器javac使用的,确保数据的安全性
  • 和免去强制类型转换问题 , 但是 , 一旦编译完成 , 所有和泛型有关的类型全部擦除
  • 为了通过反射操作这些类型 , Java新增了 ParameterizedType , GenericArrayType , TypeVariable
  • WildcardType 几种类型来代表不能被归一到Class类中的类型但是又和原始类型齐名的类型.
  • ParameterizedType : 表示一种参数化类型,比如Collection
  • GenericArrayType : 表示一种元素类型是参数化类型或者类型变量的数组类型
  • TypeVariable : 是各种类型变量的公共父接口
  • WildcardType : 代表一种通配符类型表达式

代码示例

public class Test07 {
    public void test01(Map<String, User> map, List<User> list){
        System.out.println("test01");

    }
    public Map<String, User> test02(){
        System.out.println("test02");
        return null;
    }

    public static void main(String[] args) throws NoSuchMethodException {
        Method m = Test07.class.getMethod("test01", Map.class, List.class);
        Type[] genericParameterTypes = m.getGenericParameterTypes();  //获得泛型的参数类型
        for (Type genericParameterType : genericParameterTypes) {
            System.out.println(genericParameterType);
            if(genericParameterType instanceof ParameterizedType) { //想知道里面的类型,先判断是否是结构化参数类型,是就强转出来
                Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments();
                for (Type actualTypeArgument : actualTypeArguments) {
                    System.out.println(actualTypeArgument);
                }
            }
        }

        m = Test07.class.getMethod("test02", null);
        Type genericReturnType = m.getGenericReturnType(); //获取返回值类型
        if (genericReturnType instanceof ParameterizedType) {
            Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments();
            for (Type actualTypeArgument : actualTypeArguments) {
                System.out.println(actualTypeArgument);
            }
        }

    }
}

反射操作注解

主要方法:

  • getAnnotations
  • getAnnotation

代码示例

public class Test06 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
        Class c = Class.forName("com.ma.reflection.Student2");
        //通过反射获得注解
        Annotation[] annotation = c.getAnnotations();
        for (Annotation annotation1 : annotation) {
            System.out.println(annotation1);
        }
        kuangtable annotation1 = (kuangtable) c.getAnnotation(kuangtable.class);
        System.out.println(annotation1.value());//获得注解的value值
        
        //获得指定的注解
        Field field = c.getDeclaredField("name");
        field annotation2 = field.getAnnotation(field.class);
        System.out.println(annotation2.columnName());
        System.out.println(annotation2.type());
        System.out.println(annotation2.length());
    }
}

@kuangtable("db_student")
class Student2{
    public Student2() {
    }

    @field(columnName = "name", type = "varchar", length = 10)
    private String name;
    @field(columnName = "id", type = "int", length = 10)
    private int id;
    @field(columnName = "age", type = "int", length = 10)
    private int age;

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student2{" +
                "name='" + name + '\'' +
                ", id=" + id +
                ", age=" + age +
                '}';
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public Student2(String name, int id, int age) {
        this.name = name;
        this.id = id;
        this.age = age;
    }


}

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface kuangtable{
    String value();
}

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface field{
    String columnName();
    String type();
    int length();
}


评论