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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java反射机制可以调用到私有方法,是否就破坏了JAVA的卦装性呢。相关的知识,希望对你有一定的参考价值。

java反射机制可以调用到私有方法,是不是就破坏了JAVA的卦装性呢。使java类不安全呢!!!求解答!!!

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

曾经给朋友讨论过这个问题,感觉解释得不是很清楚,大家一起探讨探讨,看看怎样表述才能更容易理解:)追问

的确,不过,你说的我倒是有一点明白了。谢谢啊,再看看。。。。。

追答

简单来说,就是封装不是封闭,类对于开发者来说还是开放的。一般情况下,只要类功能完好,开发者没必要故意去破坏封装性。当然也不排除会有不怀好意的情况。

参考技术A 先不谈安全不安全,了解一下概念
JAVA语言中的反射机制:
在Java 运行时 环境中,对于任意一个类,能否知道这个类有哪些属性和方法?
对于任意一个对象,能否调用他的方法?这些答案是肯定的,这种动态获取类的信息,以及动态调用类的方法的功能来源于JAVA的反射。从而使java具有动态语言的特性。

JAVA反射机制主要提供了以下功能:
1.在运行时判断任意一个对象所属的类
2.在运行时构造任意一个类的对象
3.在运行时判断任意一个类所具有的成员变量和方法(通过反射甚至可以调用private方法)
4.在运行时调用任意一个对象的方法(*****注意:前提都是在运行时,而不是在编译时)

java的封装性
类的封装既是不能让外面的类随意的修改一个类的成员变量;
在定义一个类的成员(包括变量和方法),使用private关键字讲明了成员的访问权限,只能这个类的其他成员方法调用,而不被其他类中的方法所调用;
为了实现封装性,常将类的成员变量声明为private,再通过public的方法对这个变量进行访问。对一个变量的操作,一般都有读取和赋值操作(getXXX和setXX);
一个类就是一个模块,我们应该养模块仅仅公开必要让外界知道的内容,而隐藏其他的一切内容。再进行程序设计的时,应尽量避免一个模块直接修改或操作另一个模块的数据,模块设计追求“强内聚(许多功能尽量在类的内部独立完成,不让外面干预),弱耦合(提供外部尽量少的方法调用)”。
封装应该是一种思路、思想
却不是强制的手段
毕竟java虚拟机需要通过某些手段去获悉类的内部结构和实现
通过概念的理解,不难看出,封装也绝非完全封装,凡是都是相对的。自然安全也就是相对比较安全。
参考技术B getDeclaredMethod(name, parameterTypes)使用这个方法获取方法,好好看看API,getMethod只能获取public的方法! 参考技术C 我理解的这两者不是同一层次的问题。反射可以调用私有方法,那也是因为这个机制把那个类给弄出来一个对象,这个对象调用的自己的私有方法,很正常啊。该私有方法仍在封装,别的对象也还是不能直接执行此方法。对吧
而且反射只是一种生成实例的办法。与封装没什么关系。
我的肤浅理解,见笑。
参考技术D Java语言是一个严谨的编程语言,语言本身是静态的。为了能让语言具有动态编程的特性,必须要有反射机制。而反射机制本身就是底层的处理,不可能按表层的封转特性来处理。也就是说不给调用私有方法的能力,很多程序受到局限,那么实现起来就麻烦了。
以上说的,有肯能你没明白。举一个生活的例子,你家的电视机是要由外壳的,目的是不让普通人接触到电视中的电路。那么Java语言的基本面向对象特征正是这个层次的应用。也就是对于普通程序员的程序,是通过遥控器来操作电视的。但是,如果你是一个专业的电工的话,那么可以打开电视机的后盖,调整电视中的电路和结构,甚至如果是电工的话,那么调台可能都不使用遥控器,而是通过调整内部电路的电阻的阻值来实现。Java中的反射机制正是提供更高要求的编程来使用的,不需要考虑基本面向对象的特征,而是要考虑能否得到和控制代码中的一切,这样反射机制编程才有意义。

使用反射机制调用属性和私有成员与代理模式的介绍

使用反射机制调用属性:

通过反射机制可以获得类的属性,获得到的属性同样的可以进行赋值、得值操作,调用getField方法并传递属性的名称可以获得【学Java,到凯哥学堂kaige123.com】指定的属性,调用getFields方法则可以获得全部属性,但是这种方式不能获得私有属性: 代码示例:

image

Student类示例:

image

运行结果:

image

从运行结果可以看出只拿出了公开的属性,私有的属性拿不到。

使用反射机制调用私有成员:

1.调用私有属性

在反射机制里调用私有属性需要通过getDeclaredFields方法或者getDeclaredField方法,前者是获得类里所有的私有属性,后者是获得指定的私有属性,类似于getFields和getField。但是使用getDeclaredFields或者getDeclaredField方法获得私有属性之后需要再调用setAccessible方法进行一个调用授权的操作才能对获得到的私有属性进行操作: 代码示例:

image

Student代码示例:

image

运行结果:

image

2.调用私有方法 调用私有方法也是一样的,需要先通过getDeclaredMethods方法或者getDeclaredMethod方法来获得私有方法,然后还得再调用setAccessible方法进行调用授权: 代码示例:

image

Student代码示例:

image

运行结果:

image

3.调用私有构造器

image

Student代码示例:

image

运行结果:

image

代理模式: 代理模式又称为切面编程,顾名思义就是可以把代码切开一个缝隙塞入一些代码,代理模式可以在方法的前后监控异常,也可以把日志打印语句放在代理里,方法里就不需要写日志打印的语句了,资源的开启和关闭这种重复次数多的的代码也可以写在代理里,同样的在方法里就不需要再写了,所以代理模式类似于中介一样,在代码中间解决一些反复而常规的代码。 编写代理模式的代码,第一步是写一个接口声明一个方法,第二步写一个A类去实现这个接口,在方法里写上一些代码,第三步写一个B类,这个类也要实现接口,并且在这个类的属性上声明接口的变量,构造器里声明接口类型的参数,用于把对象存储到属性里,接着在重写接口的方法里调用A实现类里的方法,第四步写运行类,在main方法里首先new A类的对象出来,然后new B 类的对象并且把A类的对象放进B类的构造器里,最后用B类的对象调用方法。 代码示例:

image

image

image

image

运行结果:

image

代码图解:

image

还可以使用继承的方式编写代理模式,但是继承有个弊端,万一这个类不允许被继承(final修饰的类),或者还需要继承其他的类(Java只能单一继承),那么就无法编写代理模式,因为接口可以实现多个,所以使用接口是最好的。 代码示例:

image

image

image

运行结果:

image

代码图解:

image

以上是关于java反射机制可以调用到私有方法,是否就破坏了JAVA的卦装性呢。的主要内容,如果未能解决你的问题,请参考以下文章

使用反射机制调用属性和私有成员与代理模式的介绍

使用反射机制调用属性和私有成员与代理模式的介绍

Java的反射机制

Java的反射机制

反射机制

利用JAVA反射机制实现调用私有方法