Blog Details

Java Reflection makes it possible to inspect

What is Reflection in Java?

Reflection is an API which is used to examine or modify the behavior of methods, classes, interfaces at runtime. A class has multiple components, such as methods, fields, and constructors. Java Reflection makes it possible to inspect classes, interfaces, fields and methods at runtime, without knowing the names of the classes, methods etc. at compile time.

How to use?

static Class<?> forName(String name):
returns the Class Object associated with the class or interface with the given String name.

Load class from hard drive to memory:

// Load from directory to memory [Most used]
Class person1 = Class.forName("com.liyiandxuegang.Person");

// Create the class and class the method of getClass()
Class person2 = new Person().getClass();

// Use the Person Class
Class Person3 = Person.class;

Constructor in Reflection

Person.java file

package com.liyiandxuegang;

public class Person {
	public String username = "Frank Wang";
        private long password =123456;
        private static double height = 1.70;
	private int age;
	
	// constructor
	public Person() {
		System.out.println("Constructor without parameters!");
	}
	
	// constructor
	public Person(String username) {
		this.username = username;
		System.out.println("Constructor with username: " + username);
	}
	
	// constructor 
	public Person(String username, int age) {
		this.username = username;
		this.age = age;
		System.out.println("Constructor with username: " + username + ", and age: " + age);
	}
	
	// Private Constructor 
	private Person(int age){
		this.age = age;
		System.out.println("Private!!! Constructor with age: " + age);
	}
	
	// method
        public void eat() {
                System.out.print("You are human, so you can eat());
        }

        // method 
        public void eat(String name, int age) {
                System.out.println("You can eat in public place, which you should have your name (" + name + "), and age (" + age + ")");
        }

        // method
        public Class[] eat(String name, int[] age) {
                for(int i = 0;i < age.length; i ++) {
                        System.out.println(age[i]);
                }
                return new Class[]{String.class};
        }

        // method 
        private void eat(InputStream inputStream) { 
                System.out.println("The parameter type for eat is inputStream"); 
        }
 
        // method
        public static void eat(int age) {
               System.out.println("Human can eat in " + age + " years old");
        }

        // main method
        public static void main(String[] args) {
                System.out.println("This is main function.");
        }
}

Test class

package com.liyiandxuegang;

import java.lang.reflect.Constructor;
import org.junit.Test;

public class PersonTest {
	@Test
	public void test1() throws Exception {
		// 1 Load class to memory
		Class clazz = Class.forName("com.liyiandxuegang.Person");
		// 2 Call the methods
		Constructor constructor = clazz.getConstructor();
		// 3 Create the class
		Person person = (Person) constructor.newInstance(null);
		// 4 Get field value
		System.out.println(person.username);
	}
}

Utilize different types of constructors, with different parameters.

  • String
Constructor constructor = clazz.getConstructor(String.class);
Person person = (Person) constructor.newInstance("Rock");
  • String & int
Constructor constructor = clazz.getConstructor(String.class, int.class);

Person person = (Person)constructor.newInstance("rock", 20);
  • Private Constructor
Constructor constructor = clazz.getDeclaredConstructor(int.class);
// force the constructor to be accessible
constructor.setAccessible(true);
// Then create the obj
Person person = (Person) constructor.newInstance(15);

Methods

Call different types of methods, such as return type, parameters, method type difference.

  • Call eat method, without passing parameters
// Load Class
Class clazz = Class.forName("com.liyiandxuegang.Person");
// Call method: first param: name of method, second param: parameters
Method method = clazz.getMethod("eat", null);
// Create class
Person person = new Person();
// invoke:Invokes the underlying method represented by this Method object, on the specified object with the specified parameters.
method.invoke(person, null);
  • Call eat method, passing String and int parameters in.
// get the method
Method method = clazz.getMethod("eat", String.class, int.class);
// invoke
method.invoke(person, "Liyi", 20);
  • Call eat method, passing String and int array
// get eat method
Method method = clazz.getMethod("eat", String.class, int[].class);
// invoke
method.invoke(person, "Liyi", new int[]{1,2,3});
  • Call private eat method
// Call private method
Method method = clazz.getDeclaredMethod("eat", InputStream.class);
// Set accessible 
method.setAccessible(true);
// invoke
method.invoke(person, new FileInputStream("/path-to-file"));
  • Call static eat method
// call the method
Method method = clazz.getMethod("eat", int.class);
// invoke: no instance, so it should be null
method.invoke(null, 20);
  • Call the main function
// Call the main method
Method method = clazz.getMethod("main", String[].class);
// Method 1
method.invoke(null, new Object[]{new String[] {"aa", "bb"}});
// method 2
mehtod.invoke(null, (Object[]) new String[]{"aa", "bb"});

Fields in Reflection

Get the field value through getField() method.

  • Get public field “username”, set the value.
// Load class
Class clazz = Class.forName("com.liyiandxuegang.Person");
// get field by name
Field field = clazz.getField("username");
// You can print the field type 
System.out.println(field.getType());
// Once you get the field, you need the get the value of the field in object person
Person person = new Person();
String username = (String) field.get(person);
System.out.println(username);
// Set the field value
field.set(person, "Liyi");
// Chec the result
System.out.println(field.get(person));

A Field provides information about, and dynamic access to, a single field of a class or an interface. The reflected field may be a class (static) field or an instance field.

  • Get the private Field value
// get declared filed
Field field = clazz.getDeclaredField("password");
// set field accessible 
field.setAccessible(true);
// get the value
Person person = new Person();
System.out.println(field.get(person));
  • Get the value of Static field
Field field = clazz.getDeclaredField("height");
field.setAccessible(true);
System.out.println(field.get(null));