反射是框架设计的灵魂,只有学好了反射,才能设计出好的框架 一.反射的概述Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能就是Java语言的反射机制.简单来说,就是反射可以帮助我们在动态运行的时候,对于任意一个类,可以获得其所有方法,所有的变量(是所有的!包括私有!) 反射的作用获取某些类的一些变量,调用某些类的私有方法.(举个栗子,例如在Android开发中我们可以用来开启WiFi热点,调用WifiManager中的setWifiApEnabled()方法) 增加代码的灵活性.(很多主流框架都使用了反射技术,像ssm框架都采用两种技术xml做配置文件+反射技术) 而我们要想使用反射,就要对反射的常用对象有个基本了解Class Class类的实例表示正在运行的Java应用程序中的类和接口Constructor 关于类的单个构造方法的信息以及对它的访问权限 Field Field提供有关类或接口的单个字段的信息,以及对它的动态访问权限. Method Method提供关于类或接口上单独某个方法的信息 反射在内存中的样子大概长这样 这是一个简单的Animal类,这个Animal.java文件,想要被执行的话,首先会被编译成Animal.class文件.而Animal.class想要被执行的话,就会被类加载器加载到JVM中执行,JVM就会将它加载到内存,而加载之后,我们的字节码文件Animal.class在内存中也会有一个对象的表示,别忘了Java语言有句话咋说的,“万事万物,皆为对象”.而.class文件在内存中的对象就是Class对象,所以说获得了Class,才能获得它的构造方法,属性以及方法,相对应的构造方法在内存中对应的是Constructor对象,属性对应的就是Field,而方法呢对应的就是Method,但是不管我们想要获得构造方法,属性还是方法,前提都是我们先获得Class对象 二.Class类Java中java.lang.Class类用于表示一个类的字节码(.class)文件 如何得到某个class文件对应的Class对象 已知类和对象的情况下 类名.class 对象.getClass()—Object类提供 未知类和对象的情况下 Class.forName(“包名.类名”) Class类代表某个类的字节码,并提供了加载字节码的方法:forName(“包名.类名”),forName方法用于加载类字节码到内存中,并封装成一个Class对象. packageJavaReflectTest;publicclassAnimal{publicStringname;privateintid;publicAnimal(){System.out.println("我是无参构造方法");}publicAnimal(intid,Stringname){this.setId(id);this.setName(name);System.out.println("我是有参构造方法");}publicvoideat(){System.out.println("我是公有方法");}privatevoiddrink(){System.out.println("我是私有方法");}privatevoidplay(Stringname,Stringsex){System.out.println("我是私有带参方法");}@OverridepublicStringtoString(){return"Animal{"+"name='"+name+'''+",id="+id+'}';}publicStringgetName(){returnname;}publicvoidsetName(Stringname){this.name=name;}publicintgetId(){returnid;}publicvoidsetId(intid){this.id=id; packageJavaReflectTest;publicclassClassTest{/***获得Class对象*1.通过类名.class*2.对象.getClass()*3.Class.forName();* /publicvoiddemo1()throwsClassNotFoundException{//1.通过类名.class的方式Classclass1=Animal.class;//2.通过对象.getClass()的方式Animalanimal=newAnimal();Classclass2=animal.getClass();//3.Class类forName();获得(推荐)Classclass3=Class.forName("JavaReflectTest.Animal");}publicstaticvoidmain(String[]args){}}这三种获得Class对象的方法,推荐使用第三种方法,因为我们通常做反射的时候,都是在不知道类的实例的时候进行操作的,注意第三种方法通过Class.forName();来获得Class对象的时候,会抛出一个ClassNotFoundException没有发现类的异常,如果我们Class.forName(“路径”);路径写错了或者没有找到这个类的时候,就会抛出这个异常,当然这个异常处理,你可以选择try…catch处理也可以先向上抛,我这里为了方便,就直接向上抛了 三.Constructor类Constructor类的实例对象代表类的一个构造方法 得到某个类所有的构造方法 Constructor[]constructors=Class.forName(“java.lang.String”).getConstructors();得到指定的构造方法并调用 Constructorconstructor=Class.forName(“java.lang.String”).getConstructors(String.class);Stringstr=(String)constructor.newInstance(“abc”);Class类的newInstance()方法用来调用类的默认构造方法 Stringobj=(String)Class.forName(“java.lang.String”).newInstance();packageJavaReflectTest;importjava.lang.reflect.Constructor;publicclassConstructorTest{/***获得无参构造方法* /publicvoiddemo1()throwsException{//获得类的字节码文件对应的对象:Classclass1=Class.forName("JavaReflectTest.Animal");Constructorc=class1.getConstructor();Animalanimal=(Animal)c.newInstance();//相当于Animalanimal=newAnimal();}/***获得有参构造方法* /publicvoiddemo2()throwsException{Classclass1=Class.forName("JavaReflectTest.Animal");Constructorc=class1.getConstructor(int.class,String.class);Animalanimal=(Animal)c.newInstance(2,"猴子");//相当于Animalanimal=newAnimal(2,"猴子");System.out.println(animal.toString());}publicstaticvoidmain(String[]args)throwsException{ConstructorTestc=newConstructorTest();c.demo1();System.out.println("------------");c.demo2();}}四.Field类Field类代表某个类中的一个成员变量,并提供动态的访问权限 Field对象的获得 Field[]fields=c.getFields();//取得所有public属性(包括父类继承) Field[]fields=c.getDeclaredFields();//取得所有声明的属性 得到指定的成员变量 Fieldname=c.getField(“name”);Fieldname=c.getDeclaredField(“name”);设置Filed变量是否可以访问 field.setAccessible(boolean);-Field变量值的读取,设置 field.get(obj);filed.set(obj,value);packageJavaReflectTest;importjava.lang.reflect.Field;publicclassFieldTest{//测试共有属性publicvoiddemo1()throwsException{//获得ClassClassclass1=Class.forName("JavaReflectTest.Animal");//获得属性:Fieldfield=class1.getField("name");//操作属性:Animalanimal=(Animal)class1.getConstructor().newInstance();field.set(animal,"老虎");//animal.name="老虎";//获取值Objectobj=field.get(animal);System.out.println(obj);System.out.println(animal);//这样会自动调用toString()方法}//测试私有方法publicvoiddemo2()throwsException{//获得ClassClassclass1=Class.forName("JavaReflectTest.Animal");//获得私有属性:Fieldfield=class1.getDeclaredField("id");//操作属性:Animalanimal=(Animal)class1.getConstructor().newInstance();//私有属性,需要设置一个可访问的权限field.setAccessible(true);field.set(animal,1);//获取值:Objectobj=field.get(animal);System.out.println(obj);System.out.println(animal);}publicstaticvoidmain(String[]args)throwsException{FieldTestfieldTest=newFieldTest();fieldTest.demo1();System.out.println("----------------");fieldTest.demo2();}}效果图 五.Method类Method类代表某个类中的一个成员方法 Method对象的获得 获得所有方法 getDeclaredMethods()getMethods()-获得指定的方法 getDeclaredMethod(Stringname,Class…parameterTypes)getMethod(Stringname,Class…parameterTypes)通过反射执行方法 invoke(Objectobj,Object…args)packageJavaReflectTest;importjava.lang.reflect.Method;publicclassMethodTest{//测试公有方法publicvoiddemo1()throwsException{//获取Class对象Classclass1=Class.forName("JavaReflectTest.Animal");//实例化Animalanimal=(Animal)class1.getConstructor().newInstance();//获得公有方法Methodmethod=class1.getMethod("eat");//执行该方法method.invoke(animal);//相当于animal.eat();}//测试私有方法publicvoiddemo2()throwsException{//获取Class对象Classclass1=Class.forName("JavaReflectTest.Animal");//实例化Animalanimal=(Animal)class1.getConstructor().newInstance();//获得私有方法Methodmethod=class1.getDeclaredMethod("drink");//设置私有的访问权限method.setAccessible(true);//执行该方法method.invoke(animal);//相当于animal.drink();}publicvoiddemo3()throwsException{//获取Class对象Classclass1=Class.forName("JavaReflectTest.Animal");//实例化Animalanimal=(Animal)class1.getConstructor().newInstance();//获得私有带参的方法Methodmethod=class1.getDeclaredMethod("play",int.class,String.class);//设置私有的访问权限method.setAccessible(true);//执行该方法Objectobj=method.invoke(animal,2,"孔雀");//这是有返回值的情况如果没有返回值可以直接写method.invoke(animal,2,"孔雀");System.out.println(obj);//打印返回的东西,没有就是null}//测试私有带参数的方法publicstaticvoidmain(String[]args)throwsException{MethodTestmethodTest=newMethodTest();methodTest.demo1();System.out.println("--------------------");methodTest.demo2();System.out.println("--------------------");methodTest.demo3();}}效果图 java反射就介绍到这里 原文链接:
