zoukankan      html  css  js  c++  java
  • java反射 实例

    首先介绍几个概念:

          1、Java反射的概念
      反射含义:可以获取正在运行的Java对象。
      2、Java反射的功能
      1)可以判断运行时对象所属的类
      2)可以判断运行时对象所具有的成员变量和方法
      3)通过反射甚至可以调用到private的方法
      4)生成动态代理
      3、实现Java反射的类
      1)Class:它表示正在运行的Java应用程序中的类和接口
      2)Field:提供有关类或接口的属性信息,以及对它的动态访问权限
      3)Constructor:提供关于类的单个构造方法的信息以及对它的访问权限
      4)Method:提供关于类或接口中某个方法信息
      注意:Class类是Java反射中最重要的一个功能类,所有获取对象的信息(包括:方法/属性/构造方法/访问权限)都需要它来实现
      4、编写Java反射程序的步骤:

      1)必须首先获取一个类的Class对象
      例如:
      Class c1 = Test.class;
      Class c2 = Class.forName(“com.reflection.Test”);
      Class c3 = new Test().getClass();
      2)然后分别调用Class对象中的方法来获取一个类的属性/方法/构造方法的结构
      注意:如果要能够正常的获取类中方法/属性/构造方法应该重点掌握如下的反射类
      Field
      Constructor
      Method

    原理讲的比较清楚的 推荐这个文章 http://www.cnblogs.com/gulvzhe/archive/2012/01/27/2330001.html

    下面的例子演示通过反射给变量赋值

     1 package org.tianchi.userItem;
     2 
     3 import java.lang.reflect.Field;
     4 
     5 public class PrivateTest {     
     6     private String name = "hello";     
     7     public  long number ;
     8 
     9     public String getName() {     
    10         return name;     
    11     }    
    12     
    13     public void setName(String name) {
    14         this.name = name;
    15     }
    16 
    17     public static void main(String[] args) throws Exception {
    18         PrivateTest pt = new PrivateTest();     
    19         
    20         Class<PrivateTest> clazz = PrivateTest.class;     
    21              
    22         Field field = clazz.getDeclaredField("name");     
    23         field.setAccessible(true);     
    24         field.set(pt, "world");     
    25         field.setAccessible(false);    
    26         
    27         Field fieldNum = clazz.getDeclaredField("number");     
    28         fieldNum.setAccessible(true);     
    29         fieldNum.set(pt, 20);     
    30         fieldNum.setAccessible(false);  
    31              
    32         System.out.println(pt.getName());
    33         System.out.println(pt.number);
    34     }
    35 }
    View Code

    2、 利用反射创建一个无法通过new实例化的类的实例,并调用其私有方法进行数据传递(此为转载http://www.cnblogs.com/pricks/archive/2009/08/11/1543855.html)

     1 首先创建一个无法实例化的类:Customer.java:
     2 public class Customer {
     3     private long id;
     4     private String name;
     5     private String age;
     6     
     7     private static Customer instance = null;
     8     /** 显示将构造函数声明为私有,外界无法通过new来实例化本类 */
     9     private Customer(){}
    10     private static synchronized Customer getInstance(){
    11         if(instance == null){
    12             return new Customer();
    13         }
    14         return instance;
    15     }
    16     
    17     /** 本set()方法为私有方法,外界无法直接为id属性赋值 */
    18     private void setId(long id) {
    19         this.id = id;
    20     }
    21     public long getId() {
    22         return id;
    23     }
    24     /** 本set()方法为私有方法,外界无法直接为name属性赋值 */
    25     private void setName(String name) {
    26         this.name = name;
    27     }
    28     public String getName() {
    29         return name;
    30     }
    31     /** 本set()方法为私有方法,外界无法直接为age属性赋值 */
    32     private void setAge(String age) {
    33         this.age = age;
    34     }
    35     public String getAge() {
    36         return age;
    37     }
    38 }
    39 
    40 接下来,开始利用反射创建该类实例,并调用其私有化方法来为其属性赋值,最后调用其公开的方法验证其属性是否被赋上了值:
    41 import java.lang.reflect.Field;
    42 import java.lang.reflect.Method;
    43 
    44 public class test {
    45     public static void main(String[] args) {
    46    //创建类的实例
    47      java.lang.Class c = null;
    48         Customer customer = null;
    49         try{
    50             c = Customer.class;
    51             Method m1 = c.getDeclaredMethod("getInstance");
    52             m1.setAccessible(true);//这句至关重要,不设置为true,便无法获取私有方法
    53             customer = (Customer)m1.invoke(c);
    54         } catch(Exception e){}
    55         
    56         try{
    57             java.lang.reflect.Field fieldId = customer.getClass().getDeclaredField("id");//获取私有成员变量id
    58             
    59             //获取私有方法setId(int id)
    60             String firstLetter = fieldId.getName().substring(0, 1).toUpperCase();
    61             String setName = "set" + firstLetter + fieldId.getName().substring(1);
    62             String getName = "get" + firstLetter + fieldId.getName().substring(1);
    63             java.lang.reflect.Method setMethod = customer.getClass().getDeclaredMethod(setName, new Class[]{fieldId.getType()});
    64             Method getMethod = customer.getClass().getDeclaredMethod(getName, new Class[]{});
    65             setMethod.setAccessible(true);//使私有方法可以被获取到
    66             setMethod.invoke(customer, new Object[]{ 23 });//调用该私有方法并传递数据
    67             
    68             System.out.println("-------------通过公共方法获取到的id值:" + customer.getId());
    69             System.out.println("-------------通过反射获取到的id值:" + getMethod.invoke(customer, null));
    70             
    71             //下面将模仿上面的这一段代码,通过反射来分别为name和age这两个私有成员变量赋值
    72             Field fieldName = customer.getClass().getDeclaredField("name");
    73             firstLetter = fieldName.getName().substring(0, 1).toUpperCase();
    74             setName = "set" + firstLetter + fieldName.getName().substring(1);
    75             setMethod = customer.getClass().getDeclaredMethod(setName, new Class[]{ fieldName.getType() });
    76             setMethod.setAccessible(true);
    77             setMethod.invoke(customer, "张三");
    78             System.out.println("-----------------姓名:" + customer.getName());
    79             
    80             Field fieldAge = customer.getClass().getDeclaredField("age");
    81             firstLetter = fieldAge.getName().substring(0, 1).toUpperCase();
    82             setName = "set" + firstLetter + fieldAge.getName().substring(1);
    83             setMethod = customer.getClass().getDeclaredMethod(setName, new Class[]{ fieldAge.getType() });
    84             setMethod.setAccessible(true);
    85             setMethod.invoke(customer, "40");
    86             System.out.println("-----------------年龄:" + customer.getAge());
    87         } catch(Exception e){}
    88     }
    89 }
    View Code

    这里需要注意:java.lang.reflect.Method貌似是值对象,如果将其传递到另一个方法中并做处理,然后从那个方法中出来后,依然保持其原来的属性不变,没有一点引用类型对象的特征。
      同时,这里的Customer类虽然使用了一个单例模式,但如果我们使用反射的方法来实例化两个该对象实例,它们并非指向同一个引用,例如:
      private static Customer test1(){
            java.lang.Class c = null;
            Customer customer = null;
            try{
                c = Customer.class;
                Method m1 = c.getDeclaredMethod("getInstance");
                m1.setAccessible(true);//这句至关重要,不设置为true,便无法获取私有方法
                customer = (Customer)m1.invoke(c);
            } catch(Exception e){}
      }
      public static void main(String[] args) {
            Customer c1 = test1();
            Customer c2 = test1();
            System.out.println("-----------------------" + c1.equals(c2));
            System.out.println("-----------------------" + (c1 == c2));
        }
      编译后,两个都显示为false。

  • 相关阅读:
    python之private variable
    python实例、类方法、静态方法
    python常用option
    access
    FD_CLOEXEC
    fork后父子进程文件描述问题
    split
    信号
    kill
    进程组&Session
  • 原文地址:https://www.cnblogs.com/tina-smile/p/4432911.html
Copyright © 2011-2022 走看看