黑马程序员_12_高新技术之反射

来源:互联网 发布:java ee插件下载 编辑:程序博客网 时间:2024/05/23 12:18

                                    黑马程序员——反射

                                          ------- android培训、java培训、期待与您交流! ----------

反射的概念:一个类是由多个部分组成,例如:成员变量,方法,构造函数等,反射就是加载类<把硬盘中的class文件加载到内存中>,并解剖类的各个组成部分,包括私有的。

应用场景:主要是用于制作框架的时候使用,通过配置文件进行反射。

那么该如何加载类,如何反射呢?

Java是面向对象语言,万物皆对象,所以sun公司把所有类用一个Class类来描述。

通过字节码对象获取构造方法,创建对象,使用了Constructor类描述一个类的构造方法。创建对象用newInstance
通过一个字节码对象获取到成员函数,sun使用了一个Method类描述函数。执行指定方法用invoke
通过字节码对象获取成员变量 , sun使用了Field描述了一个类的成员变量。

首先我们先描述一个Person类,以Person类为列进行反射:
package cn.chen.reflect;import java.io.InputStream;import java.util.List;public class Person {//成员变量public String name="aaa";private int age = 22;//构造函数public Person(){System.out.println("person");}public Person(String name){System.out.println(name);}public Person(String name,int pass){System.out.println(name+":"+pass);}//集合作为形参传递private Person(List list){System.out.println("list");}public void aa1(){System.out.println("aa1...");}public void aa1(String name,int pass){System.out.println(name+":"+pass);}//返回类型是数组public Class[] aa1(String name,int[] pass){return new Class[]{String.class};}private void aa1(InputStream io){System.out.println(io);}//静态方法public static void aa1(String name){System.out.println(name);}public static void main(String[] args) {System.out.println("main...");}}

步骤如下:
1:首先把硬盘中的class文件加载进内存中;

加载类进内存有三种方法:
a:通过Class类中forName方法:forName(String  className)
b:通过上帝Object类中getClass方法:对象.getClass()
c:通过类名.class

代码实现如下:
</pre><pre name="code" class="java">package cn.chen.reflect;public class Demo1 {public static void main(String[] args) throws ClassNotFoundException {//第一种方法Class clazz1 = Class.forName("cn.chen.reflect.Person");//第二种方法Class clazz2 = new Person().getClass();//第三种方法Class clazz3 = Person.class;}}


2:通过上个步骤获得该类字节码;通过该类的字节码获得该类的所以构造函数描述的类,该类有一个方法,根据构造函数指定的参数创建对象。

反射构造函数代码如下:

package cn.chen.reflect;import java.lang.reflect.Constructor;import java.util.ArrayList;import java.util.List;import org.junit.Test;public class Demo2 {@Testpublic void test1() throws Exception{Class clazz = Class.forName("cn.chen.reflect.Person");Constructor c = clazz.getConstructor(null);Person p = (Person) c.newInstance(null);System.out.println(p.name);}@Testpublic void test2() throws Exception{Class clazz = Class.forName("cn.chen.reflect.Person");Constructor c = clazz.getConstructor(String.class);Person p = (Person) c.newInstance("chenlong");System.out.println(p.name);}@Testpublic void test3() throws Exception{Class clazz = Class.forName("cn.chen.reflect.Person");Constructor c = clazz.getConstructor(String.class,int.class);Person p = (Person) c.newInstance("xieli",20);System.out.println(p.name);}@Testpublic void test4() throws Exception{//获得字节码文件对象Class clazz = Class.forName("cn.chen.reflect.Person");//反射私有成员时用的方法Constructor c = clazz.getDeclaredConstructor(List.class);//暴力反射c.setAccessible(true);//返回类型是Object,所以需要强制转换Person p = (Person) c.newInstance(new ArrayList());System.out.println(p.name);}@Testpublic void test5() throws Exception{Class clazz = Class.forName("cn.chen.reflect.Person");Person p = (Person) clazz.newInstance();System.out.println(p.name);}}

举一反三反射成员函数:

package cn.chen.reflect;import java.io.FileInputStream;import java.io.InputStream;import java.lang.reflect.Method;import org.junit.Test;public class Demo3 {@Testpublic void test1() throws Exception{Person p = new Person();Class clazz = Class.forName("cn.chen.reflect.Person");Method method = clazz.getMethod("aa1", null);method.invoke(p,null);}@Testpublic void test2() throws Exception{Person p = new Person();//获得字节码文件对象Class clazz = Class.forName("cn.chen.reflect.Person");//获得该类方法对象Method method = clazz.getMethod("aa1", String.class,int.class);//根据指定的参数,执行指定的方法。第一个参数是指定那个类的对象,后面参数是该类方法的形参method.invoke(p, "chen",25);}@Testpublic void test3() throws Exception{Person p = new Person();Class clazz = Class.forName("cn.chen.reflect.Person");Method method = clazz.getMethod("aa1", String.class , int[].class);Class cs[] = (Class[]) method.invoke(p, "xieli",new int[]{12,2});System.out.println(cs[0]);}@Testpublic void test4() throws Exception{Person p = new Person();Class clazz = Class.forName("cn.chen.reflect.Person");Method method = clazz.getDeclaredMethod("aa1", InputStream.class);method.setAccessible(true);method.invoke(p,new FileInputStream("H:\\1.jpg"));}@Testpublic void test5() throws Exception{Class clazz = Class.forName("cn.chen.reflect.Person");Method method = clazz.getMethod("aa1", String.class);//反射静态方法,不需要对象、method.invoke(null,"chen");}@Testpublic void test6() throws Exception{Person p = new Person();Class clazz = Class.forName("cn.chen.reflect.Person");Method method = clazz.getMethod("main", String[].class);//第一种解决方案,由于传入数组jvm会拆开,所以进行包装//method.invoke(null,(Object)new String[]{"s"});//第二种解决方案。method.invoke(null,new Object[]{new String[]{"bb","aa"}});}}

反射字段即成员变量

package cn.chen.reflect;import java.lang.reflect.Field;import org.junit.Test;public class Demo4 {@Testpublic void test1() throws Exception{Person p = new Person();Class clazz = Class.forName("cn.chen.reflect.Person");//根据参数获取对应的字段Field f = clazz.getField("name");System.out.println(f.get(p));}@Testpublic void test2() throws Exception{Person p = new Person();Class clazz = Class.forName("cn.chen.reflect.Person");Field f = clazz.getDeclaredField("age");f.setAccessible(true);System.out.println(f.get(p));}}


注意部分:反射时如果是私有成员,必须使用带有Declared字母的方法,如果需要使用时,需要调用setAccessible(true) 方法告诉Jvm需要暴力访问。




------- android培训、java培训、期待与您交流! ----------





0 0
原创粉丝点击