大学IT网 - 最懂大学生的IT学习网站! QQ资料交流群:367606806
当前位置:大学IT网 > Java技巧 > JAVA反射范例代码

JAVA反射范例代码

关键词:反射  阅读(710) 赞(11)

[摘要]一个类有多个组成部分,例如:成员变量,方法,构造方法等。反射就是加载类,并解剖(反射)出类的各个组成部分。本人在下面的反射例子中以注释的形式把所理解的东西写了出来.

一个类有多个组成部分,例如:成员变量,方法,构造方法等。反射就是加载类,并解剖(反射)出类的各个组成部分。
本人在下面的反射例子中以注释的形式把所理解的东西写了出来

Person类:

 import java.util.List;
 
 public class Person {
 
     /*
      * 1.构造方法
      */
     //无参的
     public Person(){
         System.out.println("无参的构造方法!");
     }
     //一个参数,类型为String的
     public Person(String name){
         System.out.println("name:" + name);
     }
     //一个参数,类型为int的,且为私有的
     private Person(int age){
         System.out.println("age:" + age);
     }
     //参数为两个参数
     public Person(String name, int age){
         System.out.println(name + "的年龄:" + age + "岁");
     }
     //参数为List的
     public Person(List list){
         System.out.println("list:" + list);
     }
     
     /*
      * 2.普通方法
      */
     //1、无参
     public void methodTest(){
         System.out.println("这是无参的普通方法!");
     }
     
     //2、一个参数
     public void methodTest(String name){
         System.out.println("名字:" + name);
     }
     //3、一个参数私有的
     private void methodTest(int age){
         System.out.println("年龄:" + age);
     }
     //4、两个参数静态的
     public static void methodTest(String name, int age){
         System.out.println(name + "的年龄:" + age);
     }
     //5、main方法
     public static void main(String[] args) {
         System.out.println("main方法:");
     }
     
     /*
      * 3.字段
      */
     public String name = "张三";
     private int age = 25;
     private static String password = "PaSs1111";
 }

测试代码:

 import java.lang.reflect.Constructor;
 import java.lang.reflect.Field;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.util.ArrayList;
 import java.util.List;
 
 import org.junit.Test;
 
 public class ReflectTest {
 
     /**
      * @功能:反射
      * @介绍:
      *         clazz1.getConstructor()中的参数是可变参数,
      *     且用clazz1.getConstructor()只能反射出public型的,private反射不到
      *     如果想要得到private的构造方法,则需要用clazz.getDeclaredConstructor()来反射private的构造函数
      * @日期:2013-10-22
      */
 
     /*
      * 1.构造方法反射
      */
     @Test
     public void test1() throws Exception{
         //加载类(方式一) 参数中类名要全称
         Class clazz1 = Class.forName("cn.itcast.reflect.Person");
         //加载类(方式二)  ==> 实例化的时候构造方法直接运行
 //        Class clazz2 = new Person().getClass();
         //加载类(方式三)
 //        Class clazz3 = Person.class;
         //反射无参的构造方法,null表示无参
         Constructor c = clazz1.getConstructor(null);
         //new一个对象(正常情况下返回的是Object型的,这里强转为Person)
         Person p = (Person) c.newInstance();
     }
     
     @Test
     public void test2() throws Exception{
         //加载类
         Class clazz = Class.forName("cn.itcast.reflect.Person");
         //解剖(反射)出参数为String的构造方法(String.class)
         Constructor c = clazz.getConstructor(String.class);
         c.newInstance("张三");
     }
     
     @Test
     public void test3() throws Exception{
         //加载类
         Class clazz = Class.forName("cn.itcast.reflect.Person");
         //解剖(反射)出参数为int的构造方法(int.class)
         /*
          * 因为此时的构造方法为private的,所以正常的clazz.getConstructor(),不能反射出来
          * 此时就要用clazz.getDeclaredConstructor()来反射private的构造函数
          * 但解剖出来的构造方法不能直接new一个新的对象,还得能过c.setAccessible(true)修改一下属性(暴力反射)
          * ,这时才能进行new新对象,和正常的反射一样了
          */
         Constructor c = clazz.getDeclaredConstructor(int.class);
         //打开访问权限
         c.setAccessible(true);
         c.newInstance(25);
     }
     
     @Test
     public void test4() throws Exception{
         //加载类
         Class clazz = Class.forName("cn.itcast.reflect.Person");
         //反射方法
         Constructor c = clazz.getConstructor(String.class,int.class);
         //new
         c.newInstance("李四",25);
     }
     
     @Test
     public void test5() throws Exception{
         //加载类
         Class clazz = Class.forName("cn.itcast.reflect.Person");
         //反射方法
         Constructor c = clazz.getConstructor(List.class);
         //new
         List list = new ArrayList();
         list.add("zhangsan");
         list.add("lisi");
         list.add("wangwu");
         list.add("zhaoliu");
         c.newInstance(list);
     }
     
     /*
      * 2.普通方法反射
      */
     @Test
     public void test6() throws Exception{
         Person p = new Person();
         //加载类
         Class clazz = Class.forName("cn.itcast.reflect.Person");
         
         /*
          * 反射方法【clazz.getMethod("methodTest", null) 第一个参数为:方法名;第二个参数为:方法入参的类型】
          * 这里方法入参为空,所以用null表示参数类型
          */
         Method method = clazz.getMethod("methodTest", null);
         //method.invoke(p, null) 第一个参数要传一个对象,第二个为所反射的方法入参
         method.invoke(p, null);
     }
     
     @Test
     public void test7() throws Exception{
         Person p = new Person();
         //加载类
         Class clazz = Class.forName("cn.itcast.reflect.Person");
         //反射
         Method method = clazz.getMethod("methodTest", String.class);
         //
         method.invoke(p, "张三");
     }
     
     @Test
     public void test8() throws Exception{
         Person p = new Person();
         //加载类
         Class clazz = Class.forName("cn.itcast.reflect.Person");
         //私有的方法要用getDeclaredMethod来反射获取
         Method method = clazz.getDeclaredMethod("methodTest", int.class);
         //反射出来的方法此时还是private的,要强制打开访问权限
         method.setAccessible(true);
         //
         method.invoke(p, 25);
     }
     
     @Test
     public void test9() throws Exception{
         //加载类
         Class clazz = Class.forName("cn.itcast.reflect.Person");
         //反射
         Method method = clazz.getMethod("methodTest", String.class, int.class);
         /*
          * 静态的可以不传对象,为:null即可
          * (第一个参数为传对象的位置,后边的参数都是把反射方法的入参,invoke的“第二个参数”即为可变参数)
          */
         method.invoke(null, "李四", 25);
     }
     
     @Test
     public void test10() throws Exception{
         //加载类
         Class clazz = Class.forName("cn.itcast.reflect.Person");
         Method method = clazz.getMethod("main", String[].class);
         //main方法也是个静态方法
         /*
          * 关于下边注释的部分,是不可以用的,因为main方法中的参数为String[] args,是一个数组,在这里视为一个参数
          * 在jdk1.4之前,没有“可变参数”,到了1.5以后才有的可变参数
          * 那么,jdk1.4之前的method.invoke(String mehtodName, Object obj[])中
          * 第二个参数用一个数组Object obj[]来传参的,在invoke中会把这个数组拆解成为一个个对应的参数
          * 而jdk1.5是兼容jdk1.4的,所以,在jdk1.5中用数组来传参也可以,当然,它会把这个数组给拆解成几个参数
          * 因此,在调用main方法的时候,要在外围再加一个数组,具体如下【数组参数1/2】
          * 
          * 注:反射参数为数组的方法都要注意
          */
         //method.invoke(null, new String[]{"123","234"});
         //【数组参数1】
         method.invoke(null, new Object[]{new String[]{"1234","5678","9012"}});
         //【数组参数2】也可以这样(前边加一个Object可以欺骗一下程序,骗它为不是数组,其实传进去的确实为数组)
         method.invoke(null, (Object)new String[]{"1234","5678","9012"});
     }
     
     /*
      * 3.字段反射
      */
     
     @Test
     public void test11() throws Exception{
         Person p = new Person();
         //加载类
         Class clazz = Class.forName("cn.itcast.reflect.Person");
         //参数为字段名称
         Field field = clazz.getField("name");
         //获取字段值,传一个对象进去
         Object obj = field.get(p);
         //获取字段的类型
         Class type = field.getType();
         //如果字段类型为String,则打印数值
         if(type.equals(String.class)){
             String value = (String) obj;
             System.out.println(value);
         }
         //设置字段值,第一个参数传一个对象,第二个参数为修改的内容
         field.set(p, "李四");
         //打印一下,看看能不能通过反射来改变字段的值(结果:可以)
         System.out.println(p.name);
     }
     
     @Test
     public void test12() throws Exception{
         Person p = new Person();
         //加载类
         Class clazz = Class.forName("cn.itcast.reflect.Person");
         //
         Field field = clazz.getDeclaredField("age");
         //私有字段,修改访问权限
         field.setAccessible(true);
         System.out.println(field.get(p));
     }
     
     @Test
     public void test13() throws Exception{
         Person p = new Person();
         //加载类
         Class clazz = Class.forName("cn.itcast.reflect.Person");
         Field field = clazz.getDeclaredField("password");
         field.setAccessible(true);
         /*
          * 这里,password字段为私有且静态的字段,
          * 但静态字段不同于静态方法和静态构造方法,field.get(p)中必须传对象
          */
         System.out.println(field.get(p));
     }
 }


相关评论