反射的概述
Java的反射机制:是指在运行去获取一个类的变量和方法信息,然后通过获取到的信息来创建对象,调用方法的一种机制。由于这种动态性,可以极大的增强程序的灵活性,程序不用再编译期就完成确定,在运行期仍然可以扩展。
通过反射获取到构造方法:
先说只能获取到一个构造方法的方法:
Class c=Class.forName("Reflect.Student");//引号中的为学生类的路径
Constructor con=c.getConstructor();//获取无参构造方法
Student s=(Student)con.getInstance();
下面的和上面的相同(这里说明在调用反射时需要抛出异常)
public static void method01(String addr){
//构造方法通过反射来调用
try{
//字节码,代表Student类在内存中的字节码对象
Class clazz=Class.forName(addr);
Constructor cs = clazz.getConstructor();//获取到构造方法->无参构造方法
//cs.newInstance();//通过无参构造创建对象
Student s=(Student) cs.newInstance();
}catch (Exception e){
e.printStackTrace();
}
}
下面来进行扩展
获取构造方法处:
(1).Constructor con=c.getConstructor(String.class,int.class);//这里是有参构造方法
Student s=(Student) con.newInstance("李四",28);//使用构造方法进行赋值
(2).Constructor con=c.getConstructor(int.class);
Student s=(Student) con.newInstance(28);//使用构造方法进行赋值
系统会根据参数的个数自动去获取是哪个构造方法,以上几种只能获取到共有的构造方法。
下面进行私有的构造方法的获取:
Constructor con=c.getDeclaredConstructor();
con.setAccessible(true);
Constructor con=c.getDeclaredConstructor(String.class,int.class);
con.setAccessible(true);//在获取私有的构造方法时,需要调用该方法,取消访问检查,也叫作暴力反射
Student s=(Student) con.newInstance("李四",28);//使用构造方法进行赋值
下面来介绍可以获取全部的构造方法的方法:
Class c=Class.forName("Reflect.Student");//引号中的为学生类的路径
Constructor[ ] con=c.getConstructors();//注意这里加了s,该方法可以获取所有的公有属性的构造方法
Constructor[ ] con=c.getDeclaredConstructors();//该方法可以获取到所有的构造方法(包括私有的构造方法)
以下时代码实现
private static void method01() {
try{
Class c=Class.forName("Reflect.Student");
//获取字节码中共有化的构造方法
Constructor[] con = c.getConstructors();
for (Constructor co:con) {
System.out.println(co);
}
//获取所有的构造方法
Constructor[] caAll=c.getDeclaredConstructors();
for (Constructor co1:caAll) {
System.out.println(co1);
}
}catch (Exception e){
e.printStackTrace();
}
}
通过反射来获取成员方法:
先时获取一个成员方法的方法,并且只能获取到一个方法(而且还是共有的成员方法):
Class c=Class.forName("Reflect.Student");
Student s=c.getInstance();//获取无参构造方法
Method m=c.getMethod("getName",String.class);//引号中为需要调用的方法名,后面的为参数,没有就不写
Method m=c.getMethod("getName");
m.invoke(s,"李四");//s为创建的学生对象,李四为传进去的参数,没有同样不写
m.invoke(s);//理解为对象s调用方法m,方法m反射给对象
public static void method05(String addr){
try{
Class clazz=Class.forName(addr);
//通过无参构造方法创建对象
Student s=(Student) clazz.newInstance();
//通过方法名及参数列表获取对应的方法
Method m=clazz.getMethod("setBirthday",Date.class);
m.invoke(s,new Date());//方法的调用
}catch (Exception e){
e.printStackTrace();
}
}
public static void method06(String addr){
try{
Class clazz=Class.forName(addr);
//通过无参构造方法创建对象
Student s=(Student) clazz.newInstance();
//通过方法名及参数列表获取对应的方法
Method m=clazz.getMethod("addStuNames",String[].class);
//m.setAccessible(true);
m.invoke(s,(Object) new String[]{"123","hqj","lsj"});//方法的调用
}catch (Exception e){
e.printStackTrace();
}
}
接下来能获取到私有的成员方法:
Class c=Class.forName("Reflect.Student");
Student s=(Student)c.getInstance();
Method m=c.getDeclaredMethod("getName");
m.setAccessible();
m.invoke(s);
//如果方法中有参数
Method m=c.getDeclaredMethod("getName",String.calss);
m.setAccessible();
m.invoke(s,"李四");
private static void method03(String addr) {
try{
Class clazz=Class.forName(addr);
//通过无参构造方法创建对象
Student s=(Student) clazz.newInstance();
//通过方法名及参数列表获取对应的方法
Method m=clazz.getMethod("getName");
String name=(String) m.invoke(s);//方法的调用
System.out.println("返回的值:"+name);
}catch (Exception e){
e.printStackTrace();
}
}
private static void method04(String addr) {
try{
Class clazz=Class.forName(addr);
//通过无参构造方法创建对象
Student s=(Student) clazz.newInstance();
//通过方法名及参数列表获取对应的方法
Method m=clazz.getDeclaredMethod("youName");
m.setAccessible(true);//值为true是取消访问检查
m.invoke(s);//方法的调用
//System.out.println("返回的值:"+name);
}catch (Exception e){
e.printStackTrace();
}
}
接下来介绍获取全部方法的方法:
private static void method02() {
try{
Class c=Class.forName("Reflect20210629.Student");
System.out.println("........公有化.......");
Method ms[]=c.getMethods();
for (Method m:ms) {
System.out.println(m);
}
System.out.println("所有方法不含继承的方法");
Method msAll[]=c.getDeclaredMethods();
for (Method s:msAll){
System.out.println(s);
}
}catch (Exception e){
e.printStackTrace();
}
}
通过反射来获取成员变量:
方法与获取成员方法相同,此处就不作解释,直接放代码例子:
先是获取单个成员变量的:method01只能获取到公有成员,method02能获取公有和私有的成员
private static void method01(String addr) {
try{
Class clazz=Class.forName(addr);
Student s=(Student)clazz.newInstance();
//获取属性
Field f=clazz.getField("age");
//set值
f.set(s,20);
//s.age=40;
//get值
int age=(int)f.get(s);
System.out.println(age);
//age=s.age;
}catch (Exception e){
e.printStackTrace();
}
}
private static void method02(String addr) {
try{
Class clazz=Class.forName(addr);
Student s=(Student)clazz.newInstance();
//获取属性
Field f=clazz.getDeclaredField("name");
f.setAccessible(true);
//set值
f.set(s,"yjw1123");
//s.age=40;
//get值
String name=(String) f.get(s);
System.out.println(name);
//age=s.age;
}catch (Exception e){
e.printStackTrace();
}
}
获取全部变量的:
private static void method03() {
try{
Class c=Class.forName("Reflect20210629.Student");
System.out.println(">>>>>>>>>>>公有属性>>>>>>>>>");
Field[] fs=c.getFields();
for (Field f:fs) {
System.out.println(f);
}
System.out.println("...........所有属性..........");
Field fsAll[]=c.getDeclaredFields();
for (Field f:fsAll) {
System.out.println(f);
}
} catch (Exception e){
e.printStackTrace();
}
}