首页 > 其他分享 >注解与反射

注解与反射

时间:2023-12-06 23:44:55浏览次数:42  
标签:反射 String System public User println 注解 class

注解与反射

注解

注解:就是以@开头的

比如:@Override

内置注解

例如:

@Override:重写注解

@Deprecated:表示已过时的注解(不推荐使用某方法)

@SuppressWarnings(String[] value()):镇压警告,参数是value=一个字符串数组

元注解

修饰其他注解的注解

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

@Retention:表示在什么级别保留注解信息,用于描述注解的生命周期

(SOURCE<CLASS<RUNTIME)

......

自定义注解

//元注解修饰自定义注解
@Target(value= {ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
//自定义注解,写法:public @interface 注解名
public @interface MyAnotation{
    String name() default "qs";//注解参数,这里默认值为qs,写法:类型 名()
    int[] num();//注解参数
}
//由public修饰的类时,自定义注解不用写public

反射

反射机制:Java有一个很特别的类——Class,java的所有类都有一个Class对象,该对象记录关于对应的类的信息,所有类都只有一个Class对象,Class对象是由JVM(Java虚拟机)创建的,自己不能实例化class对象

通过引入java.lang.reflect.* 我们可以获取对应的类对象的构造器、方法、属性等,还可以实例化类对象对应的类从而获得一个对象

获取类对象的方式

  1. 对象.getClass()

    import java.lang.reflect.*;
    
    public class test {
        public static void main(String[] args){
            User user = new User();
            Class c = user.getClass();
            System.out.println(c);
        }
    }
    
    class User{
        public String name="qq";
        public User(String n){
            this.name = n;
    
        }
        public User(){
    
        }
    }
    
  2. Class.ForName()

    import java.lang.reflect.*;
    
    public class test {
        public static void main(String[] args) throws ClassNotFoundException{
            Class c = Class.ForName("testReflaction/User");
            System.out.println(c);
        }
    }
    
    class User{
        public String name="qq";
        public User(String n){
            this.name = n;
    
        }
        public User(){
    
        }
    }
    
  3. 类名.class

    import java.lang.reflect.*;
    
    public class test {
        public static void main(String[] args){
            Class c = User.class;
            System.out.println(c);
        }
    }
    
    class User{
        public String name="qq";
        public User(String n){
            this.name = n;
    
        }
        public User(){
    
        }
    }
    

所有类型的class对象

  1. 类有class对象:object.class
  2. 数组有class对象:String[].class
  3. 接口有class对象:Comparable.class
  4. 二维数组有class对象
  5. 注解有class对象:Override.class
  6. 枚举有class对象:ElementType.class
  7. 基本数据类型有class对象
  8. void有class对象:void.class
  9. Class类本身有class对象:class.class

类加载内存和类初始化

类的加载:把class文件的字节码读入内存,把静态数据转换为方法区运行时数据结构,并生成一个Class对象表示该类

链接:

  1. 验证:确保类信息符合JVM规范
  2. 准备:正式为静态变量(类变量)分配内存并设置默认值,这些内存在方法区分匹配
  3. 解析:把虚拟机常量池内的符号引用(常量名引用)转换为直接引用(地址引用)

初始化:执行类构造器()方法的过程,类构造器方法由编译期自动收集所有类变量的赋值和静态代码块中的语句合并产生的,类构造器方法不是构造方法。

class Test{
    static{
        ...
    }
    static int a = 100;
    public Test(){
        ...
    }
}
//如以上代码,把这里的static修饰的变量和static代码块里面的代码合并起来就是类构造器方法
//而Test()这个方法才是构造方法

初始化一个类,发现其父类没有初始化,会首先初始化父类

虚拟机会保证一个类的构造器方法在多线程环境被正确加锁和同步

什么时候类会初始化:

主动引用:

  1. new的时候
  2. 反射的时候

类加载器

类缓存:类被加载到加载器,会维持加载一段时间,JVM垃圾回收机制可以回收这些缓存的类的class对象

类加载器类型:

  1. 引导类加载器(根加载器,c++写的无法获取)

  2. 扩展类加载器

  3. 系统类加载器(常用)

package testReflaction;

public class ClassLoader {
    public static void main(String[] args){
        java.lang.ClassLoader loader1 = java.lang.ClassLoader.getSystemClassLoader();
        System.out.println(loader1);//打印系统类加载器
        java.lang.ClassLoader loader2 = loader1.getParent();
        System.out.println(loader2);//打印扩展类加载器
        java.lang.ClassLoader loader3 = loader2.getParent();
        System.out.println(loader3);//打印根类加载器,无法获取显示为空
    }
}

image-20230804092246310

获取类运行时结构

获取类名:

类对象.getName()——获取包名+类名

类对象.getSimpleName()——获取类名

获取类属性

类对象.getFields()——只获取public属性

类对象.getDeclaredFields()——获取所有属性

类对象.getField("属性名")——获得指定public属性

类对象.getDeclaredFields("属性名")——获取指定的非public属性

package testReflaction;
import java.lang.reflect.*;

public class test {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException,NoSuchMethodException{

        Class c1 = Class.forName("testReflaction.User");//获取类对象
        //获取类名
        System.out.println("获取类名:");
        System.out.println(c1.getName());//获取并打印包名+类名
        System.out.println(c1.getSimpleName());//获取并打印类名

        //获取类属性
        System.out.println("获取类属性:");
        System.out.println("___________________________________________");
        Field[] fields = c1.getFields();
        for(Field field:fields){
            System.out.println(field);
        }
        System.out.println("");
        for (Field f : c1.getDeclaredFields()){
            System.out.println(f);
        }
        Field f1 = c1.getField("name");
        Field f2 = c1.getDeclaredField("a");
        System.out.println("获取指定属性:\n" + f1 + "\n" + f2);

    }

}

class User{
    public String name="qq";
    static int a = 1;
    int b = 3;
    public User(String n){
        this.name = n;

    }
    public User(){

    }
    public String getName(){
        return this.name;
    }
    public int getA(){
        return a;
    }
    int getB(){
        return b;
    }
}

image-20230804103226028

获取类方法

类对象.getMethod()——获取指定public方法

类对象.getMethods()——获取所有public方法

类对象.getDeclaredMethod()——获取指定非Public方法

类对象.getDeclaredMethods()——获取所有非public方法

package testReflaction;
import java.lang.reflect.*;

public class test {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException,NoSuchMethodException{

        Class c1 = Class.forName("testReflaction.User");//获取类对象
       //获取类方法
        System.out.println("获取类方法:");
        Method[] methods = c1.getMethods();
        System.out.println("getMethods:");
        for (Method m : methods){
            System.out.println(m);
        }
        System.out.println("getDeclaredMethods:");
        for (Method m1 : c1.getDeclaredMethods()){
            System.out.println(m1);
        }
        Method m3 = c1.getDeclaredMethod("getB");
        System.out.println(m3);
        Method m4 = c1.getMethod("getA");
        System.out.println(m4);

    }

}

class User{
    public String name="qq";
    static int a = 1;
    int b = 3;
    public User(String n){
        this.name = n;

    }
    public User(){

    }
    public String getName(){
        return this.name;
    }
    public int getA(){
        return a;
    }
    int getB(){
        return b;
    }
}

image-20230804103157360

获取构造方法

类对象.getConstructor():获取指定的公有构造方法

类对象.getConstructors():获取类中所有公有构造方法

类对象.getDeclaredConstructor():获取指定的构造方法

类对象.getDeclareConstructors():获取类的所有构造方法

package testReflaction;
import java.lang.reflect.*;

public class test {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException,NoSuchMethodException{

        Class c1 = Class.forName("testReflaction.User");//获取类对象
         //获取构造方法
        System.out.println("___________________________________________");
        System.out.println("获取构造方法:");
        for (Constructor c : c1.getConstructors()){
            System.out.println(c);
        }
        for (Constructor c2 : c1.getDeclaredConstructors()){
            System.out.println(c2);
        }
        System.out.println(c1.getConstructor(String.class));
        System.out.println(c1.getDeclaredConstructor());
      

    }

}

class User{
    public String name="qq";
    static int a = 1;
    int b = 3;
    public User(String n){
        this.name = n;

    }
    public User(){

    }
    public String getName(){
        return this.name;
    }
    public int getA(){
        return a;
    }
    int getB(){
        return b;
    }
}

image-20230804103125206

通过反射动态创建对象

package testReflaction;
import java.lang.reflect.*;

public class test {
    public static void main(String[] args) throws ClassNotFoundException, InvocationTargetException,IllegalAccessException,InstantiationException{

        Class c1 = Class.forName("testReflaction.User");//获取类对象
        //创建对象
        //newInstance()
        User user = (User)c1.newInstance();
        System.out.println(user);

        //通过构造器创建
        Constructor c = c1.getDeclaredConstructor(String.class);
        User use = (User)c.newInstance("小d");
        System.out.println(use);
        
        //调用方法
        Method getA = c1.getMethod("getA",null);
        getA.invoke(use,null);
        
      

    }

}

class User{
    public String name="qq";
    static int a = 1;
    int b = 3;
    public User(String n){
        this.name = n;

    }
    public User(){

    }
    public String getName(){
        return this.name;
    }
    public int getA(){
        return a;
    }
    int getB(){
        return b;
    }
}

image-20230804104440888

反射机制很重要,在java反序列化时会用到,可以用来获取一些自定义类的信息,还可以利用JAVA本身自带的包中的类来执行系统命令或执行代码,在框架中也会用到

接下来会去学习并记录一些JAVA反序列化的实战,以及框架方面的知识

通过反射操作泛型

通过反射获取注解

标签:反射,String,System,public,User,println,注解,class
From: https://www.cnblogs.com/q1stop/p/17880789.html

相关文章

  • java 序列话注解 @Transient
    java序列话注解@TransientJava序列化注解及其使用简介在Java程序中,对象的序列化是指将对象转换为字节流的过程,以便在网络上传输或保存到文件中。而反序列化则是将字节流重新转换为对象。Java提供了java.io.Serializable接口,用于标识可序列化的类。然而,有时我们希望......
  • @SpringBootTest 和 @RunWith 注解不能识别 单元测试第一步引入maven依赖
    @SpringBootTest和@RunWith注解不能识别单元测试第一步引入maven依赖一、背景    最近在预研 Rocketmq,在写小例子的时候,需要编写测试代码,突然间发现我的 @SpringBootTest 和 @RunWith 这两个注解不能识别,于是展开了我的问题排查过程。问题截图如下:二、问题排......
  • @RunWith注解找不到,怎么办? spring-boot-starter-test 2.5.5 版本只需要在类上加上@Spr
    @RunWith注解找不到,怎么办?spring-boot-starter-test2.5.5版本只需要在类上加上@SpringBootTest即可,不需要再加@RunWith()注解了。1、新版spring-boot-starter-test不再集成junit,而是junit-jupiter在这里,先说明我使用的版本SpringBoot2.5.5spring-boot-starter-test2.5......
  • 【漏洞分析】Reflection Token 反射型代币攻击事件通用分析思路
    在本篇文章中,我将通过一个攻击事件引出ReflectionToken攻击事件的一个通用分析思路。关于ReflectionToken的其他案例分析,可以参考BEVO代币攻击事件分析及复现一文。TomInu攻击事件TomInuToken是一个反射型代币reflectiontoken,于2023-01-26遭到黑客攻击,攻击者获利355......
  • @PostConstruct 注解不生效的问题
    @PostConstruct注解不生效的问题1、从JavaEE5规范开始,Servlet中增加了两个影响Servlet生命周期的注解,@PostConstruct和@PreDestroy,这两个注解被用来修饰一个非静态的void()方法。写法有如下两种方式:@PostConstructpublicvoidsomeMethod(){}或者public@PostConstructvoi......
  • @Transactional事务注解及请求接口的定义先后执行顺序设计
    @Transactional事务注解及请求接口的定义先后执行顺序设计1.事务内查询,可能存在事务没有提交,导致查询数据查不出来。2.或者可能跟请求参数作为查询条件,在某个条件下,请求参数发生变化,也会导致查询不出来。可以将在一个事务内的操作(定义为一个组,Group_ID),根据组号来查询。根据接口......
  • 单元测试:Junit框架、反射、注解、动态代理
    单元测试:Junit框架单元测试单元测试就是针对最小的功能单元编写测试代码,Java程序最小的功能单元是方法,因此,单元测试就是针对Java方法的测试,进而检查方法的正确性目前测试方法的方式的和存在的问题方式:只有一个main方法,如果一个方法的测试失败了,其他方法测试会受到影响问题:①无法得......
  • 基于xml的Spring是如何解析@Component,@Service等注解的
    SpringFramework2.0开始,引入可扩展的XML编程机制,该机制要求XMLSchema命名空间需要与Handler建立映射关系。该关系配置在相对于classpath下的/META-INF/spring.handlers中。如上图所示 ContextNamespaceHandler对应<context:...>分析的入口。ContextNamespaceHandler 这......
  • SpringBoot自定义注解导出Excel
    先定义一个注解importjava.lang.annotation.Retention;importjava.lang.annotation.RetentionPolicy;@Retention(RetentionPolicy.RUNTIME)public@interfaceExcelHander{Stringvalue()default"";StringlinkFiled()default"";Cel......
  • Angular Input 注解在 Spartacus 项目开发中的实际应用场景一例
    @Input()装饰器是Angular中用于在组件中接收父组件传递的数据的一种方式。它的作用是将一个属性标记为输入属性,使得父组件可以将数据绑定到子组件的这些属性上。这样,父子组件之间就可以实现双向数据传递,实现更灵活的组件通信。下面是一个实际的例子:SearchBoxComponent是父组......