2024年10月java反射调用private方法(Java反射访问私有变量和私有方法)

 更新时间:2024-10-12

  ⑴java反射调用private方法(Java反射访问私有变量和私有方法

  ⑵Java反射访问私有变量和私有方法

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

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

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

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

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

  ⑻清单原始待测类A代码

  ⑼publilassA{???privateStringname=null;???privatevoidcalculate(){???}}

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

  ⑾publilassA{???Stringname=null;???privatevoidcalculate(){???}}

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

  ⒀方法二利用安全管理器

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

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

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

  ⒄//获得指定变量的值

  ⒅publicstaticObjectgetValue(ObjectinstanceStringfieldName)

  ⒆throws??IllegalAessExceptionNoSuchFieldException{

  ⒇Fieldfield=getField(instancegetClass()fieldName);

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

  ⒉fieldsetAessible(true);

  ⒊returnfieldget(instance);

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

  ⒌publicstaticFieldgetField(ClassthisClassStringfieldName)

  ⒍throwsNoSuchFieldException{

  ⒎if(thisClass==null){

  ⒏thrownewNoSuchFieldException(Errorfield!);

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

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

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

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

  ⒔publicstaticMethodgetMethod(ObjectinstanceStringmethodNameClassclassTypes)

  ⒕throws??NoSuchMethodException{

  ⒖MethodaessMethod=getMethod(instancegetClass()methodNameclassTypes);

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

  ⒘aessMethodsetAessible(true);

  ⒙returnaessMethod;

  ⒚privatestaticMethodgetMethod(ClassthisClassStringmethodNameClassclassTypes)

  ⒛throwsNoSuchMethodException{

  if(thisClass==null){

  thrownewNoSuchMethodException(Errormethod!);

  returnthisClassgetDeclaredMethod(methodNameclassTypes);

  }catch(NoSuchMethodExceptione){

  returngetMethod(thisClassgetSuperclass()methodNameclassTypes);

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

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

  publicstaticObjectinvokeMethod(ObjectinstanceStringmethodNameObjectarg)

  throwsNoSuchMethodException

  IllegalAessExceptionInvocationTargetException{

  returninvokeMethod(instancemethodNameargs);

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

  publicstaticObjectinvokeMethod(ObjectinstanceStringmethodNameObjectargs)

  throwsNoSuchMethodException

  IllegalAessExceptionInvocationTargetException{

  ClassclassTypes=null;

  if(args!=null){

  classTypes=newClass;

  for(inti=;i《argslength;i++){

  if(args!=null){

  classTypesgetClass();

  returngetMethod(instancemethodNameclassTypes)invoke(instanceargs);

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

  packagetest;

  importjavalangreflectField;

  importmodelDept;

  publilassTypeTest{

  publicstaticvoidmain(Stringargs)

  Deptd=newDept();

  dsetDeptNo();

  dsetDName(v);

  dsetLoc(mopish);

  delete(dDeptclass);

  publicstaticvoiddelete(ObjectobjClass《?》clazz)

  Systemoutprintln(?+(objinstanceofDept));

  Systemoutprintln(clazzgetName());

  Systemoutprintln(clazzgetDeclaredFields()length);

  for(Fieldf:clazzgetDeclaredFields())

  fsetAessible(true);

  Systemoutprintln(fgetName());

  Systemoutprintln(+fget(obj));

  }catch(Exceptione)

  eprintStackTrace();

  packagemodel;

  publilassDept{

  privatelongdeptNo;

  privateStringDName;

  privateStringLoc;

  publiclonggetDeptNo(){

  returndeptNo;

  publicvoidsetDeptNo(longdeptNo){

  thisdeptNo=deptNo;

  publicStringgetDName(){

  returnDName;

  publicvoidsetDName(StringdName){

  DName=dName;

  publicStringgetLoc(){

  returnLoc;

  publicvoidsetLoc(Stringloc){

  }lishixinzhi/Article/program/Java/hx//

  java反射机制调用class方法,但是这个类有一个private的构造方法无法new和newInstance

  public?static?void?main(String?args)?throws?Exception?{????Class《ModTest》?modTestClass?=?ModTest.class;????Constructor《ModTest》?declaredConstructor?=?modTestClass.getDeclaredConstructor();????declaredConstructor.setAessible(true);????Method?method?=?modTestClass.getDeclaredMethod(“testM“,?String.class);????method.setAessible(true);????Object?aa?=?method.invoke(declaredConstructor.newInstance(),?“aa“);????System.out.println(aa);}

  代码如上,使用暴力反射即可.

  请教java反射机制里可以调用私有方法吗

  Methodmethod=c.getDeclaredMethod(name);//可以调用类中的所有方法(不包括父类中继承的方法Methodmethod=c.getMethod(name);//可以调用类中有访问权限的方法(包括父类中继承的方法

  java反射,调用private的方法

  so?easyString?path=“.test.B”Class?clazz?=?Class.forName(path);???//获得b的反射B?b?=(B)clazz.newInstance();???//前提是b类有个无参构造函数Method?m?=?clazz.getDeclaredMehod(“SetName“,String.class);m.setAessible(true);????//不做安全检查,你才可以去访问私有方法m.invoke(b,“哈哈“);这里是给B里面的(下面这个方法进行调用赋值)private?void?SetName(String?s){}ps??getDeclaredMehod?是对私有的方法进行调用?要访问必须加setAessible????getMehod?是对通用方法进行调用,不用加setAessible

  java反射访问私有方法的的问题

  java的反射可以绕过访问权限,访问到类的私有方法和成员。可能这点会引起安全性的讨论。反射的使用帮助解决很多复杂的问题,其运行时的类型检查,动态调用,代理的实现等,反射为我们写程序带来了很大的灵活性,很多功能都是基于反射。利用反射还可以访问内部类、匿名内部类的私有属性。用java自带的java-private类名反编译命令可以查看类的完整定义。(参考thinkinjava下面举例子说明。首先定义一个接口Java代码publicinterfaceRef{publicvoidf();}publicinterfaceRef{publicvoidf();}接口的实现类Java代码publilassRefImplimplementsRef{//实现接口方法publicvoidf(){System.out.println(“publicmethodf()“);}voidg(Stringargs){System.out.println(“packagemethodg():“+args);}privatevoidw(){System.out.println(“privatemethodw()“);}}publilassRefImplimplementsRef{//实现接口方法publicvoidf(){System.out.println(“publicmethodf()“);}voidg(Stringargs){System.out.println(“packagemethodg():“+args);}privatevoidw(){System.out.println(“privatemethodw()“);}}测试类Java代码publilassTestRef{publicstaticvoidmain(Stringargs){Refref=newRefImpl();System.out.println(ref.getClass().getSimpleName());//RefImpl类型ref.f();//调用接口方法//ref.g();//向上转型后实现类添加的方法不能调用if(refinstanceofRefImpl){RefImplref=(RefImpl)ref;//类型识别后转型ref.g(“zhouyang“);//ref.w();//私有方法不能访问}//通过反射调用方法try{Refref=newRefImpl();Methodm=ref.getClass().getDeclaredMethod(“f“);Methodm=ref.getClass().getDeclaredMethod(“g“,String.class);//有参的方法Methodm=ref.getClass().getDeclaredMethod(“w“);System.out.println(“==============“);m.invoke(ref);//调用方法f()m.invoke(ref,“yangzhou“);m.setAessible(true);///调用private方法的关键一句话m.invoke(ref);}catch(Exceptione){e.printStackTrace();}//java的javap反编译能够查看类的信息,-private开关能够打开所有信息//javap-private类名类必须是编译成.calss文件//利用反射访问私有成员,改变私有成员值,但是final域可以访问不可改变PrivateFieldpf=newPrivateField();//ps.ss;//私有成员不能访问//打印原来的成员值pf.print();try{//反射访问和改变原来值Fieldf=pf.getClass().getDeclaredFields();for(inti=;i《f.length;i++){f.setAessible(true);System.out.println(f.getType());//打印字段类型System.out.println(f.get(pf));//打印值if(“ss“.equals(f.getName())){f.set(pf,“hehe“);//修改成员值}else{f.setInt(pf,);}}//重新打印修改后的成员值,final域值不变pf.print();}catch(Exceptione){e.printStackTrace();}/*打印输出的结果*RefImplpublicmethodf()&nb

  java中的private变量与方法的调用问题

  private方法是私有的,不能从外部调用,只能内部调用private变量同理比如这个类:classA{privateinta=;}classB{publicvoidfunction(){newA().a=//这样写是错误的!}}改进方法:classA{privateinta=;publicintgeta(){returna;}}classB{publicvoidfunction(){inta=newA().geta;a+=;}}然后你希望这个a不变的话,即每次调用这个方法都公用同一个a,可以用static修饰望采纳

  java反射调用private方法

  Java程序不能访问持久化类的private方法,但是利用JAVA的反射机制可以实现调用,代码如下:

  《span?style=“font-size:px;“》import?java.lang.reflect.InvocationTargetException;import?java.lang.reflect.Method;public?class?ReflectDemo?{public?static?void?main(String?args)?throws?Exception?{Method?method?=?PackageClazz.class.getDeclaredMethod(“privilegedMethod“,?new?Class{String.class,String.class});??method.setAessible(true);method.invoke(new?PackageClazz(),?““,“q“);}}class?PackageClazz?{private?void?privilegedMethod(String?invokerName,String?adb)?{System.out.println(“---“+invokerName+“----“+adb);}}《/span》#程序输出结果为:-------q

  java一个类文件中的private方法想在另一个类文件中调用怎么办,前提是不改变修饰符

  可以在这个类中预留一个public的方法作为入口。一般规范化的java程序,成员变量都是private保护,然后用的时候public预留出去。private是继承不了的。private只有本类引用,继承至少为default权限。创建类对象更不用说了,private就是为了不让你创建对象时直接用的。

  java反射机制可以调用到私有方法,是不是就破坏了JAVA的卦装性呢

  这是一个很值得探讨的问题,许多人接触反射时,对反射功能之强大都会抱有怀疑,感觉严重破坏了封装的性质。可是,什么是封装,什么是安全呢?封装,是将具体的实现细节隐藏,而把功能作为整体提供给类的外部使用,也就是说,公有方法能够完成类所具有的功能。当别人使用这个类时,如果通过反射直接调用私有方法,可能根本实现不了类的功能,甚至可能会出错,因此通过反射调用私有方法可以说是没有任何用处的,开发人员没有必要故意去破坏封装好的类。从这点上看,封装性并没有被破坏。所谓安全,如果意思是保护实现源码不被别人看见,那没有作用。不用反射也能轻易获取源码。所以我以为反射机制只是提供了一种强大的功能,使得开发者能在封装之外,按照特定的需要实现一些功能。就好比核技术,虽然造核弹很危险吧,但造核电站还是很有用处的(这个比喻似乎不是很恰当,将就将就。曾经给朋友讨论过这个问题,感觉解释得不是很清楚,大家一起探讨探讨,看看怎样表述才能更容易理解:

  反射调用private方法实践(php、java)

  单测中有个普遍性的问题,被侧类中的private方法无法直接调用。小拽在处理过程中通过反射改变方法权限,进行单测,分享一下,直接上代码。简单被测试类生成一个简单的被测试类,只有个private方法。复制代码代码如下:《?php/***崔小涣单测的基本模板。**authorcuihuan*date//::*version$Revision:.$**/classMyClass{/***私有方法**param$params*returnbool*/privatefunctionprivateFunc($params){if(!isset($params)){returnfalse;}echo“testsuess“;return$params;}}单测代码复制代码代码如下:《?php/*****************************************************************************$Id:MyClassTestT,v.PsCaseTestcuihuanExp$***************************************************************************//***崔小涣单测的基本模板。**authorcuihuan*date//::*version$Revision:.$**/require_once(’);classMyClassTestextendsPHPUnit_Framework_TestCase{constCLASS_NAME=’MyClass’;constFAIL=’fail’;protected$objMyClass;/***briefsetup:Setsupthefixture,forexample,opensaworkconnection.**可以看做phpunit的构造函数*/publicfunctionsetup(){date_default_timezone_set(’PRC’);$this-》objMyClass=newMyClass();}/***利用反射,对类中的private和protect方法进行单元测试**param$strMethodNamestring:反射函数名*returnReflectionMethodobj:回调对象*/protectedstaticfunctiongetPrivateMethod($strMethodName){$objReflectClass=newReflectionClass(self::CLASS_NAME);$method=$objReflectClass-》getMethod($strMethodName);$method-》setAessible(true);return$method;}/***brief:测试private函数的调用*/publicfunctiontestPrivateFunc(){$testCase=’justateststring’;//反射该类$testFunc=self::getPrivateMethod(’privateFunc’);$res=$testFunc-》invokeArgs($this-》objMyClass,array($testCase));$this-》assertEquals($testCase,$res);$this-》expectOutputRegex(’/suess/i’);//捕获没有参数异常测试try{$testFunc-》invokeArgs($this-》transferPscase,array());}catch(Exception$expected){$this-》assertNotNull($expected);returntrue;}$this-》fail(self::FAIL);}}运行结果cuihuan:testcuixiaohuan$phpunitMyClassTest.phpPHPUnit..bySebastianBergmannandcontributors.Time:ms,Memory:.MbOK(test,assertions)关键代码分析封装了一个,被测类方法的反射调用;同时,返回方法之前处理方法的接入权限为true,便可以访问private的函数方法。复制代码代码如下:/***利用反射,对类中的private和protect方法进行单元测试**param$strMethodNamestring:反射函数名*returnReflectionMethodobj:回调对象*/protectedstaticfunctiongetPrivateMethod($strMethodName){$objReflectClass=newReflectionClass(self::CLASS_NAME);$method=$objReflectClass-》getMethod($strMethodName);$method-》setAessible(true);return$method;}下面给大家分享java中利用反射调用另一类的private方法我们知道,Java应用程序不能访问持久化类的private方法,但Hibernate没有这个限制,它能够访问各种级别的方法,如private,default,protected,public.Hibernate是如何实现该功能的呢?答案是利用JAVA的反射机制,如下:《spanstyle=“font-size:px;“》importjava.lang.reflect.InvocationTargetException;importjava.lang.reflect.Method;publilassReflectDemo{publicstaticvoidmain(Stringargs)throwsException{Methodmethod=PackageClazz.class.getDeclaredMethod(“privilegedMethod“,newClass{String.class,String.class});method.setAessible(true);method.invoke(newPackageClazz(),““,“q“);}}classPackageClazz{privatevoidprivilegedMethod(StringinvokerName,Stringadb){System.out.println(“---“+invokerName+“----“+adb);}}《/span》输出结果为:-------q

您可能感兴趣的文章:

相关文章