论坛首页 编程语言技术论坛

利用反射获取与修改private的属性的值

浏览 9659 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (1) :: 隐藏帖 (0)
作者 正文
   发表时间:2012-11-16  
1.PrivateObject.java

可以看到PrivateObject 里有一个private 的属性String型的 privateString
没有为其实义getter,setter方法。

package org.iteye.bbjava.runtimeinformation;

import java.lang.reflect.Field;

public class PrivateObject {

	private String privateString = null;

	public PrivateObject(String privateString) {
		this.privateString = privateString;
	}

}


2.Test.java
这里将对PrivateObject类进行反射取值,是一种“暴力操作”,相信经常逛论坛的同学们,应该听过这个词。
还可以“暴力修改”。

package org.iteye.bbjava.runtimeinformation;

import java.lang.reflect.Field;

public class Test {
	 public static void main(String []args) throws IllegalArgumentException, IllegalAccessException, SecurityException, NoSuchFieldException{
		  PrivateObject privateObject = new PrivateObject("The Private Value");

		  Field privateStringField = PrivateObject.class.
		              getDeclaredField("privateString");

		  privateStringField.setAccessible(true);

		  String fieldValue = (String) privateStringField.get(privateObject);
		  System.out.println("fieldValue = " + fieldValue);
	  }
}


3.console infomaction:
引用
fieldValue = The Private Value


4.接下来将对Test.java进行修改,以对“暴力修改”是如何做到的进行说明。
对比上面的Test.java这里多了8行代码,这就是“暴力修改”的关键。
其中  privateStringField.setAccessible(true); 就是对private 属性修改的“权限开关”,当设置为true时,可以修改,为false时会抛出异常,动行时信息将会给出该异常.

package org.iteye.bbjava.runtimeinformation;

import java.lang.reflect.Field;

public class Test {
	 public static void main(String []args) throws IllegalArgumentException, IllegalAccessException, SecurityException, NoSuchFieldException{
		  PrivateObject privateObject = new PrivateObject("The Private Value");

		  Field privateStringField = PrivateObject.class.
		              getDeclaredField("privateString");

		 
		  
		  privateStringField.setAccessible(true);
		  String fieldValue = (String) privateStringField.get(privateObject);
		  System.out.println("fieldValue = " + fieldValue);

		  
		  privateStringField.setAccessible(true);
		  privateStringField.set(privateObject, "As you see,privateString's value is changed!");
		  String fieldValue1 = (String) privateStringField.get(privateObject);
		  System.out.println("fieldValue = " + fieldValue1);

		  privateStringField.setAccessible(false);
		  privateStringField.set(privateObject, "As you see,privateString's value is changed!");
		  String fieldValue2 = (String) privateStringField.get(privateObject);
		  System.out.println("fieldValue = " + fieldValue2);
	  }
}



5.console infomaction:
引用
fieldValue = The Private Value
fieldValue = As you see,privateString 'value is changed!
Exception in thread "main" java.lang.IllegalAccessException: Class org.iteye.bbjava.runtimeinformation.Test can not access a member of class org.iteye.bbjava.runtimeinformation.PrivateObject with modifiers "private"
at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:65)
at java.lang.reflect.Field.doSecurityCheck(Field.java:960)
at java.lang.reflect.Field.getFieldAccessor(Field.java:896)
at java.lang.reflect.Field.set(Field.java:657)
at org.iteye.bbjava.runtimeinformation.Test.main(Test.java:25)

   发表时间:2012-11-16  
修改final类型的值才有意思
0 请登录后投票
   发表时间:2012-11-17  
freish 写道
修改final类型的值才有意思

那就失去final存在的意义了。
撸主例子不错阿。我在Java编程思想上看来,不过那例子木有撸主的好。支持。。。
0 请登录后投票
   发表时间:2012-11-17  
ifox 写道
freish 写道
修改final类型的值才有意思

那就失去final存在的意义了。
撸主例子不错阿。我在Java编程思想上看来,不过那例子木有撸主的好。支持。。。

private本来就是不给外部直接访问的,这样搞不也失去private的意义了
0 请登录后投票
   发表时间:2012-11-18  
写过一个类,可以递归打印AppClassLoader加载的类的所有属性。有空贴上来
0 请登录后投票
   发表时间:2012-11-19  
freish 写道
ifox 写道
freish 写道
修改final类型的值才有意思

那就失去final存在的意义了。
撸主例子不错阿。我在Java编程思想上看来,不过那例子木有撸主的好。支持。。。

private本来就是不给外部直接访问的,这样搞不也失去private的意义了


既然有这个api,说明sun有考虑让你打破规则不是么?
0 请登录后投票
   发表时间:2012-11-19  
freish 写道
ifox 写道
freish 写道
修改final类型的值才有意思

那就失去final存在的意义了。
撸主例子不错阿。我在Java编程思想上看来,不过那例子木有撸主的好。支持。。。

private本来就是不给外部直接访问的,这样搞不也失去private的意义了


这一般用于debug吧,不过总归是破坏封装的。

但是final修饰的变量就不通了,final变量放在栈中,跟普通变量根本无法互相转换。
0 请登录后投票
   发表时间:2012-11-19  
if(i!=我){} 写道
写过一个类,可以递归打印AppClassLoader加载的类的所有属性。有空贴上来

package com.cccode.object;

import java.lang.reflect.Field;
import java.util.Date;

/**
 * 
 * @author YDSoft-15
 * @author if(i!=我){} 保留署名权
 * 
 */
public class ObjectFields
{

	/**
	 * @param args
	 */
	public static void main(String[] args)
	{
		ObjectFields of = new ObjectFields();
		System.out.println(of.ObjectFields2String(new A()));
	}



	/**
	 * 
	 * @param obj
	 * @return 对象存在的属性值
	 */
	public String ObjectFields2String(Object obj)
	{
		return ObjectFields2String(new StringBuffer(), obj, 0);
	}



	/**
	 * 
	 * @param sb
	 * @param obj
	 * @param index
	 * @return 对象存在的属性值
	 */
	private String ObjectFields2String(StringBuffer sb, Object obj, int index)
	{
		if (obj == null)
		{
			return null;
		}
		Class<?> clas = obj.getClass();// 加载类
		sb.append(clas.getName());
		Field[] fields = clas.getDeclaredFields();// 获得对象属性集合
		sb.append(" {");
		printBlankSpace(sb, index + 1);
		for (int i = 0; i < fields.length; i++)
		{
			Field field = fields[i];
			String fieldName = field.getName();// 得到字段名

			sb.append(fieldName);
			sb.append("(");

			Class<?> fieldType = field.getType();// 得到字段类别
			sb.append(fieldType.getSimpleName());
			sb.append(") = ");

			try
			{
				field.setAccessible(true); // 设置强制访问
				Object fieldValue = field.get(obj);// 得到属性值
				if (fieldType.getClassLoader() != null// 不为BootstrapLoader(ExtClassLoader或AppClassLoader)
						&& !fieldType.isInterface() // fieldType不为接口
						&& fieldValue != null// 排除未实例化的声明
				)
				{
					ObjectFields2String(sb, fieldValue, index + 1);// 递归
				} else
				{
					sb.append(fieldValue);
				}
			} catch (IllegalArgumentException e)
			{
				e.printStackTrace();
			} catch (IllegalAccessException e)
			{
				e.printStackTrace();
			} finally
			{
				field.setAccessible(false);
			}
			if (i != fields.length - 1)
			{
				printBlankSpace(sb, index + 1);
			}
		}
		printBlankSpace(sb, index);
		sb.append("}");
		return sb.toString();
	}



	private void printBlankSpace(StringBuffer sb, int index)
	{
		sb.append("\n");
		for (int i = 0; i < index; i++)
		{
			sb.append("    ");
		}
	}

}

class A
{
	String a = "String of class A";
	B b = new B();
	long l = 123456l;
	Date d = new Date();
	StringBuffer sb = new StringBuffer();
	java.awt.Image img = null;



	public A()
	{
		sb.append("StringBuffer");
	}
}

class B
{
	String b = "String of class B";
	C c = new C();
}

class C
{
	String b = "String of class C";
}

0 请登录后投票
   发表时间:2012-11-19   最后修改:2012-11-19
if(i!=我){} 写道
freish 写道
ifox 写道
freish 写道
修改final类型的值才有意思

那就失去final存在的意义了。
撸主例子不错阿。我在Java编程思想上看来,不过那例子木有撸主的好。支持。。。

private本来就是不给外部直接访问的,这样搞不也失去private的意义了


这一般用于debug吧,不过总归是破坏封装的。

但是final修饰的变量就不通了,final变量放在栈中,跟普通变量根本无法互相转换。



恕我直言,这句话反映出你还没搞清楚堆、栈、java堆、java栈的区别以及用途
0 请登录后投票
   发表时间:2012-11-19  
freish 写道
if(i!=我){} 写道
freish 写道
ifox 写道
freish 写道
修改final类型的值才有意思

那就失去final存在的意义了。
撸主例子不错阿。我在Java编程思想上看来,不过那例子木有撸主的好。支持。。。

private本来就是不给外部直接访问的,这样搞不也失去private的意义了


这一般用于debug吧,不过总归是破坏封装的。

但是final修饰的变量就不通了,final变量放在栈中,跟普通变量根本无法互相转换。



恕我直言,这句话反映出你还没搞清楚堆、栈、java堆、java栈的区别以及用途


那烦请您老人家指点一二?
0 请登录后投票
论坛首页 编程语言技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics