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);
    }
}
相关推荐
不会c嘎嘎2 小时前
深入理解QT之信号和槽
开发语言·qt
SunnyDays10112 小时前
Python 实现 PDF 文档压缩:完整指南
linux·开发语言·python
大海星辰7982 小时前
工厂模式与策略模式的深度实践:从代码优化到架构思考
java·架构·策略模式
Cx330❀2 小时前
《C++ 动态规划》第001-002题:第N个泰波拉契数,三步问题
开发语言·c++·算法·动态规划
神仙别闹2 小时前
基于Qt5(C++)+SQLite 开发的一个小巧精美的本地音乐播放器
开发语言·c++·qt
Jack_abu2 小时前
详解java中的线程间协作工具:CountDownLatch,Semaphore,CyclicBarrier(二)
java·并发编程·juc
差点GDP2 小时前
C语言常用编译命令和示例
c语言·开发语言
weixin_307779132 小时前
Jenkins Pipeline: Input Step插件详解与实践指南
运维·开发语言·自动化·jenkins·etl
宵时待雨2 小时前
C语言笔记归纳21:编译与链接
linux·c语言·开发语言·笔记