Java_反射暴破创建对象与访问类中的成员

通过反射创建对象:

1.方式一:调用类中的public修饰的无参构造器

2.方式二:调用类中的指定构造器

3.Class类相关方法:

newInstance:调用类中的无参构造器,获取对应类的对象

getConstructor(Class ....class):根据参数列表,获取对应的public构造器对象

getDecalaredConstructor(Class ....class):根据参数列表,获取对应的所有构造器对象

4.Constructor类相关方法:

setAccessible:爆破

newInstance(Object ...obj):调用构造器

案例演示:

测试1:通过反射创建某类的对象,要求该类中必须有public的无参构造

测试2:通过调用某个特定构造器的方式,实现创建某类的对象

java 复制代码
package com.reflection.ReflactionCreateInstance;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class ReflectionCreateInstance {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
        //先获取到User类的Class对象
        Class<?> userClass = Class.forName("com.reflection.ReflactionCreateInstance.User");

        //通过public的无参构造器创建实例
        Object o = userClass.newInstance();

        //通过public的有参构造器创建实例
        //先得到对应的构造器,再去创建实例,并传入实参
        /*
            constructor对象就是
            public User(String name) {  //有参public
                this.name = name;
            }
            String.class 是获取 String 类的 Class 对象,用于在反射中标识参数类型
         */
        Constructor<?> constructor = userClass.getConstructor(String.class);
        Object o1 = constructor.newInstance("大黄");//通过newInstance为形参赋值

        //通过非public的有参构造器创建实例
        Constructor<?> declaredConstructor = userClass.getDeclaredConstructor(int.class, String.class);
        //暴破
        declaredConstructor.setAccessible(true);//暴破(暴力破解)使用反射,可以访问非公有的(private等)修饰的构造器
        Object o2 = declaredConstructor.newInstance(5, "小黄");
        System.out.println(o2);
    }
}
class User{
    private int age = 10;
    private String name = "泥嚎";

    public User() { //无参public
    }

    public User(String name) {  //有参public
        this.name = name;
    }

    private User(int age, String name) {    //有参private
        this.age = age;
        this.name = name;
    }

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

通过反射访问类中的成员:

一.访问属性:

1.根据属性名获取field对象

java 复制代码
Field f = clazz对象.getDeclaredField(属性名);

2.暴破:

java 复制代码
f.setAccessible(true);//f是Field

3.访问

java 复制代码
f.set(o,值);//o表示对象
System.out.println(f.get(o));

4.如果是静态属性,则set和get中的参数o,可以写成null

案例演示:

java 复制代码
package com.reflection.ReflectionAccessProperty;

import java.lang.reflect.Field;

//演示反射访问(操作)属性
public class ReflectionAccessProperty_ {
    public static void main(String[] args) throws Exception{
        //1.得到student类对应的class对象
        Class<?> stuClass = Class.forName("com.reflection.ReflectionAccessProperty.Student");
        //2.创建对象
        Object o = stuClass.newInstance();//o的运行类型就是Student
        System.out.println(o.getClass());//Student
        //3.使用反射得到age 属性对象
        Field age = stuClass.getField("age");
        age.set(o,88);//通过反射来操作属性
        System.out.println(o);//Student{age=88,name=null}
        System.out.println(age.get(o));//88,这样也可以
        //4.使用反射操作name属性
        //先得到name对应的field对象
        Field name = stuClass.getDeclaredField("name");//name是私有的,不能使用getField()
        name.setAccessible(true);
        name.set(o,"张三");
        name.set(null,"张三");//这样也可以,因为name是静态的,设置为null就等于给Student的所有实例都设置为"张三"
        System.out.println(name.get(o));//张三
        System.out.println(name.get(null));//张三,只有静态属性才能置空
    }
}
class Student{
    public int age;
    private static String name;

    public Student() {
    }

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

二.访问方法:

1.根据方法名和参数列表获取Method方法对象:

java 复制代码
Method m = clazz.getDeclaredMethod(方法名,XX.class);//得到本类的所有方法

2.获取对象:

java 复制代码
Object o = clazz.newInstance();

3.暴破:

java 复制代码
m.setAccessible(true);

4.访问:

java 复制代码
Object returnValue = m.invoke(o,实参列表);

5.如果是静态方法,则invoke的参数o,可以写成null

案例演示;

java 复制代码
package com.reflection.ReflectionAccessMethod;

import java.lang.reflect.Method;

//演示通过反射调用方法
public class ReflectionAccessMethod {
    public static void main(String[] args) throws Exception{
        //得到boss类对应的class对象
        Class<?> bossClass = Class.forName("com.reflection.ReflectionAccessMethod.Boss");
        //创建对象
        Object o = bossClass.newInstance();

        //调用public方法
        //得到hi()对象
        Method hi = bossClass.getMethod("hi", String.class);
        //调用
        hi.invoke(o, "熊大");

        //调用非public的静态方法
        //得到say()对象
        Method say = bossClass.getDeclaredMethod("say", int.class,String.class, char.class);
        say.setAccessible(true);
        System.out.println(say.invoke(o,5,"熊二",'a'));
        //因为say()是静态的,还可以将对象置空
        System.out.println(say.invoke(null,5,"熊二",'a'));

        //返回值
        //在反射中,如果方法有返回值,统一返回Object,但是它的运行类型和实际方法返回的类型是一样的
        Object o1 = say.invoke(null, 300, "熊三", '男');
        System.out.println(o1);//300 熊三 男
    }
}
class Boss{
    public int age;
    private static String name;

    public Boss() { //构造器
    }

    private static String say(int n,String s,char c){   //静态方法
        return n + " " + s + " " + c;
    }

    public void hi(String s){     //普通方法
        System.out.println("hi" + s);
    }
}
相关推荐
清心歌10 小时前
CopyOnWriteArrayList 实现原理
java·开发语言
Java成神之路-10 小时前
通俗易懂理解 Spring MVC 拦截器:概念、流程与简单实现(Spring系列16)
java·spring·mvc
zhanghongbin0110 小时前
AI 采集器:Claude Code、OpenAI、LiteLLM 监控
java·前端·人工智能
良木生香10 小时前
【C++初阶】C++入门相关知识(2):输入输出 & 缺省参数 & 函数重载
开发语言·c++
计算机毕设vx_bysj686910 小时前
【免费领源码】77196基于java的手机银行app管理系统的设计与实现 计算机毕业设计项目推荐上万套实战教程JAVA,node.js,C++、python、大屏数据可视化
java·mysql·智能手机·课程设计
忘梓.10 小时前
墨色规则与血色节点:C++红黑树设计与实现探秘
java·开发语言·c++
hhh3u3u3u10 小时前
Visual C++ 6.0中文版安装包下载教程及win11安装教程
java·c语言·开发语言·c++·python·c#·vc-1
星河耀银海10 小时前
C++ 模板进阶:特化、萃取与可变参数模板
java·开发语言·c++
cccccc语言我来了10 小时前
【C++---unordered_set/map底层封装】个不拘一格的集合。它不似有序集合那般循规蹈矩,而是以一种洒脱不羁的方式,将元素们随意地散落其中。每一个元素都是独一无二的。
开发语言·c++·哈希算法
Zfox_10 小时前
C++ IO流全解析:标准库中的数据处理与文件读写艺术
开发语言·c++