注解和反射基础知识和使用方法

注解

注解(Annotation)不是程序本身,可以对程序做出解释(这和注释comment没什么区别)。

注解可以被其他程序读取。

内置注解

@Override  //重写的注解
public String toString(){
    return super.toString();
}

@Deprecated  //不推荐程序员使用,或者存在更好的方式,但是可以使用。
public void test(){
    System.out.println("这段代码不推荐使用");
}

@SuppressWarnings()  //镇压警告,需要参数

元注解

元注解(meta-annotation)负责注解其他注解的注解,Java中定义了4个标准的元注解类型,用来提供对其他注解类型作说明。

@Target  //描述注解的使用范围

@Retention  //表示需要在什么级别保存该注释信息,描述注解的生命周期(SOURCE<CLASS<RUNTIME)

@Documented  //说明该注解将被包含在javadoc中

@Inherited  //说明子类可以继承父类中的该注解

自定义注解

使用@interface自定义注解,自动继承java.lang.annotation.Annotation接口。

  1. @interface用来声明一个注解,格式:public @interface 注解名{定义内容}

  2. 其中的每一个方法实际上是声明了一个配置参数

  3. 方法的名称就是参数的名称

  4. 返回值类型就是参数的类型(返回值只能是基本类型,Class,String,enum)

  5. 可以通过default声明参数的默认值

  6. 如果只有一个参数成员,一般参数名为value

  7. 注解元素必须要有值,定义注解元素时,经常使用空字符串0作为默认值

//自定义一个注解格式
@Target(value = ElementType.METHOD)//在方法中生效
@Retention(value = RetentionPolicy.RUNTIME)//表示在运行时也生效(任何时生效)
@Documented
@Inherited
public @interface MyFirstAnnotation{
    //注解的参数 : 参数类型 + 参数名();
    String name() default "";
    int age() default 0;
    int id() default -1;//默认-1,代表不存在
}

//使用时必须需要提供无默认值的参数
@MyFirstAnnotation(name = "lee",age = 18,id = 10086)
public void test1(){}

反射

反射(Reflection)使Java有一定的动态性,可以利用反射机制获得类似动态语言的特性,使程序更灵活。

反射就是在运行时才知道要操作的类是什么,并且可以在运行时获取类的完整构造,并调用对应的方法。使用反射提高程序的通用性。

通过统一的语法创建对象获取对象。

注解和反射基础知识和使用方法

类加载

Class:在JVM(虚拟机)加载完,Class文件以后,会给每个类生成唯一的一个Class对象。该Class对象是该类所有实例(对象)共享的一个对象,Class对象包含了与类有关的信息,在Class对象中会把属性以及方法都单独封装成一个对象。

三个步骤:

  1. 加载:将class文件字节码内容加载到内存中,并将这些静态数据转换成方法区的运行时数据结构,然后生成一个代表这个类的java.lang.Class对象。

  2. 链接:将Java类的二进制代码合并到JVM的运行状态之中的过程。

    验证:确保加载的类信息符合JVM规范,没有安全问题。

    准备:正式为类变量(static)分配内存并设置类变量默认初始值的阶段,这些内存都将在方法区中进行分配。

    解析:虚拟机常量池内的符合引用(常量名)替换为直接引用(地址)的过程。

  3. 初始化:到了此阶段,才真正开始执行类中定义的java程序代码,用于执行该类的静态初始器和静态初始块,如果该类有父类,优先对其父类进行初始化。

使用步骤

  1. 获取class对象

    一个类在内存中只有一个Class对象。

    一个类被加载后,类的整个结构都会被封装在class对象中。

    //通过类的对象获取
    Animal animal = new Animal();
    Class animalClass1 = animal.getClass();
    //通过类名.class获取
    Class animalClass2 = Animal.class;
    //通过forName限定性类名获取
    String className = "包名.类名"
    Class animalClass3 = Class.forName(className);
    //通过反射创建一个类的实例
    object obj = animalClass3.newInstance;
    
  2. 操作对象里面的属性

    Field[] fs1 = animalClass3.getFields();//获取所有的公共属性
    Field[] fs2 = animalClass3.gerDeclaredFields();//获取所有属性
    
  3. 根据属性名称获取属性

    Field[] ageField = animalClass3.gerDeclaredFields("age");
    ageField.setAccessible(true);//取消安全检查,允许获取私有的属性值
    ageField.setInt(obj,999);
    int age = ageField.getInd(obj);//获取
    System.out.println(age);
    
  4. 操作对象里面的方法

    Method[] ms = animalClass3.getMethods();//获取所有的公共方法
    Method[] ms = animalClass3.getDeclaredMethods();//获取所有方法
    Method eatMethod = animalClass3.getMethod("eat",int.class,String.class);
    eatMethod.invoke(obj,20,"lee");
    Class<?>[] pcType = eatMethod.getParameterTypes();
    

实例

/*反射实例*/
public void r1(){
    String personStr = "com.example.bean.Person";//对象类型属性
    try {
        Class personClass = Class.forName(personStr);
        Object obj = personClass.newInstance();
        String parKey = "name";
        String parValue = "张三";
        
		//通过字符串拼接创建set方法
        String setParKey = "set"+parKey.substring(0,1).toUpperCase()+parKey.substring(1);
        Method setNameMethod = personClass.getMethod(setParKey,parValue.getClass());

        setNameMethod.invoke(obj,parValue);

        //通过字符串拼接创建get方法
        String getParKey = "get"+parKey.substring(0,1).toUpperCase()+parKey.substring(1);
        Method getNameMethod = personClass.getMethod(setParKey,parValue.getClass());

        Object result = getNameMethod.invoke(obj);

        System.out.println(result);

    } catch (Exception e) {
        e.printStackTrace();
    }
}

注解和反射基础知识和使用方法

上一篇:OB-管理oceanbase集群参数


下一篇:DRF自动生成接口文档