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
目录
相关文章
|
1月前
|
存储 Java 索引
用Java语言实现一个自定义的ArrayList类
自定义MyArrayList类模拟Java ArrayList核心功能,支持泛型、动态扩容(1.5倍)、增删改查及越界检查,底层用Object数组实现,适合学习动态数组原理。
87 4
|
1月前
|
Java
Java语言实现字母大小写转换的方法
Java提供了多种灵活的方法来处理字符串中的字母大小写转换。根据具体需求,可以选择适合的方法来实现。在大多数情况下,使用 String类或 Character类的方法已经足够。但是,在需要更复杂的逻辑或处理非常规字符集时,可以通过字符流或手动遍历字符串来实现更精细的控制。
221 18
|
1月前
|
IDE JavaScript Java
在Java 11中,如何处理被弃用的类或接口?
在Java 11中,如何处理被弃用的类或接口?
160 5
|
1月前
|
JSON 网络协议 安全
【Java】(10)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
143 1
|
1月前
|
Java Go 开发工具
【Java】(8)正则表达式的使用与常用类分享
正则表达式定义了字符串的模式。正则表达式并不仅限于某一种语言,但是在每种语言中有细微的差别。
203 1
|
1月前
|
存储 Java 程序员
【Java】(6)全方面带你了解Java里的日期与时间内容,介绍 Calendar、GregorianCalendar、Date类
java.util 包提供了 Date 类来封装当前的日期和时间。Date 类提供两个构造函数来实例化 Date 对象。第一个构造函数使用当前日期和时间来初始化对象。Date( )第二个构造函数接收一个参数,该参数是从1970年1月1日起的毫秒数。
148 1
|
1月前
|
Java 编译器 Go
【Java】(5)方法的概念、方法的调用、方法重载、构造方法的创建
Java方法是语句的集合,它们在一起执行一个功能。方法是解决一类问题的步骤的有序组合方法包含于类或对象中方法在程序中被创建,在其他地方被引用方法的优点使程序变得更简短而清晰。有利于程序维护。可以提高程序开发的效率。提高了代码的重用性。方法的名字的第一个单词应以小写字母作为开头,后面的单词则用大写字母开头写,不使用连接符。例如:addPerson。这种就属于驼峰写法下划线可能出现在 JUnit 测试方法名称中用以分隔名称的逻辑组件。
196 4
|
1月前
|
JSON 网络协议 安全
【Java基础】(1)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
160 1
|
1月前
|
编解码 Java 开发者
Java String类的关键方法总结
以上总结了Java `String` 类最常见和重要功能性方法。每种操作都对应着日常编程任务,并且理解每种操作如何影响及处理 `Strings` 对于任何使用 Java 的开发者来说都至关重要。
262 5
|
2月前
|
算法 安全 Java
除了类,Java中的接口和方法也可以使用泛型吗?
除了类,Java中的接口和方法也可以使用泛型吗?
134 11
下一篇
oss云网关配置