Java反射(Class类)常用方法(附Xmind整理)

简介: Java反射(Class类)常用方法(附Xmind整理)

@[toc]


一、类加载器

1、Java类加载机制

  1. 加载:将class文件字节码内容加载到内存中,并将这些静态数据转换成方法区中的运行时数据结构,在堆中生成一个代表这个类的java.lang.Class对象,作为方法区类数据的访问入口。
  2. 链接:将java类的二进制代码合并到 jvm的运行状态之中的过程,链接过程又分为3个过程:

    1. 验证:确保加载的类信息符合jvm规范,没有安全方面的问题。
    2. 准备:正式为类变量(static变量)分配内存并设置类变量初始值的阶段, 这些内存都将在方法区中进行分配。
    3. 解析:虚拟机常量池内的符号引用替换为直接引用的过程。(比如String s ="aaa",转化为 s的地址指向“aaa”的地址)
  3. 初始化:初始化阶段是执行类构造器方法的过程。类构造器方法是由编译器自动收集类中的所有类变量的赋值动作和静态语句块(static块)中的语句合并产生的。当初始化一个类的时候,如果发现其父类还没有进行过初始化,则需要先初始化其父类的初始化虚拟机会保证一个类的构造器方法在多线程环境中被正确加锁和同步 当访问一个java类的静态域时,只有真正声明这个静态变量的类才会被初始 化。

Java类的生命周期:
在这里插入图片描述

2、ClassLoader类加载器

ClassLoader类加载器的作用就是将 .class 文件加载到JVM虚拟机中去。

package com.lydms.test;

public class ClassLoaderDemo {
    public static void main(String[] args) throws ClassNotFoundException {

        //获取类加载器
        ClassLoader classLoader = ClassLoaderDemo.class.getClassLoader();

        //常用三种方式加载类
        // 使用ClassLoader.loadClass()来加载类,不会执行初始化块
        System.out.println("‐‐ClassLoader.loadClass()‐‐");
        classLoader.loadClass("com.lydms.test.Test1");

        //  使用Class.forName(clssName) 来加载类,默认会执行初始化块
        System.out.println("‐‐Class.forName(clssName)‐‐");
        Class.forName("com.lydms.test.Test2");

        //  使用Class.forName(className, initialize, ClassLoader) 来加载类,并指定ClassLoader,初始化时不执行静态块.
        //  参数:类名,是否初始化,类加载器
        System.out.println("‐‐Class.forName(className,initialize,ClassLoader)‐‐");
        Class.forName("com.lydms.test.Test3", false, classLoader);
    }
}

class Test1 {
    static {
        System.out.println("Test1 静态初始化块");

    }
}

class Test2 {
    static {
        System.out.println("Test2 静态初始化块");

    }
}

class Test3 {
    static {
        System.out.println("Test3 静态初始化块");

    }
}

二、获取Class对象的方式

1、Class.forName("全类名")

通过指定的字符串路径获取

Class<?> aClass = Class.forName("com.lydms.classes.TestFiled");

2、类名.class

通过类名的属性class获取

Class<ArrayList> arrayListClass = ArrayList.class;

3、对象.getClass()

通过对象的getClass()方法获取

Class<? extends TestFiled> aClass = new TestFiled().getClass();

三、常用方法:

字节码文件 Class类 Class.forName()
构造方法 Constructor类 getConstructor()
成员方法 Method类 getMethod()
成员变量 Field类 getField()

首先获取该类的class对象

Class<?> aClass = Class.forName("com.lydms.classes.TestFiled");

1、获取构造方法、成员方法、成员变量(公开的public)

//  构造方法
Constructor<?>[] constructors = aClass.getConstructors();
//  成员方法
Method[] methods = aClass.getMethods();
//  成员变量
Field[] fields = aClass.getFields();

2、获取构造方法、成员方法、成员变量(所有的public+private)

//  构造方法
Constructor<?>[] declaredConstructors = aClass.getDeclaredConstructors();
//  成员方法
Method[] declaredMethods = aClass.getDeclaredMethods();
//  成员变量
Field[] declaredFields = aClass.getDeclaredFields();

3、获取名称

String name = aClass.getName();
//  返回源代码中给出的底层类的简称。
String simpleName = aClass.getSimpleName();
String typeName = aClass.getTypeName();

4、获取父接口

Class<?> superclass = aClass.getSuperclass();

5、获取实现的接口

Class<?>[] interfaces = aClass.getInterfaces();

6、实例化为新对象

Object newInstance = aClass.newInstance();

7、返回此元素上存在的所有注释

返回此元素上存在的所有注释(public)

RestController annotation = aClass.getAnnotation(RestController.class);
//  获取所有
Annotation[] annotations = aClass.getAnnotations();
for (int i = 0; i < annotations.length; i++) {
    System.out.println(annotations[i].toString());
}

返回此元素上存在的所有注释(public+private)

RestController declaredAnnotation = aClass.getDeclaredAnnotation(RestController.class);
//  获取所有
Annotation[] aas = aClass.getDeclaredAnnotations();
for (int i = 0; i < aas.length; i++) {
    System.out.println(aas[i].toString());
}

8、返回此类的包(package com.lydms.classes)

String packUrl = aClass.getPackage().toString();

9、查找带有给定名称的资源(打印绝对路径)

URL resource = aClass.getResource("TestFiled.class");
System.out.println(resource.getPath().toString());

10、判断类型

//  是否为数组类
boolean isArray = aClass.isArray();
//  是否为接口类
boolean isInterface = aClass.isInterface();
//  是否为枚举类
boolean isEnum = aClass.isEnum();

四、案例

1、获取对应的名称

getName();

通过一个对象获得完整的包名+类名(java.util.HashMap)

HashMap<String, String> hashMap = new HashMap<>();
String name = hashMap.getClass().getName();
System.out.println(name);

2、获得类的简称(HashMap)

getSimpleName();

获得类的简称(HashMap)

HashMap<String, String> hashMap = new HashMap<>();
String typeName = hashMap.getClass().getSimpleName();
System.out.println(typeName);

3.实例化Class对象

forName("com.lydms.utils.Test")
package com.lydms.utils;
public class Test {
    public static void main(String[] args) throws ClassNotFoundException {
//      实例化Class对象(com.lydms.utils.Test)
        Class<?> aClass1 = Class.forName("com.lydms.utils.Test");
        Class<? extends Test> aClass2 = new Test().getClass();
        Class<Test> aClass3 = Test.class;
        System.out.println(aClass1.getName());
        System.out.println(aClass2.getName());
        System.out.println(aClass3.getName());
    }
}

4、获取一个对象的父接口和实现的接口

getSuperclass();    //父接口
getInterfaces();    //接口实现类
package com.lydms.utils;
import java.io.Serializable;

public class Test implements Serializable {
    public static void main(String[] args) throws ClassNotFoundException {

//        4、获取一个对象的父接口和实现的接口
        Class<?> aClass = Class.forName("com.lydms.utils.Test");
        Class<?> superclass = aClass.getSuperclass();
//        获取到的父类
        String parentName = superclass.getName();
        System.out.println("父类名为:" + parentName);
//        获得所有的接口实现类
        Class<?>[] interfaces = aClass.getInterfaces();
        for (int i = 0; i < interfaces.length; i++) {
            System.out.println("实现的接口为:" + interfaces[i]);
        }
    }
}

5、反射机制实例化一个类的对象

newInstance();            
getConstructors();        
getParameterTypes();    

方法一:

//  1、强转为指定格式对象
Class<?> aClass = Class.forName("com.lydms.utils.User");
User user = (User) aClass.newInstance();
user.setName("张三");
user.setAge(11);
System.out.println(user.toString());

方法二:

//  2、方式二(先获取方法对象,在取参数)
Constructor<?>[] constructors = aClass.getConstructors();
for (int i = 0; i < constructors.length; i++) {
    Class<?>[] parameterTypes = constructors[i].getParameterTypes();
    for (int i1 = 0; i1 < parameterTypes.length; i1++) {
        String name = parameterTypes[i1].getName();
        System.out.println("name"+name);
    }
}

实体类

package com.lydms.utils;

public class User {
    private String name;
    private int age;

    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public User() {
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

6、获取某个类的全部属性

aClass.getDeclaredFields();        //获取本类的全部属性(数组)
aClass1.getFields();            //获取实现的接口或父类的属性
fields[i].getModifiers()        //数字型权限修饰符
Modifier.toString(modifiers);    //将返回的数字型修饰符,转为string类型。(private static final)

获取本类的全部属性(数组)

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
public class Test{

    private static final long seriaVersionUID = 342342342;

    public static void main(String[] args) throws Exception {
        Class<?> aClass = Class.forName("com.lydms.utils.Test");

//        获取本类的全部属性(循环获取)
        Field[] fields = aClass.getDeclaredFields();
        for (int i = 0; i < fields.length; i++) {
//            权限修饰符(private static final)
            int modifiers = fields[i].getModifiers();
            String str = Modifier.toString(modifiers);
            System.out.println(str);

//            属性类型(long)
            Class<?> type = fields[i].getType();
//            private static final + long + seriaVersionUID;
            System.out.println(str + "+" + type.getName() + "+" + fields[i].getName() + ";");
        }
    }

获取实现的接口或父类的属性

public interface interfaceTest {
    static final long interfaceTest= 111111;
}
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
public class Test implements interfaceTest {
    public static void main(String[] args) throws Exception {
        Class<?> aClass = Class.forName("com.lydms.utils.Test");
        Field[] fields1 = aClass.getFields();
        for (int i = 0; i < fields1.length; i++) {
            int mo = fields1[i].getModifiers();
            String str = Modifier.toString(mo);
          
//            权限修饰符(private static final)
            System.out.println(str);
          
//            属性类型(long)
            Class<?> type = fields1[i].getType();
            System.out.println(type.getName());
          
//            方法的名称(interfaceTest)
            System.out.println(fields1[i].getName());
        }
    }
}

7、获取某个类的全部属性(修饰符,入参,返回值)

aClass.getMethods();        //获取类中所有方法
methods[i].getName()            //方法名
methods[i].getModifiers();        //修饰符
methods[i].getReturnType().getTypeName();    //返回值类型
methods[i].getParameterTypes();        //获取入参的对象
methods[i].getExceptionTypes()        //抛出的异常

待获取方法

package com.lydms.classes;
import java.io.IOException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

public class TestClass {
    public String getClass(String in) throws IOException {
        System.out.println("获取所有的方法");
        return null;
    }
}

获取TestClass中全部属性

public static void main(String[] args) throws Exception {
    Class<?> aClass = Class.forName("com.lydms.classes.TestClass");
    Method[] methods = aClass.getMethods();
    for (int i = 0; i < methods.length; i++) {
          1.方法名(getClass)
        String name = methods[i].getName();
          2.修饰符(public)
        int modifiers = methods[i].getModifiers();
        String modifierName = Modifier.toString(modifiers);
          3.返回值类型(java.lang.String)
        String name1 = methods[i].getReturnType().getName();
          4.入参的对象(class java.lang.String)
        Class<?>[] parameterTypes = methods[i].getParameterTypes();
          5. 抛出的异常( class java.io.IOException)
        Class<?>[] exceptionTypes = methods[i].getExceptionTypes();
    }
}

8、通过反射机制调用某个类的方法

aClass.newInstance()                    //闯将TestRun类的对象
test01.invoke(aClass.newInstance());    //执行test01方法

待获取方法

public class TestRun {
    public void test01(){
        System.out.println("执行Test01方法");
    }
    public void test02(int age,String name){
        System.out.println("执行Test02方法,其中年龄:"+age+",姓名:"+name);
    }
}

执行里面方法

public static void main(String[] args) throws Exception{
    Class<?> aClass = Class.forName("com.lydms.classes.TestRun");
    // 1、调用TestRun类中的test01()方法
    Method test01 = aClass.getMethod("test01");
    test01.invoke(aClass.newInstance());
    // 2、调用TestRun类中的test02()方法
    Method test02 = aClass.getMethod("test02", int.class, String.class);
    //  test02的执行,需要TestRun的对象,和2个入参
    test02.invoke(aClass.newInstance(),10,"李四");
}

9、更改类中属性

aClass.getDeclaredField("pro");        //获取里面参数pro的对象
pro.set(testObject, "新的参数");    //设置pro参数的值
pro.get(testObject)                //获取pro参数的值(TestFiled类对象)

待获取方法

public class TestFiled {
    private String pro = null;
}

执行里面方法

public static void main(String[] args) throws Exception {
    Class<?> aClass = Class.forName("com.lydms.classes.TestFiled");
    Field pro = aClass.getDeclaredField("pro");
    //  true 则指示反射的对象在使用时,应该取消Java 语言访问检查
    pro.setAccessible(true);
    Object testObject = aClass.newInstance();
    pro.set(testObject, "新的参数");
    /  打印更改后的参数值
    System.out.println(pro.get(testObject));
}

10、执行配置文件中指定的类中方法

配置文件application.properties

className=com.lydms.utils.TestClass
methodName=test

测试执行的方式:

package com.lydms.utils;

public class TestClass {
    
    public void test(){
        System.out.println("通过反射执行test中方法");
    }
}

反射使用代码:

import java.io.FileInputStream;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.Properties;

public class GoToClass {
    public static void main(String[] args) throws Exception {
//        1.1 创建Properties对象
        Properties pro = new Properties();

//        1.2 加载配置文件,转换为一个集合
        InputStream is = new FileInputStream("E:\Code\test\src\main\java\com\lydms\utils\TestClass.java");
//        加载配置信息
        pro.load(is);

//        2. 获取配置文件中定义的数据
        String className = pro.getProperty("className");
        String methodName = pro.getProperty("methodName");

//        3. 加载该类进内存
        Class cls = Class.forName(className);

//        4. 创建对象
        Object obj = cls.newInstance();

//        5. 获取方法对象
        Method method = cls.getMethod(methodName);

//        6. 执行方法
        method.invoke(obj);
    }
}

执行结果:
在这里插入图片描述

11、通过反射机制往List中添加任意类型的元素

注意:这只是演示反射机制,在正常的开发中不能这样使用(忽略了创建对象时,指定的类型)

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class ReflectDemo3 {
    public static void main(String[] args) throws Exception {
        List<Integer> list = new ArrayList<Integer>();
        list.add(11);

        //获取类
        Class<?> class1 = list.getClass();

        //获取方法
        Method addMethod = class1.getMethod("add", Object.class);

        //执行,添加任意类型对象
        addMethod.invoke(list, "asfdgh");
        addMethod.invoke(list, true);
        addMethod.invoke(list, new Date());
        System.out.println(list);
    }
}

12、更改方法上注解值

代码(更改board方法中@RequestMapping注解的值)

@RestController
@RequestMapping("/test")
public class BoardController {
   
   @RequestMapping(value = "/board", method = {RequestMethod.POST})
   public ApiResult board(@RequestBody Map<String, Object> params) throws Exception {

       return ApiResult.succ(null);
   }
}

获取方式

//  获取成员方法的class对象
Method board = BoardController.class.getMethod("board", Map.class);
// 获取 Test 上的注解
RequestMapping requestMapping = board.getAnnotation(RequestMapping.class);
// 获取代理处理器
InvocationHandler handler = Proxy.getInvocationHandler(requestMapping);
// 过去私有 memberValues 属性
Field f = handler.getClass().getDeclaredField("memberValues");
f.setAccessible(true);
// 获取实例的属性map
Map<String, Object> memberValues = (Map<String, Object>) f.get(handler);
// 修改属性值
memberValues.put("value", "/url");

五、Xmind整理

在这里插入图片描述
CSDN地址:

CSDN地址

百度网盘地址:

链接:https://pan.baidu.com/s/1_RKxpkZehV0wSFASdv-LXQ 
提取码:czz3
目录
相关文章
|
2天前
|
存储 缓存 安全
java 中操作字符串都有哪些类,它们之间有什么区别
Java中操作字符串的类主要有String、StringBuilder和StringBuffer。String是不可变的,每次操作都会生成新对象;StringBuilder和StringBuffer都是可变的,但StringBuilder是非线程安全的,而StringBuffer是线程安全的,因此性能略低。
|
19天前
|
存储 安全 Java
java.util的Collections类
Collections 类位于 java.util 包下,提供了许多有用的对象和方法,来简化java中集合的创建、处理和多线程管理。掌握此类将非常有助于提升开发效率和维护代码的简洁性,同时对于程序的稳定性和安全性有大有帮助。
41 17
|
11天前
|
安全 Java
Java多线程集合类
本文介绍了Java中线程安全的问题及解决方案。通过示例代码展示了使用`CopyOnWriteArrayList`、`CopyOnWriteArraySet`和`ConcurrentHashMap`来解决多线程环境下集合操作的线程安全问题。这些类通过不同的机制确保了线程安全,提高了并发性能。
|
15天前
|
存储 Java 程序员
Java基础的灵魂——Object类方法详解(社招面试不踩坑)
本文介绍了Java中`Object`类的几个重要方法,包括`toString`、`equals`、`hashCode`、`finalize`、`clone`、`getClass`、`notify`和`wait`。这些方法是面试中的常考点,掌握它们有助于理解Java对象的行为和实现多线程编程。作者通过具体示例和应用场景,详细解析了每个方法的作用和重写技巧,帮助读者更好地应对面试和技术开发。
55 4
|
26天前
|
Java API
Java 对象释放与 finalize 方法
关于 Java 对象释放的疑惑解答,以及 finalize 方法的相关知识。
45 17
|
16天前
|
Java 编译器 开发者
Java异常处理的最佳实践,涵盖理解异常类体系、选择合适的异常类型、提供详细异常信息、合理使用try-catch和finally语句、使用try-with-resources、记录异常信息等方面
本文探讨了Java异常处理的最佳实践,涵盖理解异常类体系、选择合适的异常类型、提供详细异常信息、合理使用try-catch和finally语句、使用try-with-resources、记录异常信息等方面,帮助开发者提高代码质量和程序的健壮性。
34 2
|
20天前
|
存储 安全 Java
如何保证 Java 类文件的安全性?
Java类文件的安全性可以通过多种方式保障,如使用数字签名验证类文件的完整性和来源,利用安全管理器和安全策略限制类文件的权限,以及通过加密技术保护类文件在传输过程中的安全。
|
20天前
|
Java 测试技术 Maven
Java一分钟之-PowerMock:静态方法与私有方法测试
通过本文的详细介绍,您可以使用PowerMock轻松地测试Java代码中的静态方法和私有方法。PowerMock通过扩展Mockito,提供了强大的功能,帮助开发者在复杂的测试场景中保持高效和准确的单元测试。希望本文对您的Java单元测试有所帮助。
45 2
|
21天前
|
Java 编译器 Maven
Java“class file contains wrong class”解决
当Java程序运行时出现“class file contains wrong class”错误,通常是因为类文件与预期的类名不匹配。解决方法包括:1. 确保类名和文件名一致;2. 清理并重新编译项目;3. 检查包声明是否正确。
|
24天前
|
Java 数据格式 索引
使用 Java 字节码工具检查类文件完整性的原理是什么
Java字节码工具通过解析和分析类文件的字节码,检查其结构和内容是否符合Java虚拟机规范,确保类文件的完整性和合法性,防止恶意代码或损坏的类文件影响程序运行。