Java Reflection Video Tutorial

Java Reflection Video TutorialWelcome to my Java Reflection Video Tutorial! I’ve been asked many times to cover Java Reflection lately and in this tutorial I’ll show you pretty much everything you can do with Java Refelection.

Many people are confused by reflection because they think it is a concept or technique. Java Reflection is an API and as soon as you know that it becomes easy. The Java Reflection API is used to manipulate classes¬†and everything in a class including fields, methods,¬†constructors, private data, etc. And, in this tutorial you’ll learn it all!

If you like videos like this, it helps if you tell Google

Sharing is great as well

Code from the Video

I used a class I previous used in my Abstract Factory Design Pattern tutorial. I provide it here with the changes made in the video, but you should also get the code on that page to get everything to work.

UFOEnemyShip.java

public class UFOEnemyShip extends EnemyShip{
	
	private String idcode = "100";
	
	private String getPrivate() { return "How did you get this"; }
	
	private String getOtherPrivate(int thisInt, String thatString){
		
		return "How did you get here " + thisInt + " " + thatString;
		
	}
	
	public UFOEnemyShip(int number, String randString){
		
		System.out.println("You sent: " + number + " " + randString);
		
	}
	
	// We define the type of ship we want to create
	// by stating we want to use the factory that 
	// makes enemy ships
	
	EnemyShipFactory shipFactory;
	
	// The enemy ship required parts list is sent to 
	// this method. They state that the enemy ship
	// must have a weapon and engine assigned. That 
	// object also states the specific parts needed
	// to make a regular UFO versus a Boss UFO
	
	public UFOEnemyShip(EnemyShipFactory shipFactory){
		
		this.shipFactory = shipFactory;
		
	}

	// EnemyShipBuilding calls this method to build a 
	// specific UFOEnemyShip
	
	void makeShip() {
		
		System.out.println("Making enemy ship " + getName());
		
		// The specific weapon & engine needed were passed in
		// shipFactory. We are assigning those specific part
		// objects to the UFOEnemyShip here
		
		weapon = shipFactory.addESGun();
		engine = shipFactory.addESEngine();
		
	}
	
}

TestingReflection.java

// The Java Reflection API is used to manipulate classes
// and everything in a class including fields, methods,
// constructors, private data, etc.

// Because using the Reflection API is most often Dynamic
// it can slow down a program because the JVM can't
// optimize the code.

// The Reflection API can't be used with applets because 
// of the added security applets require.

// Because this API allows you to do things like access
// private fields, methods, etc. it should be used 
// sparingly, or else potentially destroy the logic
// of a program

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

public class TestingReflection {
	
	public static void main(String[] args){
		
		// Getting the class Object for UFOEnemyShip
		// Everything in Java has a Class Object
		
		Class reflectClass = UFOEnemyShip.class;
		
		// Get the class name of an Object
		
		String className = reflectClass.getName();
		
		System.out.println(className + "\n");
		
		// Check modifiers of a class
		// isAbstract, isFinal, isInterface, isPrivate, isProtected,
		// isStatic, isStrict, isSynchronized, isVolatile
		
		int classModifiers = reflectClass.getModifiers();
		
		System.out.println(Modifier.isPublic(classModifiers) + "\n");
		
		// You can get a list of interfaces used by a class
		// Class[] interfaces = reflectClass.getInterfaces();
		
		// Get the super class for UFOEnemyShip
		
		Class classSuper = reflectClass.getSuperclass();
		
		System.out.println(classSuper.getName() + "\n");
		
		// Get the objects methods, return type and parameter type
		
		Method[] classMethods = reflectClass.getMethods();
		
		for(Method method : classMethods){
			
			// Get the method name
			
			System.out.println("Method Name: " + method.getName());
			
			// Check if a method is a getter or setter
			
			if(method.getName().startsWith("get")) {
				
				System.out.println("Getter Method");
				
			} else if(method.getName().startsWith("set")) {
				
				System.out.println("Setter Method");
				
			}
			
			// Get the methods return type
			
			System.out.println("Return Type: " + method.getReturnType());
			
			Class[] parameterType = method.getParameterTypes();
			
			// List parameters for a method
			
			System.out.println("Parameters");
			
			for(Class parameter : parameterType){
				
				System.out.println(parameter.getName());
				
			}
			
			System.out.println();
		
		}
		
		// How to access class constructors
		
		Constructor constructor = null;
		
		Object constructor2 = null;
		
		try {
			
			// If you know the parameters of the constructor you
			// want you do the following.
			
			// To return an array of constructors instead do this
			// Constructor[] constructors = reflectClass.getConstructors();
			
			// If the constructor receives a String you'd use the
			// parameter new Class[]{String.class}
			// For others use int.class, double.class, etc.
			
			constructor = reflectClass.getConstructor(new Class[]{EnemyShipFactory.class});
			
			// Call a constructor by passing parameters to create an object
			
			constructor2 = reflectClass.getConstructor(int.class, String.class).newInstance(12, "Random String");
		} 
		
		catch (NoSuchMethodException | SecurityException e) {
			// Exceptions thrown
			e.printStackTrace();
		} catch (InstantiationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		// Return the parameters for a constructor
		
		Class[] constructParameters = constructor.getParameterTypes();
		
		for(Class parameter : constructParameters){
			
			System.out.println(parameter.getName());
			
		}
		
		UFOEnemyShip newEnemyShip = null;
		
		EnemyShipFactory shipFactory = null;
		
		try {
			
			// Create a UFOEnemyShip object by calling newInstance
			
			newEnemyShip = (UFOEnemyShip) constructor.newInstance(shipFactory);
			
		} 
		
		catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
			
			e.printStackTrace();
			
		}
		
		// Now I can call methods in the UFOEnemyShip Object
		
		newEnemyShip.setName("Xt-1000");
		System.out.println("EnemyShip Name: " + newEnemyShip.getName());
		
		// Access private fields using reflection
		
		// Field stores info on a single field of a class
		
		Field privateStringName = null;
		
		try {
			
			// Create a UFOEnemyShip object
			
			UFOEnemyShip enemyshipPrivate = new UFOEnemyShip(shipFactory);
			
			// Define the private field you want to access
			// I can access any field with just its name dynamically
			
			privateStringName = UFOEnemyShip.class.getDeclaredField("idCode");
			
			// Shuts down security allowing you to access private fields
			
			privateStringName.setAccessible(true);
			
			// Get the value of a field and store it in a String
			
			String valueOfName = (String) privateStringName.get(enemyshipPrivate);
			
			System.out.println("EnemyShip Private Name: " + valueOfName);
			
			// Get access to a private method
			// getDeclaredMethod("methodName", methodParamters or null)
			
			// Since I provide the method name as a String I can run any method 
			// without needing to follow the normal convention methodName()
			
			String methodName = "getPrivate";
			
			Method privateMethod = UFOEnemyShip.class.getDeclaredMethod(methodName, null);
			
			// Shuts down security allowing you to access private methods
			
			privateMethod.setAccessible(true);
			
			// get the return value from the method
			
			String privateReturnVal = (String) privateMethod.invoke(enemyshipPrivate, null);
			
			System.out.println("EnemyShip Private Method: " + privateReturnVal);
			
			// Execute a method that has parameters
			
			// Define the parameters expected by the private method
			
			Class[] methodParameters = new Class[]{Integer.TYPE, String.class};
			
			// Provide the parameters above with values
			
			Object[] params = new Object[]{new Integer(10), new String("Random")};
			
			// Get the method by providing its name and a Class array with parameters
			
			privateMethod = UFOEnemyShip.class.getDeclaredMethod("getOtherPrivate", methodParameters);
			
			// Shuts down security allowing you to access private methods 
			
			privateMethod.setAccessible(true);
			
			// Execute the method and pass parameter values. The return value is stored
			
			privateReturnVal = (String) privateMethod.invoke(enemyshipPrivate, params);
			
			System.out.println("EnemyShip Other Private Method: " + privateReturnVal);
			
		} 	
		
		catch (NoSuchFieldException | SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 
		
		catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 
		
		catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 
		
		catch (NoSuchMethodException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 
		
		catch (InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
	
}

13 Responses to “Java Reflection Video Tutorial”

  1. Saleh says:

    This is Awesome.
    Everything works 100%,

    There is a minor thing I have just noticed for the first time. Which is the possibility of creating instance of object that take argument, it is possible for that argument to be a reference refer to null;


    //line 151
    EnemyShipFactory shipFactory = null;

    //line 157
    newEnemyShip = (UFOEnemyShip)constructor.newInstance(shipFactory);

    Thank you Derek.

    • admin says:

      Thank you very much :) I always wanted to solve all of the confusion around reflection. I covered questions I’ve received on reflection in my interpreter design pattern tutorial as well. I hope it helps.

      • Pat says:

        Derek,

        I went through a few of your videos. What you have here is a treasure trove. Your style is very unique. I have to admit though these may not be for beginners. But if one has a basic understanding of the subjects, the stuff you have will take him/her to the next higher level in no time.

        Thanks for the enormous effort you have put in.

        • Derek Banas says:

          You’re very welcome :) Thank you for the kind compliments. Yes, I don’t aim to have mass appeal. I look to instead either cover topics that most people ignore, or present information in completely different ways. I’m glad you like them

  2. Diep Dao says:

    Hey Derek

    You have a typo in your code.

    line 3 in UFOEnemyShip class you have idcode ‘c’ in lower case but in your TestingReflection you use “idCode” upper case just thought i mention in case anyone wonders why it wasn’t working. other then that. Thanks for the lesson.

  3. Rohit says:

    Thanks Derek,
    U explained reflection in a very easy way . My confusion about reflection is resolved now .
    :-)

  4. Ankur says:

    Thanks for the lesson, this is the first time i understood it. I have one doubt could you please let me know the practical use case of reflection.

    Thanks in advance

    • Derek Banas says:

      You’re very welcome :) I’ve found reflection is very good for testing code. In the research world it is sometimes very beneficial to take advantage of its dynamic capabilities. You can also use it to by pass private, protected, etc. Again this is done for analyzing a class rather then for use in real world code.

  5. mpatalberta says:

    Is it not the case that line 149 and 151 sort of self defeating?
    You have explicitly typed the names of the classes. I would think the whole point of the excersize is to not know the absolute names of any classes. All names need to be got at runtime.

  6. mpatalberta says:

    With looking at your example I can build the following code that DOES NOT need have fore knowledge of the actual classnames.

    package com.pat.example2;

    import java.lang.reflect.Field;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;

    public class TestReflection2 {

    public static void main(String[] args) {
    // TODO Auto-generated method stub
    System.out.println(“TestReflection2″);

    Class myruntimeclass=null;
    try {

    myruntimeclass= Class.forName(“com.pat.example2.MyRunTimeClass”);

    } catch (ClassNotFoundException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }

    // create the object with the default constructor

    Object myruntimeclassobj = null;
    Field f=null;
    try {
    myruntimeclassobj = myruntimeclass.newInstance();
    // object constructed now find a set method with parameter of a string
    Class c;
    c = myruntimeclassobj.getClass();
    String s1;

    s1 = doSet(c,myruntimeclassobj,”hellopatty”);
    System.out.println(“afterset>”+s1+”"+s1+”"+s1+”"+s1+”"+s1+”<");

    } catch (IllegalArgumentException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    } catch (SecurityException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    } catch (InstantiationException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    } catch (IllegalAccessException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    } catch (InvocationTargetException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    } catch (NoSuchMethodException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    // object constructed now find a set method with parameter of a string

    System.out.println("exiting");
    }

    public static String doGet(Class c, Object obj) {
    String sRes =null;
    Method[] m;
    m = c.getMethods();
    for(int i = 0;i<m.length;i++)
    {

    if(m[i].getName().matches("Get"))
    {
    try {
    sRes = (String)m[i].invoke(obj);
    } catch (IllegalArgumentException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    } catch (IllegalAccessException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    } catch (InvocationTargetException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    }

    }
    return sRes;
    }

    public static String doSet(Class c,Object obj ,String s)
    {
    String sRes =null;
    Method[] m;
    m = c.getMethods();
    for(int i = 0;i<m.length;i++)
    {

    if(m[i].getName().matches("Set"))
    {
    try {
    sRes = (String)m[i].invoke(obj, "hellopatty");
    } catch (IllegalArgumentException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    } catch (IllegalAccessException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    } catch (InvocationTargetException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    }

    }

    return sRes;
    }

    }
    ————-
    package com.pat.example2;

    public class MyRunTimeClass {

    public MyRunTimeClass()
    {
    System.out.println("ctor:no values passed");
    }

    public MyRunTimeClass(String s)
    {
    System.out.println("ctor with string");
    snam = s;

    }
    private String snam="NOTSET";
    public String Set(String snam)
    {
    System.out.println("stringin"+snam);
    this.snam = snam;
    return this.snam;
    }

    public String Get()
    {
    System.out.println("stringout"+snam);
    return this.snam;
    }
    }

    • mpatalberta says:

      The main routine came over wrong on the paste:
      — try againg —package com.pat.example2;

      import java.lang.reflect.Field;
      import java.lang.reflect.InvocationTargetException;
      import java.lang.reflect.Method;

      public class TestReflection2 {

      public static void main(String[] args) {
      // TODO Auto-generated method stub
      System.out.println(“TestReflection2″);

      Class myruntimeclass=null;
      try {

      myruntimeclass= Class.forName(“com.pat.example2.MyRunTimeClass”);

      } catch (ClassNotFoundException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
      }

      // create the object with the default constructor

      Object myruntimeclassobj = null;
      Field f=null;
      try {
      myruntimeclassobj = myruntimeclass.newInstance();
      // object constructed now find a set method with parameter of a string
      Class c;
      c = myruntimeclassobj.getClass();
      String s1;

      s1 = doSet(c,myruntimeclassobj,”hellopatty”);
      System.out.println(“afterset>”+s1+”"+s1+”"+s1+”"+s1+”"+s1+”<");

      } catch (IllegalArgumentException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
      } catch (SecurityException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
      } catch (InstantiationException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
      } catch (IllegalAccessException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
      } catch (InvocationTargetException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
      } catch (NoSuchMethodException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
      }
      // object constructed now find a set method with parameter of a string

      System.out.println("exiting");
      }

      public static String doGet(Class c, Object obj) {
      String sRes =null;
      Method[] m;
      m = c.getMethods();
      for(int i = 0;i<m.length;i++)
      {

      if(m[i].getName().matches("Get"))
      {
      try {
      sRes = (String)m[i].invoke(obj);
      } catch (IllegalArgumentException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
      } catch (IllegalAccessException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
      } catch (InvocationTargetException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
      }
      }

      }
      return sRes;
      }

      public static String doSet(Class c,Object obj ,String s)
      {
      String sRes =null;
      Method[] m;
      m = c.getMethods();
      for(int i = 0;i<m.length;i++)
      {

      if(m[i].getName().matches("Set"))
      {
      try {
      sRes = (String)m[i].invoke(obj, "hellopatty");
      } catch (IllegalArgumentException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
      } catch (IllegalAccessException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
      } catch (InvocationTargetException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
      }
      }

      }

      return sRes;
      }

      }

  7. mpatalberta says:

    Still the code is going over incorrectly. Regardless I use the invoke method and can design a runtime call to access a class for a bluetooth rfcomm interface on android.

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title="" rel=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Google+