精华内容
下载资源
问答
  • public class TashiFinger { private static SerialConnect _SerialConnect = null; private static CommandCall _SensorControl = null; ...[color=#FF0000]现在只能访问到TashiFinger,用反射要怎么才能反问到...
  • 对于java反射机制的描述可参考其他网站的解释,这里主要是对其中的对内部函数私有变量和构造函数的用法举例 package main;import java.lang.reflect.Constructor; import java.lang.reflect.Field; import ...

    对于java反射机制的描述可参考其他网站的解释,这里主要是对其中的对内部函数、私有变量和构造函数的用法举例

    package main;
    
    import java.lang.reflect.Constructor;
    import java.lang.reflect.Field;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    
    /**
     * Created by bigzhou on 2016/10/23 0023.
     */
    public class Person {
        public static void main(String[]arg) throws NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchFieldException, ClassNotFoundException {
            System.out.println("\n***************练习内部函数调用*****************");
            System.out.println("有一个参数的:");
            Class class11 = Person.class;
            Method method11 = class11.getDeclaredMethod("showOutName", String.class);
            method11.invoke(class11.newInstance(),"chenzhen");
    
            System.out.println("有多个参数的:");
            Class class12 = Person.class;
            Method method12 = class12.getDeclaredMethod("showOut",new Class[]{String.class,int.class});
            method12.invoke(class12.newInstance(),"chenzhen",23);
    
            System.out.println("静态内部函数:");
            Class class13 = Person.class;
            Method method13 = class13.getDeclaredMethod("staticFunc",String.class);
            method13.invoke(class13,"statictest");  //这里注意下调用的不是类实例而是类对象
    
            System.out.println("**************练习私有变量调用*****************");
            Class class21 = Person.class;
            Person person21 = (Person) class21.newInstance();
            Field field21 = class21.getDeclaredField("name");
            field21.setAccessible(true);        //这个是专门处理私有类型的,需要设置为true
            field21.set(person21,"huoyuanjia");
            person21.showName();
    
            System.out.println("**************练习私有构造函数***************");
    
            System.out.println("无参数的:");
            Constructor con31 = Person.class.getDeclaredConstructor();
            con31.setAccessible(true);
            Person f31 = (Person)con31.newInstance();
            f31.showAll();
    
            System.out.println("有多个参数的:");
            Constructor con32 = Person.class.getDeclaredConstructor(new Class[]{int.class,String.class});
            con32.setAccessible(true);
            Person f2 = (Person) con32.newInstance(new Object[]{23,"zhou"});
            f2.showAll();
    
            System.out.println("有一个参数的:");
            Constructor con3 = Person.class.getDeclaredConstructor(int.class);
            con3.setAccessible(true);
            Person f3 = (Person) con3.newInstance(23);
            f3.showAll();
        }
        private int age = 0;
        private String name = "asdf";
        Person(){}
        Person(int age, String name){
            this.age = age;
            this.name = name;
        }
        Person(int age){
            this.age = age;
        }
        void showAll(){
            System.out.println("name :"+name+"\naget :"+age+"\n");
        }
        public void showAge(){
            System.out.println("age :"+age);
        }
        public void showName(){
            System.out.println("name :"+name+"\n");
        }
        public void showOutName(String outname){
            System.out.println("name :"+outname+"\n");
        }
        public void showOut(String outname, int outage){
            System.out.println("name :"+outname+"\nage :"+outage+"\n");
        }
        public static void staticFunc(String str){
            System.out.println("static function: "+str+"\n");
        }
    }

    运行结果:

    ***************练习内部函数调用*****************
    有一个参数的:
    name :chenzhen
    
    有多个参数的:
    name :chenzhen
    age :23
    
    静态内部函数:
    static function: statictest
    
    **************练习私有变量调用*****************
    name :huoyuanjia
    
    **************练习私有构造函数***************
    无参数的:
    name :asdf
    aget :0
    
    有多个参数的:
    name :zhou
    aget :23
    
    有一个参数的:
    name :asdf
    aget :23
    
    
    Process finished with exit code 0
    
    展开全文
  • java反射访问私有变量和私有方法

    千次阅读 2010-06-25 00:31:00
    java反射访问私有变量和私有方法 引言 对于软件开发人员来说,单元测试是一项必不可少的工作。它既可以验证程序的有效性,又可以在程序出现 BUG 的时候,帮助开发人员快速的定位问题所在。但是,在写单元...
    java反射访问私有变量和私有方法

    引言

    对于软件开发人员来说,单元测试是一项必不可少的工作。它既可以验证程序的有效性,又可以在程序出现 BUG 的时候,帮助开发人员快速的定位问题所在。但是,在写单元测试的过程中,开发人员经常要访问类的一些非公有的成员变量或方法,这给测试工作带来了很大的困扰。本文总结了访问类的非公有成员变量或方法的四种途径,以方便测试人员在需要访问类非公有成员变量或方法时进行选择。

    尽管有很多经验丰富的程序员认为不应该提倡访问类的私有成员变量或方法,因为这样做违反了 Java 语言封装性的基本规则。然而,在实际测试中被测试的对象千奇百怪,为了有效快速的进行单元测试,有时我们不得不违反一些这样或那样的规则。本文只讨论如何访问类的非公有成员变量或方法,至于是否应该在开发测试中这样做,则留给读者自己根据实际情况去判断和选择。

    方法一:修改访问权限修饰符

    先介绍最简单也是最直接的方法,就是利用 Java 语言自身的特性,达到访问非公有成员的目的。说白了就是直接将 private 和 protected 关键字改为 public 或者直接删除。我们建议直接删除,因为在 Java 语言定义中,缺省访问修饰符是包可见的。这样做之后,我们可以另建一个源码目录 —— test 目录(多数 IDE 支持这么做,如 Eclipse 和 JBuilder),然后将测试类放到 test 目录相同包下,从而达到访问待测类的成员变量和方法的目的。此时,在其它包的代码依然不能访问这些变量或方法,在一定程度上保障了程序的封装性。

    下面的代码示例展示了这一方法。


    清单 1. 原始待测类 A 代码

    public class A {    private String name = null;    private void calculate() {    }}


    清单 2. 针对单元测试修改后的待测类 A 的代码
    public class A {    String name = null;    private void calculate() {    }}

    这种方法虽然看起来简单粗暴,但经验告诉我们这个方法在测试过程中是非常有效的。当然,由于改变了源代码,虽然只是包可见,也已经破坏了对象的封装性,对于多数对代码安全性要求严格的系统此方法并不可取。

    方法二:利用安全管理器

    安全性管理器与反射机制相结合,也可以达到我们的目的。Java 运行时依靠一种安全性管理器来检验调用代码对某一特定的访问而言是否有足够的权限。具体来说,安全性管理器是 java.lang.SecurityManager 类或扩展自该类的一个类,且它在运行时检查某些应用程序操作的权限。换句话说,所有的对象访问在执行自身逻辑之前都必须委派给安全管理器,当访问受到安全性管理器的控制,应用程序就只能执行那些由相关安全策略特别准许的操作。因此安全管理器一旦启动可以为代码提供足够的保护。默认情况下,安全性管理器是没有被设置的,除非代码明确地安装一个默认的或定制的安全管理器,否则运行时的访问控制检查并不起作用。我们可以通过这一点在运行时避开 Java 的访问控制检查,达到我们访问非公有成员变量或方法的目的。为能访问我们需要的非公有成员,我们还需要使用 Java 反射技术。Java 反射是一种强大的工具,它使我们可以在运行时装配代码,而无需在对象之间进行源代码链接,从而使代码更具灵活性。在编译时,Java 编译程序保证了私有成员的私有特性,从而一个类的私有方法和私有成员变量不能被其他类静态引用。然而,通过 Java 反射机制使得我们可以在运行时查询以及访问变量和方法。由于反射是动态的,因此编译时的检查就不再起作用了。

    下面的代码演示了如何利用安全性管理器与反射机制访问私有变量。


    清单 3. 利用反射机制访问类的成员变量

    //获得指定变量的值
    public static Object getValue(Object instance, String fieldName)
        
    throws   IllegalAccessException, NoSuchFieldException ...{

         Field field
    = getField(instance.getClass(), fieldName);
        
    // 参数值为true,禁用访问控制检查
         field.setAccessible(true);
        
    return field.get(instance);
    }


    //该方法实现根据变量名获得该变量的值
    public static Field getField(Class thisClass, String fieldName)
        
    throws NoSuchFieldException ...{

        
    if (thisClass == null) ...{
            
    throw new NoSuchFieldException("Error field !");
         }

    }

    其中 getField(instance.getClass(), fieldName) 通过反射机制获得对象属性,如果存在安全管理器,方法首先使用 this 和 Member.DECLARED 作为参数调用安全管理器的 checkMemberAccess 方法,这里的 this 是 this 类或者成员被确定的父类。 如果该类在包中,那么方法还使用包名作为参数调用安全管理器的 checkPackageAccess 方法。 每一次调用都可能导致 SecurityException。当访问被拒绝时,这两种调用方式都会产生 securityexception 异常 。

    setAccessible(true) 方法通过指定参数值为 true 来禁用访问控制检查,从而使得该变量可以被其他类调用。我们可以在我们所写的类中,扩展一个普通的基本类 java.lang.reflect.AccessibleObject 类。这个类定义了一种 setAccessible 方法,使我们能够启动或关闭对这些类中其中一个类的实例的接入检测。这种方法的问题在于如果使用了安全性管理器,它将检测正在关闭接入检测的代码是否允许这样做。如果未经允许,安全性管理器抛出一个例外。

    除访问私有变量,我们也可以通过这个方法访问私有方法。


    清单 4. 利用反射机制访问类的成员方法

    public static Method getMethod(Object instance, String methodName, Class[] classTypes)
        
    throws   NoSuchMethodException ...{

         Method accessMethod
    = getMethod(instance.getClass(), methodName, classTypes);
        
    //参数值为true,禁用访问控制检查
         accessMethod.setAccessible(true);

        
    return accessMethod;
    }


    private static Method getMethod(Class thisClass, String methodName, Class[] classTypes)
        
    throws NoSuchMethodException ...{

        
    if (thisClass == null) ...{
            
    throw new NoSuchMethodException("Error method !");
         }
    try ...{
            
    return thisClass.getDeclaredMethod(methodName, classTypes);
         }
    catch (NoSuchMethodException e) ...{
            
    return getMethod(thisClass.getSuperclass(), methodName, classTypes);
                
         }

    }

    获得私有方法的原理与获得私有变量的方法相同。当我们得到了函数后,需要对它进行调用,这时我们需要通过 invoke() 方法来执行对该函数的调用,代码示例如下:

    //调用含单个参数的方法
    public static Object invokeMethod(Object instance, String methodName, Object arg)
        
    throws NoSuchMethodException,
         IllegalAccessException, InvocationTargetException
    ...{

         Object[] args
    = new Object[1];
         args[
    0] = arg;
        
    return invokeMethod(instance, methodName, args);
    }


    //调用含多个参数的方法
    public static Object invokeMethod(Object instance, String methodName, Object[] args)
        
    throws NoSuchMethodException,
         IllegalAccessException, InvocationTargetException
    ...{
         Class[] classTypes
    = null;
        
    if (args != null) ...{
             classTypes
    = new Class[args.length];
            
    for (int i = 0; i < args.length; i++) ...{
                
    if (args[i] != null) ...{
                     classTypes[i]
    = args[i].getClass();
                 }

             }

         }

        
    return getMethod(instance, methodName, classTypes).invoke(instance, args);
    }

     

    利用安全管理器及反射,可以在不修改源码的基础上访问私有成员,为测试带来了极大的方便。尤其是在编译期间,该方法可以顺利地通过编译。但同时该方法也有一些缺点。第一个是性能问题,用于字段和方法接入时反射要远慢于直接代码。第二个是权限问题,有些涉及 Java 安全的程序代码并没有修改安全管理器的权限,此时本方法失效。

    展开全文
  • Java反射访问私有变量和私有方法

    千次阅读 2011-04-25 21:03:00
    引言  对于软件开发人员来说,单元测试是一项必不可少的工作。它既可以验证程序的有效性...  尽管有很多经验丰富的程序员认为不应该提倡访问类的私有成员变量或方法,因为这样做违反了 Java 语言

    引言

      对于软件开发人员来说,单元测试是一项必不可少的工作。它既可以验证程序的有效性,又可以在程序出现 BUG 的时候,帮助开发人员快速的定位问题所在。但是,在写单元测试的过程中,开发人员经常要访问类的一些非公有的成员变量或方法,这给测试工作带来了很大的困扰。本文总结了访问类的非公有成员变量或方法的四种途径,以方便测试人员在需要访问类非公有成员变量或方法时进行选择。

      尽管有很多经验丰富的程序员认为不应该提倡访问类的私有成员变量或方法,因为这样做违反了 Java 语言封装性的基本规则。然而,在实际测试中被测试的对象千奇百怪,为了有效快速的进行单元测试,有时我们不得不违反一些这样或那样的规则。本文只讨论如何访问类的非公有成员变量或方法,至于是否应该在开发测试中这样做,则留给读者自己根据实际情况去判断和选择。

      方法一:修改访问权限修饰符

      先介绍最简单也是最直接的方法,就是利用 Java 语言自身的特性,达到访问非公有成员的目的。说白了就是直接将 private 和 protected 关键字改为 public 或者直接删除。我们建议直接删除,因为在 Java 语言定义中,缺省访问修饰符是包可见的。这样做之后,我们可以另建一个源码目录 —— test 目录(多数 IDE 支持这么做,如 Eclipse 和 JBuilder),然后将测试类放到 test 目录相同包下,从而达到访问待测类的成员变量和方法的目的。此时,在其它包的代码依然不能访问这些变量或方法,在一定程度上保障了程序的封装性。

      下面的代码示例展示了这一方法。

      清单 1. 原始待测类 A 代码

      public class A {    private String name = null;    private void calculate() {    }}

      清单 2. 针对单元测试修改后的待测类 A 的代码

      public class A {    String name = null;    private void calculate() {    }}

      这种方法虽然看起来简单粗暴,但经验告诉我们这个方法在测试过程中是非常有效的。当然,由于改变了源代码,虽然只是包可见,也已经破坏了对象的封装性,对于多数对代码安全性要求严格的系统此方法并不可取。

      方法二:利用安全管理器

      安全性管理器与反射机制相结合,也可以达到我们的目的。Java 运行时依靠一种安全性管理器来检验调用代码对某一特定的访问而言是否有足够的权限。具体来说,安全性管理器是 java.lang.SecurityManager 类或扩展自该类的一个类,且它在运行时检查某些应用程序操作的权限。换句话说,所有的对象访问在执行自身逻辑之前都必须委派给安全管理器,当访问受到安全性管理器的控制,应用程序就只能执行那些由相关安全策略特别准许的操作。因此安全管理器一旦启动可以为代码提供足够的保护。默认情况下,安全性管理器是没有被设置的,除非代码明确地安装一个默认的或定制的安全管理器,否则运行时的访问控制检查并不起作用。我们可以通过这一点在运行时避开 Java 的访问控制检查,达到我们访问非公有成员变量或方法的目的。为能访问我们需要的非公有成员,我们还需要使用 Java 反射技术。Java 反射是一种强大的工具,它使我们可以在运行时装配代码,而无需在对象之间进行源代码链接,从而使代码更具灵活性。在编译时,Java 编译程序保证了私有成员的私有特性,从而一个类的私有方法和私有成员变量不能被其他类静态引用。然而,通过 Java 反射机制使得我们可以在运行时查询以及访问变量和方法。由于反射是动态的,因此编译时的检查就不再起作用了。

      下面的代码演示了如何利用安全性管理器与反射机制访问私有变量。

      清单 3. 利用反射机制访问类的成员变量

      //获得指定变量的值

      public static Object getValue(Object instance, String fieldName)

      throws   IllegalAccessException, NoSuchFieldException ...{

      Field field = getField(instance.getClass(), fieldName);

      // 参数值为true,禁用访问控制检查

      field.setAccessible(true);

      return field.get(instance);

      }

      //该方法实现根据变量名获得该变量的值

      public static Field getField(Class thisClass, String fieldName)

      throws NoSuchFieldException ...{

      if (thisClass == null) ...{

      throw new NoSuchFieldException("Error field !");

      }

      }

      其中 getField(instance.getClass(), fieldName) 通过反射机制获得对象属性,如果存在安全管理器,方法首先使用 this 和 Member.DECLARED 作为参数调用安全管理器的 checkMemberAccess 方法,这里的 this 是 this 类或者成员被确定的父类。 如果该类在包中,那么方法还使用包名作为参数调用安全管理器的 checkPackageAccess 方法。 每一次调用都可能导致 SecurityException。当访问被拒绝时,这两种调用方式都会产生 securityexception 异常 。

      setAccessible(true) 方法通过指定参数值为 true 来禁用访问控制检查,从而使得该变量可以被其他类调用。我们可以在我们所写的类中,扩展一个普通的基本类 java.lang.reflect.AccessibleObject 类。这个类定义了一种 setAccessible 方法,使我们能够启动或关闭对这些类中其中一个类的实例的接入检测。这种方法的问题在于如果使用了安全性管理器,它将检测正在关闭接入检测的代码是否允许这样做。如果未经允许,安全性管理器抛出一个例外。

      除访问私有变量,我们也可以通过这个方法访问私有方法。

      清单 4. 利用反射机制访问类的成员方法

      public static Method getMethod(Object instance, String methodName, Class[] classTypes)

      throws   NoSuchMethodException ...{

      Method accessMethod = getMethod(instance.getClass(), methodName, classTypes);

      //参数值为true,禁用访问控制检查

      accessMethod.setAccessible(true);

      return accessMethod;

      }

      private static Method getMethod(Class thisClass, String methodName, Class[] classTypes)

      throws NoSuchMethodException ...{

      if (thisClass == null) ...{

      throw new NoSuchMethodException("Error method !");

      } try ...{

      return thisClass.getDeclaredMethod(methodName, classTypes);

      } catch (NoSuchMethodException e) ...{

      return getMethod(thisClass.getSuperclass(), methodName, classTypes);

      }

      }

      获得私有方法的原理与获得私有变量的方法相同。当我们得到了函数后,需要对它进行调用,这时我们需要通过 invoke() 方法来执行对该函数的调用,代码示例如下:

      //调用含单个参数的方法

      public static Object invokeMethod(Object instance, String methodName, Object arg)

      throws NoSuchMethodException,

      IllegalAccessException, InvocationTargetException ...{

      Object[] args = new Object[1];

      args[0] = arg;

      return invokeMethod(instance, methodName, args);

      }

    //调用含多个参数的方法

      public static Object invokeMethod(Object instance, String methodName, Object[] args)

      throws NoSuchMethodException,

      IllegalAccessException, InvocationTargetException ...{

      Class[] classTypes = null;

      if (args != null) ...{

      classTypes = new Class[args.length];

      for (int i = 0; i < args.length; i++) ...{

      if (args[i] != null) ...{

      classTypes[i] = args[i].getClass();

      }

      }

      }

      return getMethod(instance, methodName, classTypes).invoke(instance, args);

      }

      利用安全管理器及反射,可以在不修改源码的基础上访问私有成员,为测试带来了极大的方便。尤其是在编译期间,该方法可以顺利地通过编译。但同时该方法也有一些缺点。第一个是性能问题,用于字段和方法接入时反射要远慢于直接代码。第二个是权限问题,有些涉及 Java 安全的程序代码并没有修改安全管理器的权限,此时本方法失效。

      另一种方法

      package test;

      import java.lang.reflect.Field;

      import model.Dept;

      public class TypeTest {

      public static void main(String args[])

      {

      Dept d=new Dept();

      d.setDeptNo(111);

      d.setDName("v0");

      d.setLoc("mopish");

      delete(d, Dept.class);

      }

      public static void delete(Object obj, Class<?> clazz)

      {

      try

      {

      System.out.println("?"+(obj instanceof Dept));

      System.out.println(clazz.getName());

      System.out.println(clazz.getDeclaredFields().length);

      for(Field f: clazz.getDeclaredFields())

      {

      f.setAccessible(true);

      System.out.println(f.getName());

      System.out.println(""+f.get(obj));

      }

      }catch(Exception e)

      {

      e.printStackTrace();

      }

      }

      }

      package model;

      public class Dept {

      private long deptNo;

      private String DName;

      private String Loc;

      public long getDeptNo() {

      return deptNo;

      }

      public void setDeptNo(long deptNo) {

      this.deptNo = deptNo;

      }

      public String getDName() {

      return DName;

      }

      public void setDName(String dName) {

      DName = dName;

      }

      public String getLoc() {

      return Loc;

      }

      public void setLoc(String loc) {

      Loc = loc;

      }

      }

    展开全文
  • 资料一:  引言  对于软件开发人员来说,单元测试是一项必不可少的工作。...本文总结了访问类的非公有成员变量或方法的四种途径,以方便测试人员在需要访问类非公有成员变量或方法时进行选择。

    资料一:

      引言

      对于软件开发人员来说,单元测试是一项必不可少的工作。它既可以验证程序的有效性,又可以在程序出现 BUG 的时候,帮助开发人员快速的定位问题所在。但是,在写单元测试的过程中,开发人员经常要访问类的一些非公有的成员变量或方法,这给测试工作带来了很大的困扰。本文总结了访问类的非公有成员变量或方法的四种途径,以方便测试人员在需要访问类非公有成员变量或方法时进行选择。

      尽管有很多经验丰富的程序员认为不应该提倡访问类的私有成员变量或方法,因为这样做违反了 Java 语言封装性的基本规则。然而,在实际测试中被测试的对象千奇百怪,为了有效快速的进行单元测试,有时我们不得不违反一些这样或那样的规则。本文只讨论如何访问类的非公有成员变量或方法,至于是否应该在开发测试中这样做,则留给读者自己根据实际情况去判断和选择。

      方法一:修改访问权限修饰符

      先介绍最简单也是最直接的方法,就是利用 Java 语言自身的特性,达到访问非公有成员的目的。说白了就是直接将 private 和 protected 关键字改为 public 或者直接删除。我们建议直接删除,因为在 Java 语言定义中,缺省访问修饰符是包可见的。这样做之后,我们可以另建一个源码目录 —— test 目录(多数 IDE 支持这么做,如 Eclipse 和 JBuilder),然后将测试类放到 test 目录相同包下,从而达到访问待测类的成员变量和方法的目的。此时,在其它包的代码依然不能访问这些变量或方法,在一定程度上保障了程序的封装性。

      下面的代码示例展示了这一方法。

      清单 1. 原始待测类 A 代码

      public class A {    private String name = null;    private void calculate() {    }}

      清单 2. 针对单元测试修改后的待测类 A 的代码

      public class A {    String name = null;    private void calculate() {    }}

      这种方法虽然看起来简单粗暴,但经验告诉我们这个方法在测试过程中是非常有效的。当然,由于改变了源代码,虽然只是包可见,也已经破坏了对象的封装性,对于多数对代码安全性要求严格的系统此方法并不可取。

      方法二:利用安全管理器

      安全性管理器与反射机制相结合,也可以达到我们的目的。Java 运行时依靠一种安全性管理器来检验调用代码对某一特定的访问而言是否有足够的权限。具体来说,安全性管理器是 java.lang.SecurityManager 类或扩展自该类的一个类,且它在运行时检查某些应用程序操作的权限。换句话说,所有的对象访问在执行自身逻辑之前都必须委派给安全管理器,当访问受到安全性管理器的控制,应用程序就只能执行那些由相关安全策略特别准许的操作。因此安全管理器一旦启动可以为代码提供足够的保护。默认情况下,安全性管理器是没有被设置的,除非代码明确地安装一个默认的或定制的安全管理器,否则运行时的访问控制检查并不起作用。我们可以通过这一点在运行时避开 Java 的访问控制检查,达到我们访问非公有成员变量或方法的目的。为能访问我们需要的非公有成员,我们还需要使用 Java 反射技术。Java 反射是一种强大的工具,它使我们可以在运行时装配代码,而无需在对象之间进行源代码链接,从而使代码更具灵活性。在编译时,Java 编译程序保证了私有成员的私有特性,从而一个类的私有方法和私有成员变量不能被其他类静态引用。然而,通过 Java 反射机制使得我们可以在运行时查询以及访问变量和方法。由于反射是动态的,因此编译时的检查就不再起作用了。

      下面的代码演示了如何利用安全性管理器与反射机制访问私有变量。

      清单 3. 利用反射机制访问类的成员变量

      //获得指定变量的值

      public static Object getValue(Object instance, String fieldName)

      throws   IllegalAccessException, NoSuchFieldException ...{

      Field field = getField(instance.getClass(), fieldName);

      // 参数值为true,禁用访问控制检查

      field.setAccessible(true);

      return field.get(instance);

      }

      //该方法实现根据变量名获得该变量的值

      public static Field getField(Class thisClass, String fieldName)

      throws NoSuchFieldException ...{

      if (thisClass == null) ...{

      throw new NoSuchFieldException("Error field !");

      }

      }

      其中 getField(instance.getClass(), fieldName) 通过反射机制获得对象属性,如果存在安全管理器,方法首先使用 this 和 Member.DECLARED 作为参数调用安全管理器的 checkMemberAccess 方法,这里的 this 是 this 类或者成员被确定的父类。如果该类在包中,那么方法还使用包名作为参数调用安全管理器的 checkPackageAccess 方法。 每一次调用都可能导致 SecurityException。当访问被拒绝时,这两种调用方式都会产生 securityexception 异常 。

      setAccessible(true) 方法通过指定参数值为 true 来禁用访问控制检查,从而使得该变量可以被其他类调用。我们可以在我们所写的类中,扩展一个普通的基本类 java.lang.reflect.AccessibleObject 类。这个类定义了一种 setAccessible 方法,使我们能够启动或关闭对这些类中其中一个类的实例的接入检测。这种方法的问题在于如果使用了安全性管理器,它将检测正在关闭接入检测的代码是否允许这样做。如果未经允许,安全性管理器抛出一个例外。

      除访问私有变量,我们也可以通过这个方法访问私有方法。

      清单 4. 利用反射机制访问类的成员方法

      public static Method getMethod(Object instance, String methodName, Class[] classTypes)

      throws   NoSuchMethodException ...{

      Method accessMethod = getMethod(instance.getClass(), methodName, classTypes);

      //参数值为true,禁用访问控制检查

      accessMethod.setAccessible(true);

      return accessMethod;

      }

      private static Method getMethod(Class thisClass, String methodName, Class[] classTypes)

      throws NoSuchMethodException ...{

      if (thisClass == null) ...{

      throw new NoSuchMethodException("Error method !");

      } try ...{

      return thisClass.getDeclaredMethod(methodName, classTypes);

      } catch (NoSuchMethodException e) ...{

      return getMethod(thisClass.getSuperclass(), methodName, classTypes);

      }

      }

      获得私有方法的原理与获得私有变量的方法相同。当我们得到了函数后,需要对它进行调用,这时我们需要通过 invoke() 方法来执行对该函数的调用,代码示例如下:

      //调用含单个参数的方法

      public static Object invokeMethod(Object instance, String methodName, Object arg)

      throws NoSuchMethodException,

      IllegalAccessException, InvocationTargetException ...{

      Object[] args = new Object[1];

      args[0] = arg;

      return invokeMethod(instance, methodName, args);

      }

      //调用含多个参数的方法

      public static Object invokeMethod(Object instance, String methodName, Object[] args)

      throws NoSuchMethodException,

      IllegalAccessException, InvocationTargetException ...{

      Class[] classTypes = null;

      if (args != null) ...{

      classTypes = new Class[args.length];

      for (int i = 0; i < args.length; i++) ...{

      if (args[i] != null) ...{

      classTypes[i] = args[i].getClass();

      }

      }

      }

      return getMethod(instance, methodName, classTypes).invoke(instance, args);

      }

      利用安全管理器及反射,可以在不修改源码的基础上访问私有成员,为测试带来了极大的方便。尤其是在编译期间,该方法可以顺利地通过编译。但同时该方法也有一些缺点。第一个是性能问题,用于字段和方法接入时反射要远慢于直接代码。第二个是权限问题,有些涉及 Java 安全的程序代码并没有修改安全管理器的权限,此时本方法失效。

      另一种方法

      package test;

      import java.lang.reflect.Field;

      import model.Dept;

      public class TypeTest {

      public static void main(String args[])

      {

      Dept d=new Dept();

      d.setDeptNo(111);

      d.setDName("v0");

      d.setLoc("mopish");

      delete(d, Dept.class);

      }

      public static void delete(Object obj, Class<?> clazz)

      {

      try

      {

      System.out.println("?"+(obj instanceof Dept));

      System.out.println(clazz.getName());

      System.out.println(clazz.getDeclaredFields().length);

      for(Field f: clazz.getDeclaredFields())

      {

      f.setAccessible(true);

      System.out.println(f.getName());

      System.out.println(""+f.get(obj));

      }

      }catch(Exception e)

      {

      e.printStackTrace();

      }

      }

      }

      package model;

      public class Dept {

      private long deptNo;

      private String DName;

      private String Loc;

      public long getDeptNo() {

      return deptNo;

      }

      public void setDeptNo(long deptNo) {

      this.deptNo = deptNo;

      }

      public String getDName() {

      return DName;

      }

      public void setDName(String dName) {

      DName = dName;

      }

      public String getLoc() {

      return Loc;

      }

      public void setLoc(String loc) {

      Loc = loc;

      }

      }


    资料二:

    public   class   X{
      private   String   secret= "1233 ";
      //...other   method   or   field
    }

    Class   a=Class.forName( "X ");
    Field   f=a.getDeclaredField( "secret ")
    System.out.println(f.isAccessible())
    f.setAccessiable(true);
    System.out.println(f.get(new   X()));


    资料三:

    在java类中,private成员一般只有在本类中才可以访问,在这里我们将通过java反射机制从外部类中访问private成员。

    首先我们写一个类:

    PrivateCar.java

    package reflect;

    public class PrivateCar {

    private String color;
     protected void drive(){
      System.out.println("driveprivate car!the color is:"+color);
     }
    }

    再写个测试类以访问PrivateCar中的color属性。

    PrivateCarReflect.java

    package reflect;

    import java.lang.reflect.Field;
    import java.lang.reflect.Method;

    public class PrivateCarReflect {

    public static void main(String args[])throws Throwable{
      ClassLoaderloader=Thread.currentThread().getContextClassLoader();
      Classclazz=loader.loadClass("reflect.PrivateCar");
      PrivateCarpcar=(PrivateCar)clazz.newInstance();
      FieldcolorFid=clazz.getDeclaredField("color");
      colorFid.setAccessible(true);//取消java语言访问检查以访问private变量
      colorFid.set(pcar, "红色");
      
      MethoddriveMtd=clazz.getDeclaredMethod("drive", (Class[])null);
      driveMtd.setAccessible(true);
      driveMtd.invoke(pcar,(Object[])null);
     }
    }

    最后打印结果为:drive private car!the color is:红色。

    在访问private、protected成员变量和方法时必须通过setAccessible方法取消java语言检查,否则将会抛出IllegalAccessExcepion。如果JVM的安全管理器设置了相应的安全机制,调用该方法将抛出SecurityException.



    展开全文
  • 父类User,包含私有变量name和money; 以及两个构造函数和基本的getter方法。 public class User { public User() { } public User(String name, int money) { this.name = name; this.money = money; } ...
  • 1.Python中的变量函数名以两个下划线“__”开头的,被视为私有的,类似java中的private,不能直接访问; 2.不能直接访问__name是因为Python解释器对外把变量函数__name(__name())改成了_classname__name(_...
  • 主要介绍了Java面向对象类的定义,静态变量,成员变量,构造函数,封装与私有,this概念与用法,较为详细的分析了Java类的定义,静态变量,成员变量,构造函数,封装,私有等相关原理、用法及操作注意事项,需要的朋友...
  • Ext JS 构造函数私有变量和静态变量
  • Java私有构造函数的使用

    万次阅读 2015-11-26 21:02:03
    Java私有构造函数的使用当我们学习Java的时候,我们接触到的构造函数的权限修饰符都是public,比如,public class Test { public Test() { } } }我们,知道构造函数的用途是创建一个对象,并返回。比如,Test ...
  • public class Test5 {   //定义包含私有成员变量函数  private int a = 201320883;  private void funcOut(){  System.out.println("out function run print:" + a);   
  • 关于Java子类访问父类的私有变量

    千次阅读 2013-10-25 13:14:33
    为了测试,我写了三个java类, father.java son.java test.java 专门来测试,关于局部变量,以及子类调用父类的私有变量。  father.java 如下:
  • 父类中只有含参的构造函数 class Animal { public String name; public int weight; public Animal(String name, int weight) { this.name = name; this.weight = weight; } } 如上面的代码所示,父类...
  • 如果子类和父类中出现非私有同名成员变量时 子类要访问本类的变量,用this 子类要访问父类的同名变量 用super super的使用和this的使用几乎一致; 2.子类中的函数: 当子类出现和父类一模一样的函数时, 当...
  • Java反射获取类的私有变量

    千次阅读 2018-02-24 09:33:50
    从设计的原则来说,类的成员变量如果设计成private,那么我们就不能在类外部去获取到此private变量的值。通常的做法是提供此private变量的get 和set方法。但是如果这个类没有提供get和set方法,我们如何去获取到这个...
  • Python中,外部操作函数内部私有变量 方法1,类似于Java中,添加getter和setter方法。 方法2,采用高级特性@property、@methodname.setter处理 测试代码:函数内部定义了私有变量,外部无法调用 class ...
  • JavaScript中的私有变量

    千次阅读 2017-03-30 11:46:55
    我们之前通过各种构造模式构建js对象,都是直接将属性添加在...首先我们要知道,函数内部的变量(使用var定义)不能被函数外部访问到,这就是函数私有变量。那我们可以利用这一点来创建有私有变量的对象:在函数内部
  • student1是公有变量,可以在函数外修改变量,比如我写的right部分; student2是私有变量,但是不可以在函数外修改变量,比如我写的wrong部分;...公有变量和私有变量的表面区别,就是在变量前了两个下划线__...
  • JAVA中的父类私有成员变量的继承问题

    千次阅读 多人点赞 2019-04-25 17:36:35
    如果父类中属性为私有(private),那么能否被子类继承呢? 答案是不可以。 我们看如下简单代码 class Father { private String name; public void sayHi() { System.out.println("My name is " + this....
  • perl不像C++、java,在类中可以直接通过private来声明成员私有。对于成员变量,如果我们在类中直接声明,那么,perl会认为这是一个类变量,即相当于C++里面的static成员变量,该变量被所有类共享,要声明私有,只有...
  • js:私有变量

    2019-01-15 13:01:09
    私有变量 1. 在私有作用域下定义的变量都是私有变量; 2. 形参也是私有变量; 3. 函数体中通过function定义的函数也是私有的,在全局作用域不能使用; 复制代码...
  • 因为成员变量的初始化时间先于类的构造函数执行前,自然保证了成员变量已经被赋值。(2)静态方法中,先实例化类,利用实例化类的引用才能调用。 3、this关键字:(1)不能在静态方法中使用。 ...
  • JavaScript如何实现私有变量私有方法

    千次阅读 2019-03-11 17:58:27
    那JavaScript如何能实现私有变量呢,下面来介绍几种实现方式。 一、函数作用域封装局部变量的方式。 1.1 闭包定义局部变量(自执行函数) var PClass = (function(){ var a = '私有变量'; var getA = ...
  • eclipse 选中声明 source -&gt; get set…
  • 使用构造函数实现实例私有变量:私有变量函数和公有特权方法每个实例都有独立的一份 使用原型模式+块级作用域实现静态私有变量:私有变量函数和公有特权方法每个实例都共享一份 1.块级作用域 javascript不像其他语言...
  • Python中定义“私有”成员变量和成员函数 参考连接:http://docs.python.org/2/tutorial/classes.html http://www.pythonclub.org/python-class/private  ...
  • 实际上,private,public,protected和继承没有关系,他们对成员函数变量的限制只是在成员的可见性上。”参考:私有的成员能被子类继承吗? 3、观点三: “父类的private变量,也会被继承并且初始化在子类父对象中,只...
  • 众所周知,子类可以继承父类所有的变量和方法,但是有没有想过子类为何能继承它们,它们是凭空继承而来的么?当然不是,其实每当调用子类构造器new一个子类对象的时候,都要先调用父类的构造new一个父类对象,父类...
  • ------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 128,001
精华内容 51,200
关键字:

java自动添加私有变量设置函数

java 订阅