Reflection(反射)是Java被视为动态语言(动态语言:程序在运行时可以改变其结构:新的函数可以引进,已有的函数可以被删除等结构上的变化)的关键,反射机制允许程序在执行期借助于Reflection API取得任何类的內部信息,并能直接操作任意对象的内部属性及方法。
一句话概括:反射就是把Java类中的各种成分映射成一个个的Java对象
简单画了个图,凑合看吧,自己的理解,如有大神希望多多指教
首先创建一个Student类,为了后面操作方便,在类里面分别创建了四种不同访问权限的构造函数,成员变量以及成员方法
package com.example.testdemo.classforname;
public class Student {
//构造方法
public Student() {
System.out.println("(公有)的构造器被执行了---------");
}
public Student(String name, int age) {
this.age = age;
this.name = name;
System.out.println("(公有带参)的构造器被执行了---------");
}
Student(String name) {
this.name = name;
System.out.println("(默认)的构造器被执行了---------");
}
private Student(int age) {
this.age = age;
System.out.println("(私有)的构造器被执行了---------");
}
protected Student(double grade) {
this.grade = grade;
System.out.println("(受保护)的构造器被执行了---------");
}
//成员变量
String name;
private int age;
public double grade;
public int classNumber;
protected String sex;
//成员函数
void method1(String name) {
System.out.println("(默认)的方法被执行了---------");
}
public void method2() {
System.out.println("(公有)的方法被执行了---------");
}
private void method3(double grade) {
System.out.println("(私有)的方法被执行了---------");
}
protected void method4(String sex) {
System.out.println("(受保护)的方法被执行了---------");
}
@Override
public String toString() {
return "[name:" + name + ",age:" + age + ",grade:" + grade + ",sex:" + sex + ",classNumber:" + classNumber + "]";
}
public static void main(String[] args) {
System.out.println("main方法被执行" + args.toString());
}
}
反射的使用在这里大致分为四个部分:
获取class对象
获取class对象有三种方式
package com.example.testdemo.classforname;
/**
* 获取class对象
*/
public class Test {
public static void main(String[] args) throws Exception {
//获取class文件的三种方法:
//1,根据对象获取class(无意义)已经有对象
Student student = new Student();
Class clazz = student.getClass();
//2,根据对象.class(无意义)一般需要导入类的相关包
clazz = Student.class;
//3,根据类名获取class(推荐使用)
clazz = Class.forName("com.example.testdemo.classforname.Student");
System.out.println(clazz);
//class对象获取实例对象
Object object= clazz.newInstance();
System.out.println(object);
}
}
获取构造函数
package com.example.testdemo.classforname;
import java.lang.reflect.Constructor;
/**
* 获取class对象的构造函数
*/
public class Test1 {
public static void main(String[] args) throws Exception {
//获取class对象
Class clazz = Class.forName("com.example.testdemo.classforname.Student");
//分为两组
//第一组:1,获取单个(公有)构造函数
System.out.println("获取单个(公有)构造函数---------");
Constructor constructor = clazz.getConstructor();
System.out.println(constructor);
constructor = clazz.getConstructor(String.class, int.class);//获取有参构造需要传入参数类型
System.out.println(constructor);
//第一组:2,获取单个(所有包括公有的,私有的,默认的,受保护的)构造函数
System.out.println("获取单个(所有包括公有的,私有的,默认的,受保护的)构造函数---------");
constructor = clazz.getDeclaredConstructor(String.class);//获取有参构造需要传入参数类型
System.out.println(constructor);
//根据不同构造器创建实例对象
Object obj = constructor.newInstance("张三");
System.out.println(obj);
//第二组:1,获取多个(公有)构造函数
System.out.println("获取多个(公有)构造函数---------");
Constructor[] constructors = clazz.getConstructors();
for (Constructor c : constructors) {
System.out.println(c);
}
//第二组:2,获取多个(所有包括公有的,私有的,默认的,受保护的)构造函数
System.out.println("获取多个(所有包括公有的,私有的,默认的,受保护的)构造函数---------");
constructors = clazz.getDeclaredConstructors();
for (Constructor c : constructors) {
System.out.println(c);
}
}
}
获取成员变量
package com.example.testdemo.classforname;
import java.lang.reflect.Field;
/**
* 获取class对象的成员变量
*/
public class Test2 {
public static void main(String[] args) throws Exception {
//获取class对象
Class clazz = Class.forName("com.example.testdemo.classforname.Student");
//分为两组
//第一组:1,获取单个(公有)成员变量
System.out.println("获取单个(公有)成员变量---------");
Field field = clazz.getField("grade");//需要传入成员变量名称
System.out.println(field);
//第一组:2,获取单个(所有包括公有的,私有的,默认的,受保护的)成员变量
System.out.println("获取单个(所有包括公有的,私有的,默认的,受保护的)成员变量---------");
field = clazz.getDeclaredField("age");//需要传入成员变量名称
System.out.println(field);
//获取私有属性并赋值
Object obj = clazz.newInstance();
//age是私有属性,需要暴力设置
field.setAccessible(true);
field.set(obj,15);
System.out.println(obj);
//第二组:1,获取多个(公有)成员变量
System.out.println("获取多个(公有)成员变量---------");
Field[] fields = clazz.getFields();
for (Field f : fields) {
System.out.println(f);
}
//第二组:2,获取多个(所有包括公有的,私有的,默认的,受保护的)成员变量
System.out.println("获取多个(所有包括公有的,私有的,默认的,受保护的)成员变量---------");
fields = clazz.getDeclaredFields();
for (Field f : fields) {
System.out.println(f);
}
}
}
获取成员方法
package com.example.testdemo.classforname;
import java.lang.reflect.Method;
/**
* 获取成员方法
*/
public class Test3 {
public static void main(String[] args) throws Exception {
//获取class对象
Class clazz = Class.forName("com.example.testdemo.classforname.Student");
//分为两组
//第一组:1,获取单个(公有)成员方法
System.out.println("获取单个(公有)成员方法---------");
Method m = clazz.getMethod("method2");//需要传入成员方法名称,有参数需要传入参数
System.out.println(m);
//第一组:2,获取单个(所有包括公有的,私有的,默认的,受保护的)成员方法
System.out.println("获取单个(所有包括公有的,私有的,默认的,受保护的)成员变量---------");
m = clazz.getDeclaredMethod("method3",double.class);//需要传入成员方法名称
System.out.println(m);
//获取方法后执行
Object obj = clazz.newInstance();
//method3是私有方法需要暴力设置
m.setAccessible(true);
m.invoke(obj,89.50);//传入方法需要的参数
//第二组:1,获取多个(公有)成员方法
System.out.println("获取多个(公有)成员方法--------");
Method[] methods = clazz.getMethods();
for (Method m1 : methods) {
System.out.println(m1);
}
//第二组:2,获取多个(所有包括公有的,私有的,默认的,受保护的)成员方法
System.out.println("获取多个(所有包括公有的,私有的,默认的,受保护的)成员方法---------");
methods = clazz.getDeclaredMethods();
for (Method m1 : methods) {
System.out.println(m1);
}
}
}
突发奇想能不能获取类中的main方法?不说了,直接上代码测试
package com.example.testdemo.classforname;
import java.lang.reflect.Method;
/**
* 获取class中的main方法
*/
public class Test4 {
public static void main(String[] args) throws Exception {
//获取class对象
Class clazz = Class.forName("com.example.testdemo.classforname.Student");
//main方法是公有方法
Method method = clazz.getMethod("main",String[].class);
//main方法没有对象(静态方法),需要注意invoke传入的参数是object类型必须强转,不然出现异常
method.invoke(null,(Object) new String[]{"aaaaa"});
}
}
依然是可以拿到的,以前觉得反射没有什么用,除了在jdbc的时候使用,最近看了一些框架,基本都是反射,编程的路漫漫,我们一起走吧