java —— 注解,反射

注解

什么是注解

注解的主要作用:对我们的程序进行标注和解释。
(可以理解成:注释是写给人看的;注解是写给jvm看的)

常用注解

在这里插入图片描述
如:
在这里插入图片描述

自定义注解

格式:
public @interface 注解名称 {
 	public 属性类型 属性名() default 默认值 ;//属性类型可以是:基本数据类型,String,Class,注解,枚举,以上类型的一维数组
 }
例子
定义
@Retention(RetentionPolicy.CLASS)//元注解,运行时注解的作用时间范围。
@Target(ElementType.METHOD)//元注解,类可以在什么上面使用。
public @interface MyTest {
    String name();
    int code() default 200;
}
使用
public class Main {
  
    @MyTest(name = "0",code = 200)//有默认值就可以不写,当你要写code = 200时可以写成@MyTest(name = "0")
    public void annotationTest(){

    }
}

元注解

元注解:就是描述注解的注解。
在这里插入图片描述

@Retention
  1. @Retention(RetentionPolicy.CLASS)//注释将被编译器记录在类文件中,但不需要在运行时由虚拟机保留。
  2. @Retention(RetentionPolicy.RUNTIME)//注释要记录在类文件由编译器和运行时虚拟机保留的,所以他们可以读沉思。
  3. @Retention(RetentionPolicy.SOURCE)//注释将被编译器丢弃。
    注解一般用在写一个通用的程序框架的场合。它通常和反射结合起来使用;

反射

反射的概述

Java反射机制(自审机制)
   是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;
   对于任意一个对象,都能够调用它的任意属性和方法;
   这种动态获取信息以及动态调用对象方法的功能称为Java语言的反射机制。
   利用反射可以无视修饰符获取类里面所有的属性和方法。
   先获取配置文件中的信息,动态获取信息并创建对象和调用方法
一般调用方法和反射调用方法比较

一般:1. 创建这个类的对象 2. 用对象调用方法;
反射:1. 利用class对象来创建的 2. 反射方式:创建对象 3. 反射方式:调用方法

对象:
在这里插入图片描述

反射获取构造方法并使用

获取Class类的对象

  1. Class.forName(“全类名”);
  2. 类名.class
  3. 对象.getClass();
Class类中用于获取构造方法的方法

Constructor<?>[] getConstructors​():返回所有公共构造方法对象的数组 Constructor<?>[] getDeclaredConstructors​():返回所有构造方法对象的数组
Constructor getConstructor​(Class<?>... parameterTypes):返回单个公共构造方法对象 Constructor getDeclaredConstructor​(Class<?>… parameterTypes):返回单个构造方法对象

Constructor类中用于创建对象的方法

T newInstance​(Object… initargs):根据指定的构造方法创建对象
setAccessible(boolean flag):设置为true,表示取消访问检查

练习

person实体类(后面将用这个类来演示):

public class Person implements Serializable {
    private String name;
    private int age;
    private String address;

    public Person() {

    }

    public Person(String name) {
        this.name = name;
    }

    private Person(String name, int age, String address) {
        this.name = name;
        this.age = age;
        this.address = address;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", address='" + address + '\'' +
                '}';
    }
    private void study(){
    	System.out.println("私有方法执行了-----");
    }
}
public class Main {

    public static void main(String[] args) {
        try {
        // 获取到Person类的class对象。
            Class<?> aClass = Class.forName("com.jifu.test.bean.Person"); 
            //创建Person对象
            Person person = (Person) aClass.newInstance();
            //获得com.jifu.test.bean.Person这个对象的所有构造方法,包括私有的。
             Constructor[] allConstructors = aClass.getDeclaredConstructors();
            //获得com.jifu.test.bean.Person这个对象的public修饰的构造方法。
            Constructor[] constructors = aClass.getConstructors();
            //获得参数类型为(String.class,int.class,String.class)的构造方法,包括私有的。
             Constructor<?> constructor = aClass.getDeclaredConstructor(String.class,int.class,String.class);
            //设置为true 表示取消访问检查。
            constructor.setAccessible(true);
            Person person = (Person)constructor.newInstance("小明", 18, "北京");
           
        }catch (ClassNotFoundException | InstantiationException | IllegalAccessException |NoSuchMethodException e) {
            e.printStackTrace();
        }

    }
}

小结

获取class对象
三种方式 ---- Class.forName(“全类名”)
获取里面的构造方法对象
getConstructor (Class<?>... parameterTypes) getDeclaredConstructor (Class<?>… parameterTypes)
如果是public的,直接创建对象
newInstance(Object… initargs)
如果是非public的,需要临时取消检查,然后再创建对象
setAccessible(boolean)(暴力获取)

反射获取成员变量

步骤

第一步:获得class对象
Class.forName(“全类名”);

第二步:获得Field对象
Field[] getFields():返回所有公共成员变量对象的数组
Field[] getDeclaredFields():返回所有成员变量对象的数组
Field getField(String name):返回单个公共成员变量对象
Field getDeclaredField(String name):返回单个成员变量对象

第三步:赋值或者获取值
void set(Object obj, Object value):赋值
Object get(Object obj)获取值。

反射获取成员方法并运行

步骤

第一步:获得class对象
Class.forName(“全类名”);

第二步:获得Method对象
Method ] getMethods():返回所有公共成员方法对象的数组,包括继承的
Method[] getDeclaredMethods():返回所有成员方法对象的数组,不包括继承的
Method getMethod(String name, Class<?>... parameterTypes):返回单个公共成员方法对象 Method getDeclaredMethod(String name, Class<?>… parameterTypes):返回单个成员方法对象

练习
public class Main {

    public static void main(String[] args) {
        try {
        // 获取到Person类的class对象。
            Class<?> aClass = Class.forName("com.jifu.test.bean.Person"); 
            //获得参数类型为(String.class,int.class,String.class)的构造方法,包括私有的。
            Constructor<?> constructor = aClass.getDeclaredConstructor(String.class,int.class,String.class);
             //设置为true 表示取消访问检查。
            constructor.setAccessible(true);
            //创建Person对象
            Person person = (Person)constructor.newInstance("小明", 18, "北京");
            //获得名为study的Person对象中的方法对象(第一个参数是方法名,后面的参数是方法参数的类型)
            Method study = aClass.getDeclaredMethod("study", null);
             //设置为true 表示取消访问检查。
            study.setAccessible(true);
            //执行方法(第一个参数是调用该方法的对象,后面的参数是方法中要传的参数值)
            study.invoke(person,null);
        }catch (ClassNotFoundException | InstantiationException | IllegalAccessException |NoSuchMethodException e) {
            e.printStackTrace();
        }

    }
}

综合应用(注解+反射)

需求:一个类里面只要是标注了 @MyTest注解的就自动运行

自定义注解类

package com.jifu.test.enumTest;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME) //此处必须是RUNTIME才能看到效果
@Target(ElementType.METHOD)
public @interface MyTest {
    String name();
    int code() default 200;
}

要运行的类

package com.jifu.test.enumTest;

public class TestDame {
    @MyTest(name = "知识")
    public void TestMethod(){
        System.out.println("测试方法1");
    }
    @Deprecated
    @MyTest(name = "知识",code = 201)
    private void TestMethod2(){
        System.out.println("测试方法2");
    }
    public void TestMethod3(){
        System.out.println("测试方法3");
    }
}

main方法运行看效果

package com.jifu.test.enumTest;

import com.jifu.test.bean.Person;

import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;


public class Main {
    public static void main(String ... args){
      try {
      //获取到"com.jifu.test.enumTest.TestDame"类的class对象。
        Class<?> aClass = Class.forName("com.jifu.test.enumTest.TestDame");
       // 获得TestDame的无参构造。
         Constructor<?> declaredConstructor = aClass.getDeclaredConstructor(null);
         //通过无参构造方法获得TestDame实例对象。
        TestDame testDame = (TestDame)declaredConstructor.newInstance();
        //获得"com.jifu.test.enumTest.TestDame"类的所有方法包括非public的
        Method[] declaredMethods = aClass.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
        //打印每个方法
          System.out.println(declaredMethod);
          //获得这个方法中的所有注解
          final Annotation[] declaredAnnotations = declaredMethod.getDeclaredAnnotations();
          for (Annotation declaredAnnotation : declaredAnnotations) {
          //遍历打印每个注解
            System.out.println(declaredAnnotation);
            //判断注解是不是MyTest.class类型
              if (declaredAnnotation.annotationType()==MyTest.class){
              //设置取消方法受检。
            declaredMethod.setAccessible(true);
              //如果注解是MyTest.class类型就运行,需要传入对象的类型
                declaredMethod.invoke(testDame);
              }
          }
          }
        }
      } catch (ClassNotFoundException e) {
        e.printStackTrace();
      }
    }
}

运行效果

Z:\jdk-11.0.1\bin\java.exe "-javaagent:D:\idea\IntelliJ IDEA 2021.1\lib\idea_rt.jar=63709:D:\idea\IntelliJ IDEA 2021.1\bin" -Dfile.encoding=UTF-8 -classpath F:\zhifei\zhifei\test\target\classes com.jifu.test.enumTest.Main

public void com.jifu.test.enumTest.TestDame.TestMethod()     //TestMethod()方法上只有一个@MyTest注解
@com.jifu.test.enumTest.MyTest(code=200, name="知识")		
测试方法1		//方法运行了

private void com.jifu.test.enumTest.TestDame.TestMethod2()     //TestMethod2()方法上有一个@MyTest注解 和 @Deprecated注解
@java.lang.Deprecated(forRemoval=false, since="")
@com.jifu.test.enumTest.MyTest(code=201, name="知识")
测试方法2          //方法运行了

public void com.jifu.test.enumTest.TestDame.TestMethod3()     //TestMethod3()方法上没有t注解  

Process finished with exit code 0

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值