Java反射机制
Posted Actexpler
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java反射机制相关的知识,希望对你有一定的参考价值。
最近学习中遇到反射机制,可是老师只是轻描淡写的解释了一通,还是自己查资料补充一下。
Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为Java语言的反射机制。
一、Class类
1、Class是一个类,一个描述类的类(也就是描述类本身),封装了描述方法的Method,描述字段的Filed,描述构造器的Constructor等属性
2、对象照镜子后(反射)可以得到的信息:某个类的数据成员名、方法和构造器、某个类到底实现了哪些接口。
3、对于每个类而言,JRE 都为其保留一个不变的 Class 类型的对象。
一个 Class 对象包含了特定某个类的有关信息。换句话说:任何类都是Class类的实例对象
4、Class 对象只能由系统建立对象
5、一个类在 JVM 中只会有一个Class实例
二、反射机制
反射是Java中一种强大的工具,能够使我们很方便的创建灵活的代码,这些代码可以再运行时装配,无需在组件之间进行源代码链接。
作用:
- 在运行时判断任意一个对象所属的类;
- 在运行时获取类的对象;
- 在运行时访问java对象的属性,方法,构造方法等。
反射的特点:
为什么要用反射机制?直接创建对象不就可以了吗,这就涉及到了动态与静态的概念。
静态编译:在编译时确定类型,绑定对象,即通过。
动态编译:运行时确定类型,绑定对象。动态编译最大限度发挥了java的灵活性,体现了多态的应用,有以降低类之间的藕合性
反射机制的优点:可以实现动态创建对象和编译,体现出很大的灵活性(特别是在J2EE的开发中它的灵活性就表现的十分明显)。通过反射机制我们可以获得类的各种内容,进行了反编译。对于JAVA这种先编译再运行的语言来说,反射机制可以使代码更加灵活,更加容易实现面向对象。
举例:一个大型的软件,当程序编译后,发布了,都会在后期不断的更新以完善整个程序,我们不可能要用户把以前的卸载,再重新安装新的版本,假如这样的话,这个软件肯定是没有多少人用的。采用静态的话,需要把整个程序重新编译一次才可以实现功能的更新,而采用反射机制的话,它就可以不用卸载,只需要在运行时才动态的创建和编译,就可以实现该功能。 想一下,王者荣耀每次出新英雄或者出新皮肤的时候都会有更新,用户在更新的时候知只是下载一个小的程序包进行安装,而不用重新安装整个王者荣耀游戏,这就是采用动态编译的例子。
反射机制的缺点:对性能有影响。使用反射基本上是一种解释操作,我们可以告诉JVM,我们希望做什么并且它 满足我们的要求。这类操作总是慢于只直接执行相同的操作。
三、Class中实现反射机制的类
java.lang.Class;
java.lang.reflect.Constructor;
java.lang.reflect.Field;
java.lang.reflect.Method;
java.lang.reflect.Modifier;
四、反射机制获取类有三种方法
在利用反射获取类的对象,对象的属性,方法,构造方法等的时候都需要创建类的类类型
package com.neuedu.reflect; /* * 项目名称:Java-Reflect * @author:wzc * @date 创建时间:2017年8月28日 下午8:41:29 * @Description:获取类的类类型 * @parameter * */ public class JavaDemo1 { public static void main(String[] args) { //Food的实例对象如何表示 Food food1=new Food(); /* * Food这个类也是一个实例对象,Class类的实例对象 * 任何一个类都是Class的实例对象,三种表示方式 * 第一种表达方式--->实际上在告诉我们任何一个类都有一个隐含的静态成员class */ Class class1=Food.class; //第二种表示方式,已知该类的对象getClass Class class2=food1.getClass(); /* * c1,c2表示了Food类的类类型(class type) * 任何类都是class类的实例对象 * c1 c2都代表了Food的类类型,一个类只可能是Class类的一个实例对象 */ System.out.println(class1==class2); //第三种表达方式 Class class3=null; try { class3=Class.forName("com.neuedu.reflect.Food"); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(class2==class3); } //创建一个Food类 class Food{ public void print(){ System.out.println("hello Food"); } }
五、创建对象
获取类的类类型以后我们就可以利用类类型创建该类的对象
package com.neuedu.reflect;
/*
* 项目名称:Java-Reflect
* @author:wzc
* @date 创建时间:2017年8月28日 下午8:41:29
* @Description:获取类的类类型
* @parameter
* */
public class JavaDemo1 {
public static void main(String[] args) {
//Food的实例对象如何表示
Food food1=new Food();
/*
* Food这个类也是一个实例对象,Class类的实例对象
* 任何一个类都是Class的实例对象,三种表示方式
* 第一种表达方式--->实际上在告诉我们任何一个类都有一个隐含的静态成员class
*/
Class class1=Food.class;
//第二种表示方式,已知该类的对象getClass
Class class2=food1.getClass();
/*
* c1,c2表示了Food类的类类型(class type)
* 任何类都是class类的实例对象
* c1 c2都代表了Food的类类型,一个类只可能是Class类的一个实例对象
*/
System.out.println(class1==class2);
//第三种表达方式
Class class3=null;
try {
class3=Class.forName("com.neuedu.reflect.Food");
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(class2==class3);
//我们可以通过类的类类型创建类的对象实例
try {
Food food2 = (Food) class1.newInstance();
food2.print();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
//创建一个Food类
class Food{
public void print(){
System.out.println("hello Food");
}
}
六、获取类的相关信息: 类名,方法名,方法的返回值类型,方法的参数列表
package com.neuedu.Uttil; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; /* * 项目名称:Java-Reflect * @author:wzc * @date 创建时间:2017年8月29日 下午1:22:15 * @Description: 1.利用反射打印类的信息 * 2.利用反射打印类的成员变量 * 3.利用反射打印类的构造方法 * @parameter * */ public class Uttil { /* * 打印类的信息,打印类的返回值类型,类类名,参数列表 * * */ public static void PrintClass(Object obj){ Class cInt=obj.getClass(); System.out.println("类的名称:"+cInt.getName()); /* * Method类,方法对象 * 一个成员方法就是一个Method对象 * getMethods()方法获取的是所有的public的函数,包括父类继承而来的 * getDeclaredMethods()获取的是所有该类自己声明的方法, * * */ Method[] ms=cInt.getMethods(); System.out.println("[类的返回值类型],[类的名称],[类的参数列表]"); for (int i = 0; i < ms.length; i++) { //得到方法的返回值类型的类类型 Class returnType=ms[i].getReturnType(); System.out.print(returnType.getName()+" "); //得到方法的名称 System.out.print(ms[i].getName()+"("); //获取参数类型 Class [] paramTypes=ms[i].getParameterTypes(); for (Class class1 : paramTypes) { System.out.print(class1.getName()+","); } System.out.println(")"); } } }
测试一下:
public class JunitTest { @Test public void test() { String string="hello"; //Uttil.PrintClass(string); } }
执行结果:
七、获取类的属性
/* * 成员变量也是对象 * java.lang.reflect.Field; * Filed类封装了关于成员变量的操作 * getFields()方法获取的是所有的public的成员变量的信息 * getDeclaredFields获取的是该类自己声明的成员变量的信息 * * * */ public static void printFieldInfo(Object obj) { //获取类的成员变量 Class class1=obj.getClass(); Field[] fields=class1.getDeclaredFields(); for (Field field : fields) { //得到成员变量的类型的类类型 //得到成员变量的类型名 Class fieldType=field.getType(); String typeName=fieldType.getName(); //得到成员变量的名称 String fieldName=field.getName(); System.out.println(typeName+" "+fieldName); } }
测试一下:
@Test public void test() { Uttil.printFieldInfo(new Integer(1)); }
结果:
八、获取类的构造方法
/* * 打印对象的构造函数 * */ public static void printConMessage(Object obj){ Class class1=obj.getClass(); /* * 构造函数也是对象 * java.lang.Contructor中封装了构造函数的信息 * getConstructors获取所有的public的构造函数 * getDeclaredContructors得到所有的构造函数 * * */ Constructor[] ct=class1.getConstructors(); for (Constructor constructor : ct) { System.out.print(constructor.getName()+"("); //获取构造函数的参数列表--->得到的是参数列表的类类型 Class[] paramTypes=constructor.getParameterTypes(); for (Class class2 : paramTypes) { System.out.print(class2.getName()); } System.out.println(")"); } }
测试一下:
@Test public void test() { String string="hello"; Uttil.printConMessage(string); }
结果:
九、通过反射来执行对象的方法
package com.neuedu.reflect; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; /* * 项目名称:Java-Reflect * @author:wzc * @date 创建时间:2017年8月29日 下午6:45:21 * @Description:通过反射执行类的方法 * * @parameter * */ public class RunMethod { public static void main(String[] args) { Student student=new Student("张三", 25); //1.要获取方法,首先要获取该方法的类类型, Class stuClass = student.getClass(); /* * 2.获取方法、名称和参数列表 * getMethod获取的是public方法 * getDelcaredMethod自己声明的方法 */ try { //stuClass.getMethod("getName",new Class[]{}) //stuClass.getMethod("getName"); Method m1=stuClass.getMethod("getName", null); //3.方法的反射操作-----以前:student.getName(); //m1.invoke(obj,args..); //方法的反射操作是用m1对象来进行方法的调用 //方法如果没有返回值返回null,有返回值返回具体的返回值,并转换成Object m1.invoke(student); System.out.println("=============="); m1=stuClass.getMethod("getAge", null); Object object=m1.invoke(student, null); System.out.println("=============="); //m1=stuClass.getMethod("getAge", int.class); m1=stuClass.getMethod("getAge", new Class[]{int.class}); m1.invoke(student, 2); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } } //student类 class Student{ private String name; private int age; public Student(){ } public Student(String name,int age){ this.name=name; this.age=age; } //无参数方法 public void getName(){ System.out.println("name:"+name); } //无参数方法 public void getAge(){ System.out.println("age:"+age); } //有参数的方法 public void getAge(int num){ System.out.println(num+"年前age:"+(age-num)); } public void studentIn(){ System.out.println("name:"+name+",age:"+age); } }
今天只是记录一些反射最基础的理论,之后会在写一些反射的应用,只有应用了才能更好的理解反射的概念。
以上是关于Java反射机制的主要内容,如果未能解决你的问题,请参考以下文章