一,反射
–1,概述
反射机制指的是程序在运行时能够获取自身的信息。在 Java 中,只要给定类的名字,就可以通过反射机制来获得类的所有信息。private的只能类内部访问,外部是不行的,但这个规定被反射赤裸裸的打破了。
Java 反射机制在服务器程序和中间件程序中得到了广泛运用。在服务器端,往往需要根据客户的请求,动态调用某一个对象的特定方法。此外,在 ORM 中间件的实现中,运用 Java 反射机制可以读取任意一个 JavaBean 的所有属性,或者给这些属性赋值。
--2,作用
--拿到.class文件里的数据进行解析.
--获取文件里的所有数据(公开的.私有的.构造.属性.方法)
--并把所有数据封装在Class对象身上.
--3,获取Class对象
Class.forName(“类的全路径”);
类名.class
对象.getClass();
--4,常用方法
二,反射的应用
–1,创建Student类
package cn.tedu.reflect;
//配合 测试 反射
public class Student {
//构造方法-generate-constructor-多选ctrl/单选-ok
public Student() {
}
public Student(String name) {
this.name = name;
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public Student(String name, int age, double score) {
this.name = name;
this.age = age;
this.score = score;
}
String name ;
int age ;
double score ;
public void study(){
System.out.println("study()");
}
public void coding(){
System.out.println("coding()");
}
}
--2,测试
package cn.tedu.reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;
//测试 反射 获取Class对象
public class Test2_ReflectStudent {
public static void main(String[] args) throws Exception {
// method();//获取Class对象
// method2();//获取构造方法
// method3();//获取成员方法
// method4();//获取成员变量
method5();//通过反射的技术创建对象
}
//创建对象
public static void method5() throws Exception {
//1,获取Class对象
Class<Student> clazz = Student.class ;
//2,调用实例化方法 --也要触发构造方法,而且触发的是无参构造
//newInstance()必须提供无参构造,否则[抛出异常:java.lang.InstantiationException: cn.tedu.reflect.Student
Student s = clazz.newInstance();
System.out.println("s = " + s);
//重写toString()前:s = cn.tedu.reflect.Student@1b6d3586
//重写toString()后:s = Student{name='null', age=0, score=0.0}
//怎么触发含参构造--触发public Student(String name)
//getConstructor(m);--m参数要 匹配构造方法里 参数的类型 的Class对象
Constructor<Student> c = clazz.getConstructor(String.class);//指定
//newInstance(x)--x是你创建对象时具体的参数
Student s2 = c.newInstance("jack");
System.out.println("s2 = " + s2);
//TODO 触发public Student(String name, int age)
Constructor<Student> c2 = clazz.getConstructor(String.class,int.class);
Student s3 = c2.newInstance("xiongda",20) ;
System.out.println("s3 = " + s3);
}
//获取成员变量
public static void method4() {
//1,获取Class对象
Class clazz = Student.class ;
//2,获取所有成员变量 -- 只能获取公开的变量
Field[] fs = clazz.getFields();
//3,遍历数组,得到每个变量f
for (Field f : fs) {
//4,获取变量名称
System.out.println(f.getName());
//5,获取变量类型
System.out.println(f.getType().getName() );
}
}
//获取成员方法
public static void method3() {
//1,获取Class对象
Class<Student> clazz = Student.class ;
//2,获取所有成员方法们 -- 包括自己的和父类的 的公开的方法们
Method[] ms = clazz.getMethods() ;
//3,遍历数组,得到每个方法m
for (Method m : ms) {
//4,获取方法名称
System.out.println(m.getName());
//5,获取方法的参数的类型
Class<?>[] cs = m.getParameterTypes();
System.out.println(Arrays.toString(cs));
}
}
//获取构造方法
public static void method2() {
//1,获取Class对象 --封装了.class文件里的所有数据
Class clazz = Student.class ;
//2,获取所有构造方法们 , 并存入数组 -- 只能反射 公开的 资源
Constructor[] cs = clazz.getConstructors();
//3,获取每个构造方法c
for (Constructor c : cs) {
//4,获取构造方法的名字
System.out.println( c.getName() );
//5,获取构造方法的参数类型 们
Class[] css = c.getParameterTypes();
System.out.println( Arrays.toString(css) );
}
}
//获取Class对象
public static void method() throws ClassNotFoundException {
Class c = Class.forName("cn.tedu.reflect.Student");//参数是类的全路径
Class c2 = Student.class ;
// Class c3 = new Student().getClass() ;//使用了父类Object提供的getClass()
// System.out.println("c3 = " + c3);
// System.out.println("c2 = " + c2);
// System.out.println("c = " + c);
}
}
三,暴力反射
–作用 : 不仅能获取到类的public资源,也可以获取到类里的private资源
–API :
–普通反射
–getConstructor()
–getConstructors()
–getMethod()
–getMethods()
–getField()
–getFields()
–暴力反射
–getDeclaredConstructor()
–getDeclaredConstructors()
–getDeclaredMethod()
–getDeclaredMethods()
–getDeclaredField()
–getDeclaredFields()
–1,创建Person类
package cn.tedu.reflect;
//配置暴力反射
public class Person {
public String name;
public int age;
private double score;
public void eat() {
System.out.println("eat()");
}
public void sleep(int a, String b) {
System.out.println("sleep()");
}
private void game(String x) {
System.out.println("game()");
}
}
--2,测试
package cn.tedu.reflect;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;
//测试 暴力反射:
//条件 : 使用getDeclaredXxx() + 开启私有可见的权限
public class Test3_BaoliReflect {
public static void main(String[] args) throws Exception {
// method();//暴力反射成员方法们
method2();//暴力反射成员变量
}
//暴力反射成员变量们
public static void method2() throws Exception {
//1,获取Class对象
Class clazz = Person.class ;
//2,暴力反射
Field[] fs = clazz.getDeclaredFields();
//3,遍历数组,得到每个变量f
for (Field f : fs) {
//4,获取变量名称
System.out.println(f.getName());
//5,获取变量类型
System.out.println(f.getType().getName() );
}
//获取指定的变量
Field f = clazz.getDeclaredField("score") ;
//开启 访问权限,否则访问私有抛出异常:IllegalAccessException:
f.setAccessible(true);
Object obj = clazz.newInstance() ;
//设置值--set(1,2)--1是指对象名称--2是要设置的具体值
f.set(obj,99.9);
//获取值--get(1)--1是指对象名称
System.out.println( f.get(obj) );
}
//暴力反射成员方法们
public static void method() throws Exception {
//1,获取Class对象
Class<Person> clazz = Person.class ;
//2,暴力反射 -- getDeclaredMethods()
Method[] ms = clazz.getDeclaredMethods() ;
//3,遍历数组,得到每个方法m
for (Method m : ms) {
//4,获取方法名称
System.out.println(m.getName());
//5,获取方法的参数的类型
Class<?>[] cs = m.getParameterTypes();
System.out.println(Arrays.toString(cs));
}
//暴力反射 某个方法
//getDeclaredMethod(1,2)--获取指定的方法
//--1是指方法名--2是指方法需要的参数类型的Class对象
Method m = clazz.getDeclaredMethod("game",String.class) ;
//暴力反射:除了用对API,另外还需要开启访问权限
m.setAccessible(true);
Object obj = clazz.newInstance() ;
//执行方法--invoke(1,2)--1是指对象名称--2是方法需要传入的参数
m.invoke(obj,"tony") ;
}
}
补充:反射注解方法
–改造Person类
package cn.tedu.reflect;
import org.junit.Test;
//配置暴力反射
public class Person {
@Test
public void show(){
System.out.println(123);
}
public String name;
public int age;
private double score;
public void eat() {
System.out.println("eat()");
}
public void sleep(int a, String b) {
System.out.println("sleep()");
}
private void game(String x) {
System.out.println("game()");
}
}
--改造测试类
package cn.tedu.reflect;
import org.junit.Test;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;
//测试 暴力反射:
//条件 : 使用getDeclaredXxx() + 开启私有可见的权限
public class Test3_BaoliReflect {
public static void main(String[] args) throws Exception {
// method();//暴力反射成员方法们
// method2();//暴力反射成员变量
method3();//反射注解方法
}
//反射注解方法
public static void method3() throws Exception {
//1,获取Class对象
Class clazz = Person.class ;
//2,获取show()
Method m = clazz.getDeclaredMethod("show",null);
//3,获取Test注解的标志
// getDeclaredAnnotation(1)--参数1是注解类型 的class对象
Test test = m.getDeclaredAnnotation(Test.class) ;
Object obj = clazz.newInstance() ;
//4,判断有注解的话,就运行
if(test != null){
m.invoke(obj) ;//运行方法
}
}
//暴力反射成员变量们
public static void method2() throws Exception {
//1,获取Class对象
Class clazz = Person.class ;
//2,暴力反射
Field[] fs = clazz.getDeclaredFields();
//3,遍历数组,得到每个变量f
for (Field f : fs) {
//4,获取变量名称
System.out.println(f.getName());
//5,获取变量类型
System.out.println(f.getType().getName() );
}
//获取指定的变量
Field f = clazz.getDeclaredField("score") ;
//开启 访问权限,否则访问私有抛出异常:IllegalAccessException:
f.setAccessible(true);
Object obj = clazz.newInstance() ;
//设置值--set(1,2)--1是指对象名称--2是要设置的具体值
f.set(obj,99.9);
//获取值--get(1)--1是指对象名称
System.out.println( f.get(obj) );
}
//暴力反射成员方法们
public static void method() throws Exception {
//1,获取Class对象
Class<Person> clazz = Person.class ;
//2,暴力反射 -- getDeclaredMethods()
Method[] ms = clazz.getDeclaredMethods() ;
//3,遍历数组,得到每个方法m
for (Method m : ms) {
//4,获取方法名称
System.out.println(m.getName());
//5,获取方法的参数的类型
Class<?>[] cs = m.getParameterTypes();
System.out.println(Arrays.toString(cs));
}
//暴力反射 某个方法
//getDeclaredMethod(1,2)--获取指定的方法
//--1是指方法名--2是指方法需要的参数类型的Class对象
Method m = clazz.getDeclaredMethod("game",String.class) ;
//暴力反射:除了用对API,另外还需要开启访问权限
m.setAccessible(true);
Object obj = clazz.newInstance() ;
//执行方法--invoke(1,2)--1是指对象名称--2是方法需要传入的参数
m.invoke(obj,"tony") ;
}
}