张春 发表于 2023-5-31 01:36:14

java注解与反射

java注解与反射


[*]java注解与反射十分重要,是很多框架的底层
注解(Annotataion)


[*]注解的作用:
   1. 不是程序本身,可以对程序作出解释
   1. 可以被其他程序读取
[*]注解的格式:@注释名,如@override表示重写方法,而且有些还可以添加一些参数值,如@SuppressWarnings(value="unchecjed")
[*]注解可以附加在package,class,method,field等上面,相当于添加了额外的辅助信息。可以通过反射机制编程实现对这些元数据的访问
内置注解


[*]@Override:重写方法
[*]@Deprecated:表示不被鼓励使用或者已废弃已过时
[*]@SuppressWarning:用来抑制编译时的警告信息,但是需要添加一个或多个参数:如("all"),("unchecked")等,平时最好还是不要用这个
使用方法:
@Override
publicvoid run() {
}其他类似。
元注解

<ul>负责注解其他注解
包括(@Target,@Retention,@Documented,@Inherited),分别表示<ol>
描述注解使用范围
需要上面级别保存该注释信息,用于描述注解的生命周期(SOURCE class1 = Class.forName("com.xxx.Teacher");      System.out.println(class1);//      比较两者      System.out.println(aClass==class1);//      方式三:通过类名.class获得      Class teacherClass = Teacher.class;      System.out.println(teacherClass);//      比较      System.out.println(teacherClass==class1);//      方式四:基本数据类型的包装类的type属性      Class type = Integer.TYPE;      System.out.println(type);//      得到父类Class类型      Class superclass = class1.getSuperclass();      System.out.println(superclass);//   补充一下,获得注解和void和Class本身的Class对象      // Override.class      // void.class      //Class.class    }}class Teacher extendsPerson{}/*class com.xxx.Teacherclass com.xxx.Teachertrueclass com.xxx.Teachertrueintclass com.xxx.Person那些类型可以有Class对象?

包括以下:
https://img2023.cnblogs.com/blog/2844064/202305/2844064-20230530230944586-520178666.png
注意:数组长度即使不一致,只要类型和维度一样,就是同一个Class
Class类的方法

获得类完整结构

//下面只能用到方法上,value的值可以取多个至于那些可以取CTRL+左键点击ElementType类去看,另外可以省略value=
@Target(value = ElementType.METHOD)
//只能存在于源码上。值有那些同上,自己点进去看RetentionPolicy类,一般取RUNTIME
@Retention(value = RetentionPolicy.SOURCE)
//这两个不多说
@Documented
@Inherited
//自定义注解
@interface MyAnnotation{

}操作类结构

//元注解
@Retention(RetentionPolicy.RUNTIME)
@Inherited
//自定义注解
@interface MyAnnotation{
//    注解参数:参数类型+参数名(),可以设置默认值,没默认值的话使用时必须传参
    String name() default "";
    int a();
    int c() default 1;
}

//使用
@MyAnnotation(name = "lihua",a = 1)类的加载过程

https://img2023.cnblogs.com/blog/2844064/202305/2844064-20230530231039100-1242750281.png
https://img2023.cnblogs.com/blog/2844064/202305/2844064-20230530231120383-303042018.png
解释一下符号引用和直接引用:
符号引用你可以理解为要引用的类目前在内存中还没被加载出来,JVM当然不知道它在哪里。所以就用唯一的符号来表示就好像给它赋了一个变量,等到链接的时候类加载器解析地址完成变成直接引用
直接引用就是存储引用类在真实内存中的地址
总而言之还是这张图:
https://img2023.cnblogs.com/blog/2844064/202305/2844064-20230530231201002-278730296.png
什么时候会发生类的初始化

https://img2023.cnblogs.com/blog/2844064/202305/2844064-20230530231235007-236024002.png
主动引用比较好理解,下面只演示一下被动引用“
public static void main(String[] args) throws ClassNotFoundException {
    /*1.下面是通过反射获取Class对象的一种方式,参数是文件路径
      2.一个类在内存中只有一个Class类,在多创建几个该类的Class
   也是同一个。
      3一个类被加载后,类的整个结构都会被封装在Class对象中
      4.我们经常用的Object的getClass方法就是返回一个Class对象,也是创建Class对象的一种常用方式
      5.反射在某种情况下可以理解为通过一个对象获得类
   */
    Class<?> aClass = Class.forName("com.xxx.MyThread");
    System.out.println(aClass);
}

//out:class com.xxx.MyThread类加载器


[*]类加载的作用:将class文件字节码内容加载到内存中,并且将这些静态数据转换成方法区的运行时数据结构,然后在堆中生成一个代表这个类的java.lang.Class 对象,作为方法区中类数据的访问入口。简单来说,类加载器的作用就是把类(class)装进内存
[*]类缓存:标准的JavaSE类加载器可以按照要求查找类,但一旦某个类被加载到类加载器中,它将维持加载(缓存)一段数据。不过JVM垃圾回收机制可以回收这些Class对象
https://img2023.cnblogs.com/blog/2844064/202305/2844064-20230530231331403-1525329110.png
类加载器有那些?

https://img2023.cnblogs.com/blog/2844064/202305/2844064-20230530231421428-1203683881.png
java的主要jar包就是rt.jar,引导类加载器就是加载这一类核心jar包
public class Test {

    public static void main(String[] args) throws ClassNotFoundException {
      Teacher teacher = new Teacher();
//      方式一:通过对象
      Class aClass = teacher.getClass();
      System.out.println(aClass);
//      方式二:forname
      Class<?> class1 = Class.forName("com.xxx.Teacher");
      System.out.println(class1);
//      比较两者
      System.out.println(aClass==class1);
//      方式三:通过类名.class获得
      Class<Teacher> teacherClass = Teacher.class;
      System.out.println(teacherClass);
//      比较
      System.out.println(teacherClass==class1);
//      方式四:基本数据类型的包装类的type属性
      Class<Integer> type = Integer.TYPE;
      System.out.println(type);
//      得到父类Class类型
      Class<?> superclass = class1.getSuperclass();
      System.out.println(superclass);
//   补充一下,获得注解和void和Class本身的Class对象
      // Override.class
      // void.class
      //Class.class

    }
}

class Teacher extendsPerson{}

/*
class com.xxx.Teacher
class com.xxx.Teacher
true
class com.xxx.Teacher
true
int
class com.xxx.Person反射操作泛型

https://img2023.cnblogs.com/blog/2844064/202305/2844064-20230530231527973-1894052229.png
public class MyThread {
    privateint a;
    publicvoid run(String a){}

    public int getA() {
      return a;
    }

    public void setA(int a) {
      this.a = a;
    }

    public MyThread(int a) {
      this.a = a;
    }

    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
      Class c1 = Class.forName("com.xxx.MyThread");
      //获取类名
      System.out.println(c1.getName());
      System.out.println(c1.getSimpleName());
//      获得类属性
      Field[] fields = c1.getFields();//只能找到public属性
      fields = c1.getDeclaredFields();
      for (Field field : fields) {
            System.out.println(field);
      }
//      获得类方法
      System.out.println("-----------------------");
      Method[] methods = c1.getMethods();//包括继承的方法
      methods=c1.getDeclaredMethods();//只包括本类的方法
      for (Method method : methods) {
            System.out.println(method);
      }
      System.out.println("-------------------------------");
//      获得指定方法:没s,两个参数分别是方法名和方法参数类型的Class
      System.out.println(c1.getMethod("run",String.class));
//      获得构造器
      System.out.println("----------------");
      Constructor[] constructors = c1.getConstructors();//获得public构造器
      for (Constructor constructor : constructors) {
            System.out.println(constructor);
      }
//      同理getDeclaredConstructors()获得的所有构造器,

      //获得指定的构造器,参数为构造器参数的Class
      System.out.println("--------------------------");
      Constructor constructor = c1.getConstructor(int.class);
      System.out.println(constructor);
    }
}
/*out:

public void com.xxx.MyThread.run(java.lang.String)
public void com.xxx.MyThread.setA(int)
public int com.xxx.MyThread.getA()
-------------------------------
public void com.xxx.MyThread.run(java.lang.String)
----------------
public com.xxx.MyThread(int)
--------------------------
public com.xxx.MyThread(int)反射操作注解

ORM->对象关系映射
public class MyThread {
    privateint a;
    publicvoid run(String a){
      System.out.println(a);
    }

    public int getA() {
      return a;
    }

    public MyThread() {
    }

    public void setA(int a) {
      this.a = a;
    }

    public MyThread(int a) {
      this.a = a;
    }

    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchFieldException {
      Class<?> aClass = Class.forName("com.xxx.MyThread");
//      构建一个对象:本质是调用无参构造器,其该类必须有无参构造器
//      MyThread myThread = (MyThread)aClass.newInstance();
//      通过构造器创建对象,可以用有参构造函数
//       Constructor constructor= aClass.getDeclaredConstructor(int.class);
//       MyThread myThread1=(MyThread)constructor.newInstance(1);

//       通过反射调用方法
//      通过反射获取一个方法
      MyThread myThread = (MyThread) aClass.newInstance();
      Method setName = aClass.getMethod("run", String.class);
//      invoke:激活,参数:对象名,方法参数
      setName.invoke(myThread,"helloworld");

//      通过反射操作属性
      Field a=aClass.getDeclaredField("a");
//      取消安全检查,否则无法操作私有属性.method,field,consructor都有它,关闭也可以提高反射效率
      a.setAccessible(true);
      a.set(myThread,5);
      System.out.println(myThread.a);
    }
   
   /*out:
   helloworld
        5
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
页: [1]
查看完整版本: java注解与反射