之前我看到过一个问题:
在一个类中,用private修饰的变量可以通过反射机制获得,那么private是不是没有意义了?
[这个问题放在这里,希望今天可以解决!]
它基本的思想就是,java中的类也是一个对象,它是java.lang.Class的实例化对象;
创建Class对象,有三种方法
1.class c= demo.class();
类的class属性
2.使用Class类的ForName方法
3.使用Object对象的getClass方法
三种方法都可以获得需要的Class对象,那么有什么区别,用下面的代码试试:
package test;
import java.io.*;
import java.lang.Class;
class A{
};
public class Test {
public static void main(String arg[]) {
Class a=A.class;
System.out.println("第一种方法:"+a.hashCode());
try {
Class b=Class.forName("test.A");
System.out.println("第二种方法:"+b.hashCode());
}catch(ClassNotFoundException e) {
e.printStackTrace();
}
A d=new A();
Class c=d.getClass();
System.out.println("第三种方法:"+c.hashCode());
}
}
运行结果如下:
三种方法获得的Class对象的哈希编码都一样,所以可以认为方法虽然不一样,但是最后得到的结果是完全一样的,也就是说得到的是如下的结构:
接下来讲的是一波对于类的形式的判定方法,比如isPublic , isProtected等等
测试就不在这里放了
接下来就是和在文章头部提出的问题相关的获取成员变量了
package test;
public class GetFieldTest {
int i=1;
public long a;
protected boolean b;
private String s;
}
这个是我的测试类,虽然没啥东西,咳咳,不要在意嘛
下面是测试代码:
package test;
import java.lang.reflect.*;
public class GetField {
public static void main(String[] args) {
// TODO Auto-generated method stub
GetFieldTest ex=new GetFieldTest();
Class exC=ex.getClass();
Field[] declaredField=exC.getDeclaredFields();
for(int i=0;i<declaredField.length;i++) {
Field field=declaredField[i];
System.out.println("变量名称:"+field.getName());
Class fieldType=field.getType();
System.out.println("变量l类型:"+fieldType);
boolean x=true;
while(x) {
try {
x=false;
System.out.println("修改前变量值为:"+field.get(ex));
if(fieldType.equals(int.class)) {
System.out.println("设置int型变量值");
field.setInt(ex, 521);
}else if(fieldType.equals(boolean.class)) {
System.out.println("设置boolean型变量值");
field.setBoolean(ex,true);
}else if(fieldType.equals(String.class)) {
System.out.println("设置String型变量值");
field.set(ex,"this is for xueguo");
}else {
System.out.println("设置long型变量值");
field.setLong(ex, (long) 5.20);
}
System.out.println("修改为:"+field.get(ex));
}catch(Exception e) {
e.printStackTrace();
System.out.println("设置成员变量时抛出异常:"+"下面使用setAccessible方法");
field.setAccessible(true);
x=true;
}
}
System.out.println("\n"+"the end");
}
}
}
运行结果如下:
可以看到,我们在访问 private String s时,遇到了异常
非法访问,这里相当于通过setAccessible方法给自己一个通行证,从而获得这个变量并可以对他进行一定的操作。
那么,又回到了最初的问题,既然可以通过这样的方式获得对private变量进行相关的操作,那么它的意义是什么?
我是这样理解的,希望大家可以指正:
private并不是绝对安全的,这在上面已经论证,它最主要的意义在于封装,并保证封装数据包内的一定的安全性,由上面可知,反射机制可以破坏封装,也反映了private的安全性是很有限的,所以,我们才需要加密算法这些东西嘛。
希望大家指出问题啊!