65 lines
		
	
	
		
			2.3 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
		
		
			
		
	
	
			65 lines
		
	
	
		
			2.3 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
| 
								 | 
							
								---
							 | 
						||
| 
								 | 
							
								title: Reflection
							 | 
						||
| 
								 | 
							
								---
							 | 
						||
| 
								 | 
							
								# Reflection
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								In Java, reflection is a powerful tool that can be used to do *virtually* anything. This can be considered a 
							 | 
						||
| 
								 | 
							
								double-edged sword, as it is at times required, yet, it is often exploited and used innappropriately.
							 | 
						||
| 
								 | 
							
								It can, however, be particularly useful, if for whatever reason, a private method or private variable needs to be 
							 | 
						||
| 
								 | 
							
								called, a method needs to be hooked or replaced, and so on.
							 | 
						||
| 
								 | 
							
								Reasoning for doing this may vary, for example, a developer may not have access to the original source-code for a library
							 | 
						||
| 
								 | 
							
								that they are working with and may need to work around this constraint.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								# Application
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								## Assigning a private or protected variable
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								As previously mentioned, assigning a private or protected variable can be made possible with the use of reflection.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Consider the following class:
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								public class MyClass {
							 | 
						||
| 
								 | 
							
								  private String hiddenString = "Hello!";
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  public String getHiddenString() {
							 | 
						||
| 
								 | 
							
								    return this.hiddenString;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								As we can see, the `hiddenString` object is marked `private`, meaning we cannot directly access it.
							 | 
						||
| 
								 | 
							
								It is however, accessible through the `getHiddenString()` method.
							 | 
						||
| 
								 | 
							
								This won't allow us to change the value of the variable, we can, however, change it using reflection.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Consider the following code:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								...
							 | 
						||
| 
								 | 
							
								MyClass myObject = new MyClass();
							 | 
						||
| 
								 | 
							
								...
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								We have an instance of myObject at this point, so let's mark the private variable as accessible.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								// Create an instance of the object.
							 | 
						||
| 
								 | 
							
								MyClass myObject = new MyClass();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// Obtain a reference to the object's private member field, we know the name of the private variable is 
							 | 
						||
| 
								 | 
							
								// 'hiddenString'.
							 | 
						||
| 
								 | 
							
								Field hiddenStringField = myObject.getClass().getDeclaredField("hiddenString");
							 | 
						||
| 
								 | 
							
								// Mark the field as accessible, this effectively tells the JVM that the field is not private, thus
							 | 
						||
| 
								 | 
							
								// we can now access it.
							 | 
						||
| 
								 | 
							
								hiddenStringField.setAccessible(true);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// The Java compiler doesn't know we have marked the field as accessible. If we wish to set the value,
							 | 
						||
| 
								 | 
							
								// we must do so via reflection. We call the set() method on our field, supplying the target object 
							 | 
						||
| 
								 | 
							
								// (myObject) and the target value.
							 | 
						||
| 
								 | 
							
								// We have successfully set the value, using reflection!
							 | 
						||
| 
								 | 
							
								hiddenStringField.set(myObject, "Hello, World!");
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// This will print our newly assigned string, as we have assigned the private variable within our
							 | 
						||
| 
								 | 
							
								// myObject instance.
							 | 
						||
| 
								 | 
							
								System.out.println(myObject.getHiddenString());
							 | 
						||
| 
								 | 
							
								```
							 |