Java advanced Programming-use reflection to force assignment to private fields __ programming

Source: Internet
Author: User

A problem has been encountered in today's project to call a class and get the property of the class to assign the value and then pass the class to the method as an argument.

In practice, it is found that the field properties in this class are private and cannot be assigned. There are no publicly available methods. And this class is packaged as a jar to me, I still can't change its code, so I want to manually write to it a set method is a problem. Later thought of using reflection to solve the problem, and then tried it, sure enough.

Reflection seems to have no distinction at all whether it is private, the private method of calling itself is acceptable, but the private method of invoking the parent class is not possible, and the reason is most likely because the Getdeclaredmethod method and the GetMethod method do not find the private method of the parent class. You can solve it by writing your own recursion, but it's not very good to do with reflection.

Let's look at the following code.

field[] fields = Obj.getdeclaredfields ();
			for (int i = 0; i < fields.length; i++) {
				fields[i].setaccessible (true);
				for (int j = 0; J < Args.length; J +) {
					String str = args[j];
					String strs[] = Str.split (",");
					if (Strs[0].equals (Fields[i].getname ())) {
						Fields[i].set (object, strs[1]);
						break;
					}}}
			
Fields[i].setaccessible (TRUE);
This remark is the key. Look at its surface. The English meaning is set accessible to: true. The programming meaning everybody guess also should know.

By viewing the JDK's source code:

public void Setaccessible (Boolean flag) throws SecurityException {
	SecurityManager sm = System.getsecuritymanager () ;
	if (SM!= null) sm.checkpermission (access_permission);
	SETACCESSIBLE0 (this, flag);
    
We can see that it manages permissions through SecurityManager, and we can enable Java.security.manager to determine if the program has permission to invoke Setaccessible (). By default, the kernel API and the code for the extended directory have this permission, and the Classpath or the application loaded by URLClassLoader does not have this permission. For example: When we execute the above program in this way, we will throw an exception
Java.security.AccessControlException:   Access   

In general, we can't manipulate the private fields of a class, but sometimes we have to be able to handle these fields, and then we need to call the Setaccessible () method on AccessibleObject to allow this access, And because the Field,method and constructor in the reflection class inherit from AccessibleObject, we can implement the operations on these fields by invoking the Setaccessible () method on these classes.


Let's take a look at what's going on with this access_permission:

Static final private Java.security.Permission access_permission =
	new Reflectpermission ("Suppressaccesschecks");

Find the JDK help document for a detailed explanation:


Public final class Reflectpermission
Extends Basicpermission Permission class for reflection operations. Reflectpermission is a specified permission, no action. The unique name currently defined is Suppressaccesschecks, which allows the elimination of standard Java language access checks that are performed by reflection objects at their point of use-for public, default (package) access, protected, private members.

The following table provides a brief description of the permissions allowed, and discusses the risk of granting code permissions.
Permission Target Name content allowed by permission the risk of allowing this permission
Suppressaccesschecks the ability to access fields and invoke methods in a class. Note that this includes not only public, but also protected and private fields and methods. the risk is that information that is usually unavailable (perhaps classified information) and methods may receive malicious code access.


Here's a little bit of it. Fields.setaccessible (True) is the actual effect of giving permissions access to Public,protected,private fields.

Isn't it cool? Of course, this method destroys the original Java Authority system. So less than a last resort, or less use, the efficiency of reflection is not so high drop.

Okay, so we're going to write a generic universal method that just passes the corresponding class, field name, and value, which we reflect and instantiate within the method. Then assign the corresponding field. Because I only used the fields. You can add the other stuff. Well. This is fun.

Package unit.sms;

public class Smss {
	private String DestID;
	Private String content;
	Private String Mobile;
	Public String Getdestid () {return
		destid;
	}
	Public String getcontent () {return
		content;
	}
	Public String Getmobile () {return
		mobile;
	}
	
}



Package com.sinoglobal.utils;

Import Java.lang.reflect.Field;

Import Com.jasson.mas.api.smsapi.Sms; /** * Reflective General-purpose tool class * * @author LZ * */public class Reflectionutils {/** * is used to assign values to the fields of the class, ignoring the Private,project modifier, ignoring the set/g Et method * @param c to reflect the class * @param the field name and value of the args class each field name and value are separated by commas * @return/@SuppressWarnings ("unchecked") public St
			atic Object getinstance (Class C, String ... args) {try {object = Class.forName (C.getname ()). Newinstance ();
			class<?> obj = Object.getclass ();
			field[] fields = Obj.getdeclaredfields ();
				for (int i = 0; i < fields.length; i++) {fields[i].setaccessible (true);
					for (int j = 0; J < Args.length; J +) {String str = args[j];
					String strs[] = Str.split (",");
						if (Strs[0].equals (Fields[i].getname ())) {Fields[i].set (object, strs[1]);
					Break
		}} return object;
		catch (Illegalaccessexception e) {e.printstacktrace (); catch (ClassNotFoundException e) {E.printstacKtrace ();
		catch (Instantiationexception e) {e.printstacktrace ();
	return null; public static void Main (string[] args) {object = getinstance (Smss.class, "destid,01201101", "mobile,158100224 "," content, test data.
");
         SMSS SMS = (SMSS) object;
         System.out.println ("SMS content:" + sms.getcontent ());
        system.out.println ("mobile number:" + sms.getmobile ());
	         SYSTEM.OUT.PRINTLN ("tail:" + sms.getdestid ());
 }
}

Console output:

SMS content: Test data.
Mobile phone Number: 15810022404
Tail: 01201101


Fields.setaccessible (True); maybe everyone will, but what we have to do is to know the reason why.

Look at the JDK source code, is undoubtedly the best way to learn and solve this method.


over~~~



Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.