当前位置:网站首页>一文看懂注解与反射

一文看懂注解与反射

2022-08-11 05:30:00 zhangkai__

注解

  • 作用:对程序做出解释;可以被其他程序读取(如:编译器等)

  • 使用方式:附加在package,class,method,field等上面,相当于添加额外的辅助信息,可以通过反射机制编程实现对元数据的访问。

1.内置注解

  • @Override 重写超类中的方法声明;
  • @Deprecated 建议不使用下面元素,因为是不安全或者有更优的选择,但是可以使用;
  • @SuppressWarnings 抑制编译时的警告信息,需要传入一个参数

2. 元注解

2.1作用

负责注解其他注解,java定义了4个标准的meta-annotation类型,时对其他annotation类型说明.

2.2 类型

  • @Target: 描述注解使用范围
  • @Retention:用于描述注解的生命周期(source<class<runtime)
  • @Document: 说明该注解将被包含在javadoc中
  • @Inherited:说明子类可以继承父类中的该注解

3.自定义注解

在这里插入图片描述

//测试元注解
public class Test001 {
    
    @MyAnnotation(name = "xiaoming",teachers = {
    "lili","hehe"})
    public void run(){
    }
}

//定义一个元注解
@Target(value = {
    ElementType.METHOD,ElementType.TYPE})//在方法中有效
//Retention表示下面的注解的作用范围(source<class<runtime)
@Retention(value = RetentionPolicy.RUNTIME)
//自定义注解
@interface MyAnnotation{
    
    //注解的参数:参数类型+参数名
    String name();
    int age() default -1;//默认值-1,代表不存在
    String[] teachers();
}

反射机制

1.动态语言与静态语言

动态语言:运行时代码可以根据条件改变自身结构,如,C#,javaScript , PHP , Python
静态语言:运行时结构不可变,如,Java,C,C++

2.反射(Reflection)

在这里插入图片描述

2.1反射相关主要API

java.lang.Class 代表一个类
java.lang.reflect.Method 代表类的方法
java.lang.reflect.Field 代表类的成员
java.lang.reflect.Constructor 代表类的构造器

2.2 Class类的常用方法

在这里插入图片描述

2.3 所有类型的Class类的对象

Class c1=Object.class //类对象
Class c2=Comparable.class //接口
Class c3=String[].class  //一维数组
Class c4=int[][].class  //二维数组
Class c5=Override.class //注解
Class c6=ElementType.class  //枚举
Class c7=Integer.class  //基本数据类型
Class c8=void.class  //void
Class c9=Class.class //Class
  • 只要元素类型与维度一样,就是同一个Class

2.4 类的加载

类加载分析:
在这里插入图片描述
其中流程为:
在这里插入图片描述

  1. 加载到内存,会产生一个类对应Class对象
  2. 链接,链接结束,栈内部初始化值
  3. 初始化,clinit()方法,加载类元素,修改对应2中栈的值。

2.5 类的初始化

在这里插入图片描述

//主动饮用子类,则子类父类都会初始化
Son son=new Son();
//使用反射得到子类,子类父类都会被初始化
Class.forName(com.zk.Son);
//当子类调用父类静态变量时,只初始化父类,不会初始化子类
Son.b //b为父类静态变量
//当创建子类数组,或者调用子类静态常量时,父类子类都不会被初始化
Son[] array=new Son[3];
Son.M //M 为子类静态常量

2.6类加载器的作用

将Class文件字节码内容加载到内存中,并将这些静态数据转换成方法区的运行数据结构,然后在堆中生成一个代表这个类的Class对象,作为方法区访问入口
在这里插入图片描述

2.6.1 双亲委派机制

当类加载时存在与底层代码相同的包时,系统会自动选择安全的自带包,而不是外部自定义的包

3.反射功能

3.1获取各类属性

Class c =Class.forName(com.zk.User);
//获取类名
c.getName(); //包名+类名
c.getSimpleName(); //类名
//获取类的属性
Fields[] fi=c.getFields(); //只能获取public属性
Fields[] fi2=c.getDeclaredFields(); //可以获取类的全部属性
Fields name= c.getDeclaredField(“name”); //获取指定属性值
//获取类的方法
Method[] m =c.getMethods(); //获得本类和其父类的全部public方法
Method[] m2=c.getDeclaredMethods(); //仅获取本类的全部方法
//获取指定方法,必须加入参数,没有加null;因为存在重载,只有方法名和参数个数两个才能精确定位方法
Method getid=c.getMethod(“getid”,null); 
Method setid=c.setMethod(“setid”,int.class);
//获取类的构造器
Constructor[] co=c.getConstructors(); //仅获得public构造器
Constructor[] co2=c.getDeclaredConstructor();//获取全部构造器
//获取指定构造器,必须参数
Constructor con=c.getConstructor(String.class,int.class,int.class);

3.2 动态创建对象

//通过反射去动态创建对象
Class c =Class.forName(com.zk.User);

//创建一个对象
User user=(User) c.newInstance(); //本质是调用了类的无参构造器
//通过构造器创建对象
Constructor co=c.getDeclaredConstructor(String.class,int.class,int.class);
User user2=(User) co.newInstance(“xiaoming”,10);

//通过反射调用方法
User user3=c.newInstance();
Method setName=c.getDeclaredMethod(“xioaming”,String.class);
//invoke(对象,“上面方法的传入值”);—->激活方法
setName.invoke(user3,”xiaohong”);
sout.user3.getName();//————->xiaohong

//通过反射操作属性
User user4=c.newInstance();
Field name=c.getDeclaredField(“name”);
//由于name是private修饰,所以不能直接反射出来
//需要使用setAccessible(true)方法打开程序可访问“开关”
name.setAccessible(true);
name.set(user4,”xiaohonhong”);
sout.user4.getname();//—->这里getname方法是为了测试—-xiaohonhong

3.3反射操作泛型

java采用泛型擦除的机制来引入泛型,Java的泛型仅仅是给编译器javac使用的,确保数据的安全性和免去强制类型转换问题,一旦编译完成,所有和泛型有关的类型全部擦除。

3.4反射操作注解

3.4.1什么是ORM

Object relationship Mapping 对象关系映射
图7

3.4.2 反射操作注解

文章中PPT和代码是狂神教学视频内容,仅学习笔记使用,嘿嘿。

原网站

版权声明
本文为[zhangkai__]所创,转载请带上原文链接,感谢
https://blog.csdn.net/zhangkai__/article/details/125321980