Survey
* Your assessment is very important for improving the work of artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the work of artificial intelligence, which forms the content of this project
Algorithm Programming 1
89-210
Java Reflection Mechanism
Bar-Ilan University
2006-2007 תשס"ז
Moshe Fresko
RTTI
RTTI : Run-time type identification
It lets you find the exact type of an object when
you have only a reference to the base type
“Traditional” RTTI : Assumes that you have all
the types available at compile time and run time
“Reflection” mechanism : Allows you to discover
class information solely at run time.
RTTI – Example
in Polymorphism
RTTI - Example
class Shape {
void draw() { System.out.println(this+".draw()"); }
}
class Circle extends Shape {
public String toString() { return "Circle"; }
}
class Square extends Shape {
public String toString() { return "Square"; }
}
class Triangle extends Shape {
public String toString() { return "Triangle"; }
}
public class Shapes {
public static void main(String[] args) {
Object[] shapeList = { new Circle(), new Square(), new Triangle() } ;
for(int i = 0; i < shapeList.length; i++)
((Shape)shapeList[i]).draw();
}
}
“Class” class
The RTTI information is kept in a special
object of class “Class”.
For each new class in a program a “Class”
object is created.
Dynamic loading of classes creates a new
“Class” object.
Class.forName(…)
class Candy {
static { System.out.println("Loading Candy"); }
}
class Gum {
static { System.out.println("Loading Gum"); }
}
class Cookie {
static { System.out.println("Loading Cookie"); }
}
public class SweetShop {
public static void main(String[] args) {
System.out.println("inside main");
new Candy();
System.out.println("After creating Candy");
try {
Class.forName("Gum");
} catch(ClassNotFoundException e) {
System.out.println("Couldn't find Gum");
}
System.out.println("After Class.forName('Gum')");
new Cookie();
System.out.println("After creating Cookie");
}
}
>java SweetShop
inside main
Loading Candy
After creating Candy
Loading Gum
After Class.forName(‘Gum’)
Loading Cookie
After creating Cookie
Casting
Type checking on Run time
Classic cast can throw ClassCastException
“Class” object can be queried for inheritance
information
“instanceof” keyword
Example: if(x instanceof Dog)
((Dog)x).bark();
Creating Instances
import java.util.*;
class Pet {}
class Dog extends Pet {}
class Pug extends Dog {}
class Cat extends Pet {}
class Rodent extends Pet {}
class Gerbil extends Rodent {}
class Hamster extends Rodent {}
public class PetInfo {
static Random rand = new Random();
static String[] typenames = { "Pet", "Dog", "Pug", "Cat", "Rodent", "Gerbil", "Hamster" } ;
public static void main(String[] args) {
Object[] pets = new Object[10];
try {
Class[] petTypes = { Class.forName("Dog"), Class.forName("Pug"),
Class.forName("Cat"), Class.forName("Rodent"),
Class.forName("Gerbil"), Class.forName("Hamster") };
for(int i = 0; i < pets.length; i++)
pets[i] = petTypes[rand.nextInt(petTypes.length)].newInstance();
} catch(InstantiationException e) {
System.out.println("Cannot instantiate"); System.exit(1);
} catch(IllegalAccessException e) {
System.out.println("Cannot access"); System.exit(1);
} catch(ClassNotFoundException e) {
System.out.println("Cannot find class"); System.exit(1);
}
for(int i = 0; i < pets.length; i++)
System.out.println(pets[i].getClass());
}
}
>java PetInfo
class Hamster
class Gerbil
class Cat
class Pug
class Rodent
class Hamster
class Dog
class Pug
class Pug
class Hamster
“Class” information
These two statements can bring the “Class”
information.
1.
2.
Class c = Class.forName(“Dog”) ;
Class c = Dog.class ;
The first one throws ClassNotFoundException
Class Instance Of …
class Base {}
class Derived extends Base {}
public class FamilyVsExactType {
static void test(Object x) {
System.out.println("Testing x of type " + x.getClass());
System.out.println("x instanceof Base " + (x instanceof Base));
System.out.println("x instanceof Derived " + (x instanceof Derived));
System.out.println("Base.isInstance(x) " + Base.class.isInstance(x));
System.out.println("Derived.isInstance(x) " + Derived.class.isInstance(x));
System.out.println("x.getClass() == Base.class " +
(x.getClass() == Base.class));
System.out.println("x.getClass() == Derived.class " +
(x.getClass() == Derived.class));
System.out.println("x.getClass().equals(Base.class)) "+
(x.getClass().equals(Base.class)));
System.out.println("x.getClass().equals(Derived.class)) " +
(x.getClass().equals(Derived.class)));
}
public static void main(String[] args) {
test(new Base());
test(new Derived());
}
}
>java FamilyVsExactType
Testing x of type class Base
x instanceof Base true
x instanceof Derived false
Base.isInstance(x) true
Derived.isInstance(x) false
x.getClass() == Base.class true
x.getClass() == Derived.class false
x.getClass().equals(Base.class)) true
x.getClass().equals(Derived.class)) false
Testing x of type class Derived
x instanceof Base true
x instanceof Derived true
Base.isInstance(x) true
Derived.isInstance(x) true
x.getClass() == Base.class false
x.getClass() == Derived.class true
x.getClass().equals(Base.class)) false
x.getClass().equals(Derived.class)) true
RTTI syntax
interface HasBatteries {}
interface Waterproof {}
interface Shoots {}
class Toy { Toy() {}
Toy(int i) {} }
class FancyToy extends Toy implements HasBatteries, Waterproof, Shoots {
FancyToy() { super(1); }
}
public class ToyTest {
static void printInfo(Class cc) {
System.out.println("Class: " + cc.getName() + " is interface? “ + cc.isInterface() );
}
public static void main(String[] args) {
Class c = null;
try { c = Class.forName("FancyToy");
} catch(ClassNotFoundException e) {
System.out.println("Can't find FancyToy"); System.exit(1); }
printInfo(c);
Class[] faces = c.getInterfaces();
for(int i = 0; i < faces.length; i++) printInfo(faces[i]);
Class cy = c.getSuperclass();
Object o = null;
try { o = cy.newInstance(); // Requires default constructor:
} catch(InstantiationException e) {
System.out.println("Cannot instantiate"); System.exit(1);
} catch(IllegalAccessException e) {
System.out.println("Cannot access"); System.exit(1); }
printInfo(o.getClass());
}
}
>java ToyTest
Class: FancyToy is interface? false
Class: HasBatteries is interface? true
Class: Waterproof is interface? true
Class: Shoots is interface? true
Class: Toy is interface? false
Reflection mechanism
With “RTTI” we can access class information that is
known at compile time.
With “Reflection” we can access classes that was not
known previously to compiler.
“Class” supports reflection
java.lang.reflect.* :
“Member” interface
“Field” class
“Method” class
“Constructor” class
Reflection
Retrieving class objects
Class c1 = myinst.getClass() ;
Class c2 = c1.getSuperclass() ; // can return null
Class c3 = Button.class ;
Class c4 = Class.forName(mystring) ;
Getting the class name
String s = c1.getName() ;
Getting the class modifiers
int m = c1.getModifiers() ;
bool isPublic = Modifier.isPublic(m) ;
bool isAbstract = Modifier.isAbstract(m) ;
bool isFinal = Modifier.isFinal(m) ;
Reflection
Getting the interfaces implemented by a class
Class c = myinst.getClass() ;
Class [ ] itfs = c.getInterfaces() ;
Examining interfaces
bool isInterface = myClass.isInterface() ;
Identifying class fields
Field [ ] publicFields = c.getFields() ;
for (int i=0;i<publicFields.length;++i) {
String fieldName = publicFields[i].getName() ;
Class typeClass = publicFields[i].getType() ;
…
}
Reflection
Discovering Class Constructors
Class c = myinst.getClass() ;
Constructor [ ] ctors = c.getConstructors() ;
for (int i=0;i<ctors.length;++i) {
Class [ ] params = ctors[i].getParameterTypes() ;
for (int k=0;k<params.length;++k) {
String paramType = params[k].getName() ;
…
}
}
Reflection
Getting Method Information
Class c = myinst.getClass() ;
Method [ ] ms = c.getMethods() ;
for (int i=0;i<ms.length;++i) {
String mname = ms[i].getName() ;
Class retType = ms[i].getReturnType() ;
Class[] params = ms[i].getParameterTypes() ;
for (int k=0;k<params.length;++k) {
String paramType = params[k].getName() ;
…
}
}
Reflection – Creating Objects
Using Default Constructors
Class c = Class.forName(“java.awt.Rectangle”) ;
Rectangle r = (Rectangle) c.newInstance() ;
Using Constructors with Arguments
Class c = Class.forName(“java.awt.Rectangle”) ;
Class[] intArgsClass = new Class[]{ int.class, int.class } ;
Object[] intArgs = new Object[]{new Integer(12),new
Integer(24)} ;
Constructor ctor = c.getConstructor(intArgsClass) ;
Rectangle r = (Rectangle) ctor.newInstance(intArgs) ;
Reflection – Accessing Fields
Getting Field Values
Rectangle r = new Rectangle(12,24) ;
Class c = r.getClass() ;
Field f = c.getField(“height”) ;
Integer h = (Integer) f.get(r) ;
Setting Field Values
Rectangle r = new Rectangle(12,24) ;
Class c = r.getClass() ;
Field f = c.getField(“width”) ;
f.set(r,new Integer(30)) ;
Reflection – Invoking Methods
String s1 = “Hello ” ;
String s2 = “World” ;
Class c = String.class ;
Class[] paramtypes = new Class[] { String.class } ;
Object[] args = new Object[] { s2 } ;
Method concatMethod =
c.getMethod(“concat”,paramtypes) ;
String result = (String) concatMethod.invoke(s1,args) ;
Tips
Don’t use the reflection API when other tools
more natural to Java are enough for a specific
problem.
It is easier to debug and maintain a program if
you don’t use Reflection objects.