一些方法
首先说一下-getField/Method什么的这种不带Declared只能获取到对应public的属性/方法
只有带Declared可以获取到非public的属性/方法
再看不带s和带s区别
不带s只获取对应的构造器/方法
比如说构造器
getDeclaredConstructor(int.class,String class)
就会获取不管什么修饰符,参数类型为int,String的构造器
下面具体讲解
反射爆破创建实例(构造器)
注意:普通的Class对象.newInstance()已经弃用
一般现在是通过Class对象获取构造器,然后用 构造器.newInstance来创建对象
说明Constructor有一个方法
就是newInstance(参数),对应的参数填写看构造器
package yuan.hsp.reflection;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
//一些反射爆破
@SuppressWarnings({"all"})
public class reBlow {
public static void main(String[] args) throws InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException {
//先获取User的Class对象
Class<?> cls = User.class;
//1.通过public无参构造实例
User a =(User) cls.newInstance();//不过这个已经弃用了,最好不要用
User newInstance2 = (User)cls.getDeclaredConstructor().newInstance();//现在一般用这个方法
//先获取无参public然后newInstance
System.out.println(newInstance2);
//2.通过public的有参构造器创建
Constructor<?> constructor = cls.getConstructor(String.class);
// 我们传入的参数,变成对应参数类型的Class对象,才能获取对应的构造器
User bUser=(User) constructor.newInstance("小袁");
System.out.println(bUser);
//3.通过非public的有参构造器创建
//只有带Declared的方法才可能获取到非public的,可以看博客的图片在Java之类加载中
//先获取private的constructor
Constructor<?> declaredConstructor = cls.getDeclaredConstructor(int.class, String.class);
//注意,这里直接newInstance会报错,因为我们调用private的方法它会检测
//所以我们之前学过一个操作,也是提高反射效率的操作
declaredConstructor.setAccessible(true);//这个就叫做爆破,没有这句话会报错
// 这个参数是true会取消反射对象访问调查,所以我们就能在别的类用private属性/方法
//在反射面前,一切都是纸老虎
User cUser=(User)declaredConstructor.newInstance(1,"666");
System.out.println(cUser);
}
}
@SuppressWarnings({"all"})
class User{
private int age;
private String name;
public User() {
}
private User(int age,String name){
this.age=age;
this.name=name;
}
public User(String name){//无参public
this.name=name;
}
@Override
public String toString() {
return "User [age=" + age + ", name=" + name + "]";
}
}
所以我们的爆破就是
把Method/Field/Constructor运用setAccessible(true)方法取消访问调查来获取/修改类中非public的方法/字段/构造器
之前也是讲过,这个方法也会提高反射效率
反射爆破操作属性
package yuan.hsp.reflection;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
@SuppressWarnings({"all"})
//反射爆破属性
public class BlowField {
public static void main(String[] args) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException, NoSuchFieldException {
//1.获取Class类
Class<Student> student = Student.class;
//2.创建对象
Student newInstance = student.getDeclaredConstructor().newInstance();
//3.使用反射得到age属性对象
//public的可以直接修改操作
Field field = student.getField("age");
field.set(newInstance, 88);
System.out.println(newInstance);
//4.反射爆破操作name
Field field2 = student.getDeclaredField("name");
//还是如果没有取消访问调查,无论对对象进行修改操作,都会出错
System.out.println(field2);
field2.setAccessible(true);//加上这句就ok了
// field2.set(newInstance, "小袁");//注意就静态变量的设置方式有多种1.实例对象2.null3.0
field2.set(null, "我");
System.out.println(newInstance);
}
}
@SuppressWarnings({"all"})
class Student{
public int age;
private static String name;
public Student(){
}
@Override
public String toString() {
return name+" "+age;
}
}
反射爆破操作属性
package yuan.hsp.reflection;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
//爆破方法
@SuppressWarnings({"all"})
public class BlowMeghod {
public static void main(String[] args) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
//获取Class对象
Class boss = boss.class;
//创建对象
Object newInstance = boss.getDeclaredConstructor().newInstance();
Method hi = boss.getDeclaredMethod("hi",String.class);//注意,如果方法有参数,在方法名后面就是参数列表对应class对象,不然获取不到
//调用
hi.invoke(newInstance, "6666");
//爆破,调用private static方法
Method declaredMethod = boss.getDeclaredMethod("say", int.class, String.class, char.class);
declaredMethod.setAccessible(true);
System.out.println(declaredMethod.invoke(null, 2,"个",'c'));//因为是private直接用会报错,要取消一下访问调查
//null可以换成0/对象实例,因为是静态的
//方法.invoke中的返回值默认都是Object打var的话,运行类型就是方法的返回类型
}
}
@SuppressWarnings({"all"})
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);
}
}
共通
一.就是修改静态属性/调用静态方法
那个对象占用的部分可以有三个值
1.实例对象2.null3.0
都可以,因为是静态的
二.getDeclared…可以获取所有修饰符修饰的
get…只能获取public修饰的
三.方法有参数的话
getDeclaredMethod(“方法名”,参数列表第一个对应class对象,参数列表第二个对应class对象,…)才能获取对应方法
四.注意用非public属性/方法/构造器
先爆破!
setAccessible(true)