Reflection – A Quick WrapUp :)

ok, I talked about reflection in couple posts specifically and indirectly I referred to them in a few others, but just to wrap up, Reflections are very useful and very powerful tool that every developers needed them in their toolbox. now, when you read and practice what I have explained so nfar, you can see the connections between that package with others and also you can see its footprints everywhere in Java frameworks and other utilities.

Reflection generally can be used to retrive the information about every Class Type.

you can load and reload Class definition into memory and you can trace everything inside classes, even inner classes (as I explained in my examples in Reflections)

Also Reflection will be used in Annotation processing behind the scene by JDK.

Also for Serialization, Java itself uses reflection to get the SerialVerUID fields to validate the classes.

to make that easy, I can just tell that wherever you saw something might use Class Type, you can now think of Reflection.

Advertisements

Serialization (Part 3) – Customized serialization and Transient Keyword

in some cases, we prefer to exclude a/ some member(s) of a class from being serialized. the way to do that is to use transient keyword in the declaration of that field. below is an example:

Why?

to decrease the space in the serialization process

Customization of serialization

make sure the Type that implement Serializable interface and you want it to be serialized, implement one or both of these two methods:


private void writeObject(ObjectOutputSteam out) throws IOException

private void readObject(ObjectInputSteam in) throws IOException, ClassNotFoundException

we can make them private since these methods could only be used by Serialization system through Reflections, so we don’t want anyone else outside of this scenario call them.

so in my example below,  I have added a new Char field into my type along with implementing these new methods into my User type and then re-ran the same test file that we have before ….


import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

/**
*
* @author Unknown_
*/
public class User implements Serializable {

private static final long serialVersionUID = -607661653725142657L;

private String username, password;
private int securityCode;
private char permissionCode;

public User() {
}

public User(String username, String password) {
this.username = username;
this.password = password;

}

public void updateUsername(String username) {
System.out.println("username's changed to ... " + username);
this.username = username;
}

public void setSecurityCode(int securityCode) {
this.securityCode = securityCode;
}

@Override
public String toString() {
return "Name: " + this.username + " - passwd: " + this.password + " - SecCode: " + this.securityCode + " permissionCode: " + permissionCode;
}

public void showcontent() {
System.out.println("" + this.toString());
}

public void setPermissionCode(char permissionCode) {
this.permissionCode = permissionCode;
}



/**
* customizing the write object process
* @param out
* @throws IOException
*/
private void writeObject(ObjectOutputStream out) throws IOException{

out.defaultWriteObject();
}

private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException{

ObjectInputStream.GetField readFields = in.readFields();
permissionCode = readFields.get("permissionCode", 'u'); // 'u' as undefined, instead of default compiler '\0' NULL
username = (String) readFields.get("username", null);
password = (String) readFields.get("password", null);
securityCode = readFields.get("securityCode", -1);
}

}

and the test scenario class:


 

import com.navid.practice.serialization.banking.User;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
* we have a bank account and we want to save and then reload that into the
* object instance to see how serialization will work.
*
* @author Unknown_
*/
public class TestScenario1 {

/**
* saving objects into a file that is mentioned in the filename argument.
*
* @param u
* @param filename
*/
public static void saveUser(User u, String filename) {

try (ObjectOutputStream out = new ObjectOutputStream(Files.newOutputStream(Paths.get(filename),StandardOpenOption.APPEND))) {

out.writeObject(u);

} catch (IOException ex) {
Logger.getLogger(TestScenario1.class.getName()).log(Level.SEVERE, null, ex);
} catch (Exception ex) {
}
}

/**
* reading the object from the file mentioned as filename.
*
* @param filename
* @return
*/
public static User reloadUser(String filename) {

User u = null;
try (ObjectInputStream in = new ObjectInputStream(Files.newInputStream(Paths.get(filename), StandardOpenOption.READ))) {
u = (User) in.readObject();

} catch (IOException ex) {
Logger.getLogger(TestScenario1.class.getName()).log(Level.SEVERE, null, ex);
} catch (ClassNotFoundException ex) {
Logger.getLogger(TestScenario1.class.getName()).log(Level.SEVERE, null, ex);
}
return u;
}

public static void main(String[] args) {

User u = new User("MyOldUserName", "myPasswd1");
u.setSecurityCode(1200);
u.showcontent();
u.updateUsername("myNewUsername");
u.showcontent();

System.out.println("Saving Object ... ");
saveUser(u, "myAccounts.dat");
System.out.println("Reloading Object ... ");
reloadUser("myAccounts.dat").showcontent();

}

}

output will be something like this …

run:
Name: MyOldUserName - passwd: myPasswd1 - SecCode: 1200 permissionCode: 
username's changed to ... myNewUsername
Name: myNewUsername - passwd: myPasswd1 - SecCode: 1200 permissionCode: 
Saving Object ... 
Reloading Object ... 
Name: myNewUsername - passwd: myPasswd1 - SecCode: 1200 permissionCode: u
BUILD SUCCESSFUL (total time: 0 seconds)

since we didn’t set the default value for that recently added char in out readObject method we defined a default value. so whenever serialization system couldn’t find that field’s value in file, returned us the default value of that.

 

Serialization (Part 1) – Basics

Serialization means make the object transferable :

  1. between ip addresses over a network
  2. between memory addresses
  3. into a file
  4. into a database systems

Serializable interface in java provides serialization capabilities to any object type which is implement that and all of its content instances (all of its memebers). Object graph

Serializable interface is an marker interface = does’t hvae any menthod.


import java.io.Serializable;

/**
*
* @author Unknown_
*/
public class User implements Serializable {

private String username, password;

public User() {
}

public User(String username, String password) {
this.username = username;
this.password = password;
}

public void updateUsername(String username) {
System.out.println("username's changed to ... " + username);
this.username = username;
}

@Override
public String toString() {
return "Name: " + this.username + " - passwd: " + this.password;
}

public void showcontent() {
System.out.println("" + this.toString());
}

}

so far we have made this class serializable, but how we can save and persist and also reload it from our file system?

  • ObjectInputStream
  • ObjectOutputStream

by using above calsses you can just easily drop the serilized object into the input stream or fetch them from output stream without being worried about the rest of the process and the result will be provided. Check below examples:


import com.navid.practice.serialization.banking.User;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
* we have a bank account and we want to save and then reload that into the
* object instance to see how serialization will work.
*
* @author Unknown_
*/
public class TestScenario1 {

/**
* saving objects into a file that is mentioned in the filename argument.
*
* @param ba
* @param filename
*/
public static void saveUser(User u, String filename) {

try (ObjectOutputStream out = new ObjectOutputStream(Files.newOutputStream(Paths.get(filename), StandardOpenOption.CREATE))) {

out.writeObject(u);

} catch (IOException ex) {
Logger.getLogger(TestScenario1.class.getName()).log(Level.SEVERE, null, ex);
} catch (Exception ex) {
}
}

/**
* reading the object from the file mentioned as filename.
*
* @param filename
* @return
*/
public static User reloadUser(String filename) {

User u = null;
try (ObjectInputStream in = new ObjectInputStream(Files.newInputStream(Paths.get(filename), StandardOpenOption.READ))) {
u = (User) in.readObject();

} catch (IOException ex) {
Logger.getLogger(TestScenario1.class.getName()).log(Level.SEVERE, null, ex);
} catch (ClassNotFoundException ex) {
Logger.getLogger(TestScenario1.class.getName()).log(Level.SEVERE, null, ex);
}
return u;
}

public static void main(String[] args) {

User u = new User("MyOldUserName", "myPasswd1");
u.showcontent();
u.updateUsername("myNewUsername");
u.showcontent();

System.out.println("Saving Object ... ");
saveUser(u, "myAccounts.dat");
System.out.println("Reloading Object ... ");
reloadUser("myAccounts.dat").showcontent();

}

}

output will be something like this …

run:
Name: MyOldUserName - passwd: myPasswd1
username's changed to ... myNewUsername
Name: myNewUsername - passwd: myPasswd1
Saving Object ... 
Reloading Object ... 
Name: myNewUsername - passwd: myPasswd1
BUILD SUCCESSFUL (total time: 0 seconds)

Reflection Example Part 6

in the previous example, the application will work however it’s tied to target object types and worker thread’s constructor. we can make it loosely coupled in a way that releases the application from these constraints and makes that flexible to decide later in running time about what Thread worker types might come in and also we can add different workerThread in future without changing the main logic. also, another good tip is reflection is Slower than regularly compiled programming, we need to decrease the use of reflections as much as possible. below is the solution:

Interface TaskWorker:


package com.navid.practice.reflection.newsrc.worker2;

/**
* by using this class
* 1. we can have different worker as much as we want
* 2. the worker's code doesn't need to have special constructor. -- more loosely coupled.
*
* @author Unknown_
*/
interface Taskworker extends Runnable{

/**
* do the actual task, so any thread could implement this.
* implement the threading triggering process.
* @param operation
* @param amount
*/
public void doWork();

/**
* setting a target for our worker thread implemenation. this target object will be an object reference to
* a BankAccount object or anything that is extended the bankAccount object.
* @param target
*/
public void setTarget(Object target);

}

then updating worker thread

AccountWorkerImproved


package com.navid.practice.reflection.newsrc.worker2;

import com.navid.practice.reflection.legacy.beans.BankAccount;
import com.navid.practice.reflection.legacy.beans.HighVolumeAccount;

/**
*
* @author Unknown_
*/
public class AccountWorkerImproved implements Taskworker {

private BankAccount bankAccount;

@Override
public void doWork() {

//decied if that's the BankAccount normal or HighVolume one, then trigger its thread.
Thread thread  = new Thread( HighVolumeAccount.class.isInstance(bankAccount)? (HighVolumeAccount)this.bankAccount : this);

thread.start();
}

@Override
public void setTarget(Object target) {

if(BankAccount.class.isInstance(target)){
this.bankAccount = (BankAccount) target;
}else
throw new IllegalArgumentException("Target object is not matching bankAccount class");
}

@Override
public void run() {
System.out.println("WorkerThreadImproved - start processing the account deposits ... ");
}

}

Executing the Scenario


package com.navid.practice.reflection.newsrc.worker2;

import com.navid.practice.reflection.legacy.beans.BankAccount;
import com.navid.practice.reflection.legacy.beans.HighVolumeAccount;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
*
* @author Unknown_
*/
public class ReflectionPractice2 {

public void startWork(String workerTypeName, Object workerTarget) {

try {

// providing the worker thread information.
Class<?> workerType = Class.forName(workerTypeName);

// since we don't have any additional constructor beside our worker thread default one, so we don;t need to get the target types
// and call it. insteda we cna use this ...
Taskworker taskWorker = (Taskworker) workerType.newInstance();

// the the rest is like reglar programming
taskWorker.setTarget(workerTarget);
taskWorker.doWork();

} catch (ClassNotFoundException | SecurityException | IllegalArgumentException | InstantiationException | IllegalAccessException ex) {
Logger.getLogger(ReflectionPractice2.class.getName()).log(Level.SEVERE, null, ex);
}

}

public static void main(String[] args) {

BankAccount bankAccount = new BankAccount("1234", 100);

new ReflectionPractice2().startWork("com.navid.practice.reflection.newsrc.worker2.AccountWorkerImproved", bankAccount);

HighVolumeAccount highVolumeAccount = new HighVolumeAccount();

new ReflectionPractice2().startWork("com.navid.practice.reflection.newsrc.worker2.AccountWorkerImproved", highVolumeAccount);
}

}

the output of our test is exactly the same as before, but we decrease the use of reflection and also make our design clearer and loosely coupled.

run:
BankAccount Object constructor 2
BankAccount Object constructor 1 
WorkerThreadImproved - start processing the account deposits ... 
HighVolumeAccount process all Daily Deposits.
HighVolumeAccount process all Daily Withrwals.
BUILD SUCCESSFUL (total time: 0 seconds)

Reflection Field, Method (Part 3)

Each class instances might have its own methods, fields, and constructors, so Class class should address them. in Java reflection, there are separate Types to refer to this need. we have below types which refer to these types in details.

  1. Method
  2. Constructor
  3. Field

below is the same example code that we have written from Part 1 and part 2, but only this time we are going to expand that to cover our concepts.


package com.navid.training.classtester;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
*
* @author Unknown_
*/
public class ClassTesting {

private static class MyInnerClass {

private String name = "";
int code = 0;

public MyInnerClass(int code) {
this.code = code;
}

}

/**
* just extending this class to express the Class related methods leverage.
*/
private static final class MySubClass extends MyInnerClass implements Runnable {

private String subClassName = "";

public MySubClass(int code) {
super(code);
}

@Override
public void run() {
System.out.println("triggering and runnin this subclass as a thread.");
}
private void method1(){
System.out.println("nothing");
}

public void method2(){
System.out.println("nothing 2");
}

}

public void doWork(Object obj) {
Class<?> c = obj.getClass();
showClassInfo(c);
}

/**
* extracting and showing the class information.
*
* @param inputClass
*/
public void showClassInfo(Class<?> inputClass) {
System.out.println("SimpleName: " + inputClass.getSimpleName());
System.out.println("CanonicalName: " + inputClass.getCanonicalName());
System.out.println("Name: " + inputClass.getName());
System.out.println("TypeName: " + inputClass.getTypeName());
}

public static void showModifier(int modifier) {
if (Modifier.isFinal(modifier)) {
System.out.println("its modifier is FINAL - using isFinal()");
}

if (Modifier.isPrivate(modifier)) {
System.out.println("its modifier is PRIVATE");
}
if (Modifier.isProtected(modifier)) {
System.out.println("it's PROTECTED.");
}
if (Modifier.isPublic(modifier)) {
System.out.println("it's public.");
}
if (Modifier.isAbstract(modifier)) {
System.out.println("it's abstract.");
}
if (Modifier.isInterface(modifier)) {
System.out.println("it's interface.");
}
if (Modifier.isNative(modifier)) {
System.out.println("it's NATIVE.");
}
if (Modifier.isStatic(modifier)) {
System.out.println("it's static.");
}
if (Modifier.isStrict(modifier)) {
System.out.println("it's STRICT.");
}
if (Modifier.isSynchronized(modifier)) {
System.out.println("it's Synchronized.");
}
if (Modifier.isVolatile(modifier)) {
System.out.println("it's Volitile.");
}
}

public static void main(String[] args) {

try {

//working with Class methods BASICS.
System.out.println("working with BASICS of CLASS methods.");
MyInnerClass innerClass = new MyInnerClass(12);
// Testing Innerclass instance
ClassTesting tester = new ClassTesting();
tester.doWork(innerClass);

//another test with a JDK Collection util package class
Map m = new HashMap<String, String>();
tester.doWork(m);
// Another test --
System.out.println("Using: Class.forName() -- it needs name and not choronical name!");
System.out.println("This may through \" java.lang.ClassNotFoundException\" - so to call inner classes you need something liek this "
+ "com.navid.training.classtester.ClassTesting$MyInnerClass");
Class<?> c = Class.forName("com.navid.training.classtester.ClassTesting$MyInnerClass");
tester.showClassInfo(c);

//Another test using class operator
System.out.println("Using: type literals for every Object - e.g: MyClass.class");
Class<?> c2 = MyInnerClass.class;
tester.showClassInfo(c2);

System.out.println("----------PART 2----------");
// Part 2: create an isntance of MySubClass
System.out.println(" ------\n working on SUBCLASSES and Modifier in Class ...");
MySubClass sub = new MySubClass(20);
//its name
Class<?> itself = sub.getClass();
System.out.println("Class itself: " + itself.getName());
//its parent
Class<?> parent = itself.getSuperclass();
System.out.println("SupserClassName: " + parent.getName());
//its interfaces
Class<?>[] interfaces = itself.getInterfaces();
for (Class cc : interfaces) {
System.out.println("Interfaces: " + cc.getName());
}

int modifier = itself.getModifiers();
if (Modifier.isFinal(modifier)) {
System.out.println("its modifier is FINAL - using isFinal()");
}
if ((modifier & Modifier.FINAL) > 0) {
System.out.println("its modifier is FINAL - using BITWISE operation");
}
if (Modifier.isPrivate(modifier)) {
System.out.println("its modifier is PRIVATE");
}
if (Modifier.isProtected(modifier)) {
System.out.println("it's PROTECTED.");
}

System.out.println("----------PART 3 ----------");
// Part 3 : working with Methods and Fields in CLASS
System.out.println("Working with Methods and Fields by Class methods...");

System.out.println("Added one field to subclass and also updating modifier in parent inner class ...");

System.out.println("--------  getDeclaredFields()------------");
Field[] declaredFields_child = sub.getClass().getDeclaredFields();
for (Field f : declaredFields_child) {
System.out.println("DeclaredField: " + f.getName());
showModifier(f.getModifiers());
}
System.out.println("-----------getFields()---------");
// if fields are public won't be shown here.
Field[] fields_child = sub.getClass().getFields();
for (Field f : fields_child) {
System.out.println("Field: " + f.getName());
showModifier(f.getModifiers());
}

System.out.println("--------  getDeclaredMethods()------------");
Method[] declaredMethods = sub.getClass().getDeclaredMethods();
for (Method method : declaredMethods) {
System.out.println("DeclaredField: " + method.toGenericString());
showModifier(method.getModifiers());
}
System.out.println("--------  getMethods()------------");
Method[] methods = sub.getClass().getMethods();
for (Method method : methods) {
System.out.println("Field: " + method.toGenericString());
showModifier(method.getModifiers());
System.out.println("##########");
}

} catch (ClassNotFoundException ex) {
Logger.getLogger(ClassTesting.class.getName()).log(Level.SEVERE, null, ex);
}
}

}

and its output will be something like …

----------PART 3 ----------
Working with Methods and Fields by Class methods...
Added one field to subclass and also updating modifier in parent inner class ...
--------  getDeclaredFields()------------
DeclaredField: subClassName
its modifier is PRIVATE
-----------getFields()---------
--------  getDeclaredMethods()------------
DeclaredField: public void com.navid.training.classtester.ClassTesting$MySubClass.run()
it's public.
DeclaredField: public void com.navid.training.classtester.ClassTesting$MySubClass.method2()
it's public.
DeclaredField: private void com.navid.training.classtester.ClassTesting$MySubClass.method1()
its modifier is PRIVATE
--------  getMethods()------------
Field: public void com.navid.training.classtester.ClassTesting$MySubClass.run()
it's public.
##########
Field: public void com.navid.training.classtester.ClassTesting$MySubClass.method2()
it's public.
##########
Field: public final void java.lang.Object.wait() throws java.lang.InterruptedException
its modifier is FINAL - using isFinal()
it's public.
##########
Field: public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
its modifier is FINAL - using isFinal()
it's public.
##########
Field: public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
its modifier is FINAL - using isFinal()
it's public.
it's NATIVE.
##########
Field: public boolean java.lang.Object.equals(java.lang.Object)
it's public.
##########
Field: public java.lang.String java.lang.Object.toString()
it's public.
##########
Field: public native int java.lang.Object.hashCode()
it's public.
it's NATIVE.
##########
Field: public final native java.lang.Class<?> java.lang.Object.getClass()
its modifier is FINAL - using isFinal()
it's public.
it's NATIVE.
##########
Field: public final native void java.lang.Object.notify()
its modifier is FINAL - using isFinal()
it's public.
it's NATIVE.
##########
Field: public final native void java.lang.Object.notifyAll()
its modifier is FINAL - using isFinal()
it's public.
it's NATIVE.
##########
BUILD SUCCESSFUL (total time: 0 seconds)

in Above code, and its ouput we tried to explain the differences between getDeclaredXXX() and getXXX().

obj.getClass().getDeclaredXXX() – is able to explore and mention all the methods that are not even public, for example we hvae method1 and method2 and only method2 is public, as you can see, getDeclaredMethods() could capture both of them, although getMethods() could only see the public methods.

Hint:

you may notice that in the output, getDelcaredMethods() was able to returning all the public and proivate, protected, etc, however we might not need all of them which came from their parent classes or even from Object class such as: hashCode(), wait(), wait(…), equals(), etc.

to prevent that to trace the hirarchial to all the parents and check all of their methods, you can easily check and make sure we can have all the class itself methods, by below snippet code.


/**
* show only methods of the class
*
* @param c2
*/
public static void showMethodsOfClassObject(Class<?> c2) {

Method[] declaredMethods = c2.getDeclaredMethods();
for (Method method : declaredMethods) {

if (method.getDeclaringClass().equals(c2)) {
System.out.println("Method of this class is: " + method);
}
}
}

output will be something like this:

--------Now only Methods of this class -------
Method of this class is: public void com.navid.training.classtester.ClassTesting$MySubClass.run()
Method of this class is: public void com.navid.training.classtester.ClassTesting$MySubClass.method2()
Method of this class is: private void com.navid.training.classtester.ClassTesting$MySubClass.method1()

 

 

Reflection Modifiers (Part 2)

by using Reflection API, we can actually see the content of the type so we can find out more information about its modifiers and its parent class in case if that was extended from a class or we can find out if that type is actually implemented an interface.

below is the same example I wrote in Part 1 Reflection, but this time we are extending an inner class from our inner class and then try to investigate further on that subclass instance. (I’ve highlighted the updated parts related to modifiers.)

Tip#1: you can see there are two ways to deal with modifiers, you can use BitWise operation or just using Modifier Class methods to verify and investigate on object instance details.


/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.navid.training.classtester;

import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
*
* @author Unknown_
*/
public class ClassTesting {

private static class MyInnerClass {

String name = "";
int code = 0;

public MyInnerClass(int code) {
this.code = code;
}

}

/**
* just extending this class to express the Class related methods leverage.
*/
private static final class MySubClass extends MyInnerClass implements Runnable {

public MySubClass(int code) {
super(code);
}

@Override
public void run() {
System.out.println("triggering and runnin this subclass as a thread.");
}

}

public void doWork(Object obj) {
Class<?> c = obj.getClass();
showClassInfo(c);
}

/**
* extracting and showing the class information.
*
* @param inputClass
*/
public void showClassInfo(Class<?> inputClass) {
System.out.println("SimpleName: " + inputClass.getSimpleName());
System.out.println("CanonicalName: " + inputClass.getCanonicalName());
System.out.println("Name: " + inputClass.getName());
System.out.println("TypeName: " + inputClass.getTypeName());
}

public static void main(String[] args) {

try {

//working with Class methods BASICS.
System.out.println("working with BASICS of CLASS methods.");
MyInnerClass innerClass = new MyInnerClass(12);
// Testing Innerclass instance
ClassTesting tester = new ClassTesting();
tester.doWork(innerClass);

//another test with a JDK Collection util package class
Map m = new HashMap<String, String>();
tester.doWork(m);
// Another test --
System.out.println("Using: Class.forName() -- it needs name and not choronical name!");
System.out.println("This may through \" java.lang.ClassNotFoundException\" - so to call inner classes you need something liek this "
+ "com.navid.training.classtester.ClassTesting$MyInnerClass");
Class<?> c = Class.forName("com.navid.training.classtester.ClassTesting$MyInnerClass");
tester.showClassInfo(c);

//Another test using class operator
System.out.println("Using: type literals for every Object - e.g: MyClass.class");
Class<?> c2 = MyInnerClass.class;
tester.showClassInfo(c2);

// create an isntance of MySubClass
System.out.println(" ------\n working on SUBCLASSES and Modifier in Class ...");
MySubClass sub = new MySubClass(20);
//its name
Class<?> itself = sub.getClass();
System.out.println("Class itself: " + itself.getName());
//its parent
Class<?> parent = itself.getSuperclass();
System.out.println("SupserClassName: " + parent.getName());
//its interfaces
Class<?>[] interfaces = itself.getInterfaces();
for (Class cc : interfaces) {
System.out.println("Interfaces: " + cc.getName());
}

int modifier = itself.getModifiers();
if (Modifier.isFinal(modifier)) {
System.out.println("its modifier is FINAL - using isFinal()");
}
if ((modifier & Modifier.FINAL) > 0) {
System.out.println("its modifier is FINAL - using BITWISE operation");
}
if (Modifier.isPrivate(modifier)) {
System.out.println("its modifier is PRIVATE");
}
if (Modifier.isProtected(modifier)) {
System.out.println("it's PROTECTED.");
}

// working with Methods and Fields in CLASS
System.out.println("Working with Methods and Fields by Class methods...");



} catch (ClassNotFoundException ex) {
Logger.getLogger(ClassTesting.class.getName()).log(Level.SEVERE, null, ex);
}
}

}

output is like this:

run:
SimpleName: MyInnerClass
CanonicalName: com.navid.training.classtester.ClassTesting.MyInnerClass
Name: com.navid.training.classtester.ClassTesting$MyInnerClass
TypeName: com.navid.training.classtester.ClassTesting$MyInnerClass
SimpleName: HashMap
CanonicalName: java.util.HashMap
Name: java.util.HashMap
TypeName: java.util.HashMap
Using: Class.forName() -- it needs name and not choronical name!
This may through " java.lang.ClassNotFoundException" - so to call inner classes you need something liek this com.navid.training.classtester.ClassTesting$MyInnerClass
SimpleName: MyInnerClass
CanonicalName: com.navid.training.classtester.ClassTesting.MyInnerClass
Name: com.navid.training.classtester.ClassTesting$MyInnerClass
TypeName: com.navid.training.classtester.ClassTesting$MyInnerClass
Using: type literals for every Object - e.g: MyClass.class
SimpleName: MyInnerClass
CanonicalName: com.navid.training.classtester.ClassTesting.MyInnerClass
Name: com.navid.training.classtester.ClassTesting$MyInnerClass
TypeName: com.navid.training.classtester.ClassTesting$MyInnerClass
 ------
 working on Subclasses
Class itself: com.navid.training.classtester.ClassTesting$MySubClass
SupserClassName: com.navid.training.classtester.ClassTesting$MyInnerClass
Interfaces: java.lang.Runnable
its modifier is FINAL - using isFinal()
its modifier is FINAL - using BITWISE operation
its modifier is PRIVATE
BUILD SUCCESSFUL (total time: 0 seconds)

Reflection Fundamentals (Part 1)

Reflection is an API that provides Type related operations in the Java language. it’s part of JDK and we can group its task into 2 major categories:

  1. Type Checking at RunTime
  2. Getting Access and Executing members and methods at Runtime.

Note: there are times that we don’t know the specific type of objects that we are using. in that case, Reflection is that API that could enable us to verify that.

there is a Class class type that every object instances ; regardless of their types, are referring to it. depending on what type they might have, they have reference to the exact same Class class instance of their type,

for example, if I have an object named:

public Class MyPersonalObject {

   private int codeid = 0;
   private String name= null;
   public MyPersonalObject(int id){ ...}
   public MyPersonalObject(int id,String name){ ...}
   public void method1(){....}
   public void method2(){....}
   public void method3(){....}

}

then you can generate 3 instances of this class. all you can be sure that every individual 3 instances have a reference to an object of Class class that is presenting MyPersonalObject class schema. This Class is very much like a reference to the blueprint of every object instance.

a very common example of using reflection is in JDBC starting point.

Class.forName(""); // then you're loading the JDBC driver.

for example below code will expose what Class.getXxx(), method will work.

package com.navid.training.classtester;

import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
*
* @author Unknown_
*/
public class ClassTesting {

private static class MyInnerClass {

String name = "";
int code = 0;

public MyInnerClass(int code) {
this.code = code;
}

}

public void doWork(Object obj) {
Class<?> c = obj.getClass();
showClassInfo(c);
}

/**
* extracting and showing the class information.
*
* @param inputClass
*/
public void showClassInfo(Class<?> inputClass) {
System.out.println("SimpleName: " + inputClass.getSimpleName());
System.out.println("CanonicalName: " + inputClass.getCanonicalName());
System.out.println("Name: " + inputClass.getName());
System.out.println("TypeName: " + inputClass.getTypeName());
}

public static void main(String[] args) {

try {

//working with Class methods BASICS.
System.out.println("working with BASICS of CLASS methods.");
MyInnerClass innerClass = new MyInnerClass(12);
// Testing Innerclass instance
ClassTesting tester = new ClassTesting();
tester.doWork(innerClass);

//another test with a JDK Collection util package class
Map m = new HashMap<String, String>();
tester.doWork(m);
// Another test --
System.out.println("Using: Class.forName() -- it needs name and not choronical name!");
System.out.println("This may through \" java.lang.ClassNotFoundException\" - so to call inner classes you need something liek this "
+ "com.navid.training.classtester.ClassTesting$MyInnerClass");
Class<?> c = Class.forName("com.navid.training.classtester.ClassTesting$MyInnerClass");
tester.showClassInfo(c);

//Another test using class operator
System.out.println("Using: type literals for every Object - e.g: MyClass.class");
Class<?> c2 = MyInnerClass.class;
tester.showClassInfo(c2);

} catch (ClassNotFoundException ex) {
Logger.getLogger(ClassTesting.class.getName()).log(Level.SEVERE, null, ex);
}
}

}

and its output will be something like this.

run:
SimpleName: MyInnerClass
CanonicalName: com.navid.training.classtester.ClassTesting.MyInnerClass
Name: com.navid.training.classtester.ClassTesting$MyInnerClass
TypeName: com.navid.training.classtester.ClassTesting$MyInnerClass
SimpleName: HashMap
CanonicalName: java.util.HashMap
Name: java.util.HashMap
TypeName: java.util.HashMap
Using: Class.forName() -- it needs name and not choronical name!
This may through " java.lang.ClassNotFoundException" -
 so to call inner classes you need something like this 
com.navid.training.classtester.ClassTesting$MyInnerClass
SimpleName: MyInnerClass
CanonicalName: com.navid.training.classtester.ClassTesting.MyInnerClass
Name: com.navid.training.classtester.ClassTesting$MyInnerClass
TypeName: com.navid.training.classtester.ClassTesting$MyInnerClass
Using: type literals for every Object - e.g: MyClass.class
SimpleName: MyInnerClass
CanonicalName: com.navid.training.classtester.ClassTesting.MyInnerClass
Name: com.navid.training.classtester.ClassTesting$MyInnerClass
TypeName: com.navid.training.classtester.ClassTesting$MyInnerClass
BUILD SUCCESSFUL (total time: 0 seconds)

In above code, method doWork(Object obj), will do the actual work. you can see how we manipulate and handled the object instance which we have no idea about its type in time of development.