通过反射创建对象:
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);
}
}