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);
    }
}
相关推荐
Boilermaker19921 小时前
[Java 并发编程] Synchronized 锁升级
java·开发语言
Cherry的跨界思维1 小时前
28、AI测试环境搭建与全栈工具实战:从本地到云平台的完整指南
java·人工智能·vue3·ai测试·ai全栈·测试全栈·ai测试全栈
MM_MS1 小时前
Halcon变量控制类型、数据类型转换、字符串格式化、元组操作
开发语言·人工智能·深度学习·算法·目标检测·计算机视觉·视觉检测
꧁Q༒ོγ꧂2 小时前
LaTeX 语法入门指南
开发语言·latex
njsgcs2 小时前
ue python二次开发启动教程+ 导入fbx到指定文件夹
开发语言·python·unreal engine·ue
alonewolf_992 小时前
JDK17新特性全面解析:从语法革新到模块化革命
java·开发语言·jvm·jdk
一嘴一个橘子2 小时前
spring-aop 的 基础使用(啥是增强类、切点、切面)- 2
java
sheji34162 小时前
【开题答辩全过程】以 中医药文化科普系统为例,包含答辩的问题和答案
java
古城小栈2 小时前
Rust 迭代器产出的引用层数——分水岭
开发语言·rust
ghie90903 小时前
基于MATLAB的TLBO算法优化实现与改进
开发语言·算法·matlab