Reflection in Java - PowerPoint PPT Presentation

1 / 39
About This Presentation
Title:

Reflection in Java

Description:

Example of execution: verifyClassInstance('java.util.Vector' ... public Class findClass(String className) throws ClassNotFoundException ... – PowerPoint PPT presentation

Number of Views:20
Avg rating:3.0/5.0
Slides: 40
Provided by: yvanla
Category:

less

Transcript and Presenter's Notes

Title: Reflection in Java


1
sysc2101 Object-Oriented Programming and Design
Laboratory
  • Reflection in Java

2
Reflection
  • In computer science, Reflection is the domain of
    programs that describe and manipulate
    "themselves", or other related programs.
  • In pure object-oriented languages such as
    Smalltalk, this is achieved by considering
    Classes as regular objects
  • as such, a Class is itself an instance of the
    Class of Classes, also called a Metaclass
  • this allows for an elegant way
  • to inspect properties of a class
  • to create new classes at runtime,
  • or to modify their behavior dynamically
  • powerful but dangerous!

3
Reflection in Java
  • For each class involved in a Java program, the
    Java Runtime Environment (JRE) maintains an
    immutable Class object that contains information
    about the class.
  • A Class object represents, or reflects, the
    class.
  • With the reflection API, you can invoke methods
    on a Class object which return Constructors,
    Methods, and Fields objects.You can use these
    objects to get information about the
    corresponding constructors, methods, and fields
    defined in the class.

4
Uses
  • To write a class browser you need a way to get
    information about classes at runtime.
  • You can reverse engineer bytecode into source
    code
  • You can develop tools that make use of method
    naming conventions to discover properties
  • JavaBeans
  • JUnit
  • You can enhance the behavior of a program during
    runtime by loading new classes

5
Reflection in Java
  • Using the classes of the Java reflection API
  • Classes in package java.lang
  • Class
  • Object
  • Package
  • ClassLoader
  • Classes in package java.lang.reflect
  • Array
  • Method
  • Modifier
  • Constructor
  • Field

6
Java reflection mechanisms
  • Java reflection mechanisms
  • Obtaining information
  • Acting on an object
  • Working with arrays

7
Obtaining information
  • Information about a class or the class of an
    object, when they are known only at runtime
  • Name,
  • Modifiers,
  • Superclass,
  • Implemented interfaces,
  • Is a Class object representing a class or an
    interface,
  • Fields,
  • Constructors,
  • Methods.

8
Information about a class
  • Getting the class of an (mystery) object
  • Class c mystery.getClass() //recall instanceof
  • Getting the super class of a class
  • TextField t new TextField()
  • Class c t.getClass()
  • Class s c.getSuperclass()
  • Getting a class from its name at compile time
  • Class c java.awt.Button.class
  • Getting a class from its name at runtime
  • Class c Class.forName(strg)
  • Getting the class name of an object
  • String s o.getClass().getName()

9
Example 1
  • Getting the modifiers of a class
  • void printModifiers(String name) throws
    ClassNotFoundException
  • out.println(Class name is)
  • Class c Class.forName(name)
  • int m c.getModifiers()
  • if (Modifier.isPublic(m))
  • out.println("public")
  • else
  • out.println("not public")
  • if (Modifier.isAbstract(m))
  • out.println("abstract")
  • else
  • out.println("not abstract")
  • if (Modifier.isFinal(m))
  • out.println("final")
  • else
  • out.println("not final")
  • Example of execution
  • printModifiers(java.lang.System)
  • printModifiers(java.io.InputStream)
  • Result
  • Class java.lang.System is
  • public
  • not abstract
  • final
  • Class java.io.InputStream is
  • public
  • abstract
  • not final

10
Example 2
  • Finding ancestors
  • void printSuperclass(String name) throws
    ClassNotFoundException
  • Class subClass, superClass
  • subClass Class.forName(name)
  • superClass subClass.getSuperclass()
  • out.println(The ancestors of name are)
  • while (superClass ! null)
  • out.println(superClass.getName())
  • subClass superClass
  • superClass subClass.getSuperclass()

Example of execution printAncestors(java.io.Buf
feredInputStream)
Result The ancestors of java.io.BufferedInputStre
am are java.io.FilterInputStream java.io.InputStre
am java.lang.Object
11
Example 3
  • Finding implemented interfaces
  • void printInterfaceNames(String name)
  • Class c Class.forName(name)
  • Class theInterfaces c.getInterfaces()
  • out.println(The interfaces implemented by
    name are)
  • for (int i0 ilttheInterfaces.length i)
  • String interfaceName theInterfacesi.getName()
  • System.out.println(interfaceName)

Example of execution printInterfaceNames(java.ut
il.Vector)
  • Result
  • The interfaces implemented by java.util.Vector
    are
  • java.util.List
  • java.util.RandomAccess
  • java.lang.Cloneable
  • java.io.Serializable

12
Example 4
  • Is a Class instance a class or an interface?
  • void verifyClassInstance(String name)
  • Class c Class.forName(name)
  • if (c.isInterface())
  • System.out.println(name " is an interface.")
  • else
  • System.out.println(name " is a class.")

Example of execution verifyClassInstance(java.ut
il.Vector) verifyClassInstance(java.util.Random
Access) Result java.util.Vector is a
class java.util.RandomAccess is an interface
13
Example 5
  • Identifying class fields
  • void printFieldNames(String name)
  • Class c Class.forName(name), typeClass
  • String fieldType
  • Field publicFields c.getFields()
  • for (int i 0 i lt publicFields.length i)
  • typeClass publicFieldsi.getType()
  • fieldType typeClass.getName()
  • out.println("Name "publicFieldsi.getName()",T
    ype"fieldType)
  • Result
  • Name ttype, type int
  • Name TT_EOF, type int
  • Name TT_EOL, type int
  • Name TT_NUMBER, type int
  • Name TT_WORD, type int
  • Name sval, type java.lang.String
  • Name nval, type double

Example of execution printFieldsName(java.io.St
reamTokenizer)
14
Example 6
  • Showing constructors information
  • void showConstructors(String name)
  • Class c Class.forName(name)
  • Constructor cs c.getConstructors()
  • for (int i0 iltcs.length i)
  • System.out.print("( ")
  • Class pT csi.getParameterTypes()
  • for (int k 0 k lt pT.length k )
  • System.out.print(pTk.getName() " ")
  • System.out.println(")")

Example of execution showConstructors(java.util.
Vector)
Result ( ) ( int int ) ( java.util.Collection
) ( int )
15
Example 7
  • Showing methods information
  • void showMethods(String name)
  • Class c Class.forName(name)
  • Method Ms c.getMethods()
  • for (int i 0 i lt Ms.length i)
  • out.println("Name " Msi.getName())
  • out.println(\tReturn Type "Msi.getReturnType(
    ).getName())
  • Class paramT Msi.getParameterTypes()
  • out.print(\tParameter Types ")
  • for (int k 0 k lt paramT.length k )
  • out.print(" " paramTk.getName())
  • out.println()

16
Example 7 (cont.)
  • Example of execution
  • showMethods(java.util.Vector)
  • Result
  • Name removeElement
  • Return type boolean
  • Parameter types java.lang.Object
  • Name removeElementAt
  • Return type void
  • Parameter types int
  • Name subList
  • Return type java.util.List
  • Parameter type int int
  • Name iterator
  • Return type java.util.Iterator
  • Parameter types

17
Acting on an object
  • Acting on an object when its type is only known
    at runtime
  • Creating an object,
  • Getting field values,
  • Setting field values,
  • Invoking methods.

18
Creating an instance with a no-argument
constructor
  • Object createObjectDefault(String className)
  • Object obj null
  • try
  • Class classDef Class.forName(className)
  • obj classDef.newInstance()
  • catch (Exception e)
  • // throws ClassNotFoundException,
    InstantiationException, IllegalAccessException
  • System.out.println(e)
  • return obj
  • Example of execution
  • Rectangle r (Rectangle) createObject("java.awt.R
    ectangle")
  • System.out.println(r)
  • Result
  • java.awt.Rectanglex0,y0,width0,height0

19
Creating an instance with a constructor that have
given argument types
  • Object createObject( Constructor constr, Object
    arguments)
  • System.out.println ("Constructor "
    constr.toString())
  • Object object null
  • try
  • object constr.newInstance(arguments)
  • System.out.println ("Object "
    object.toString())
  • catch (Exception e)
  • return object

20
  • Rectangle r
  • Class rectDef
  • Class intArgsClass new Class int.class,
    int.class
  • Integer height new Integer(12)
  • Integer width new Integer(34)
  • Object intArgs new Object height, width
  • Constructor Constr
  • try
  • rectDef Class.forName("java.awt.Rectangle")
  • Constr rectDef.getConstructor(intArgsClass)
  • r (Rectangle) createObject(Constr, intArgs)
  • catch (Exception e)

21
Getting field values
  • void printHeight(Rectangle r)
  • Field hF
  • Object hV
  • Class c r.getClass()
  • try
  • hF c.getField("height")
  • hV hF.get(r)
  • System.out.println("Height " hV.toString())
  • catch (Exception e)

22
Setting field value
  • void modifyWidth(Rectangle r, Integer val )
  • Field wF
  • Class c r.getClass()
  • try
  • wF c.getField("width")
  • wF.set(r, val)
  • catch (Exception e)

23
Invoking methods
  • String append(String first, String second)
  • String result null
  • Class c String.class
  • Class paramT new ClassString.class
  • Method concatM
  • Object args new Object second
  • try
  • concatM c.getMethod("concat", paramT)
  • result (String) concatM.invoke(first, args)
  • catch (Exception e)
  • return result

24
Working with Arrays
  • The java.lang.reflect.Array class provides
    methods that allow you to dynamically create and
    access arrays.
  • Working with arrays
  • Identifying arrays,
  • Retrieving Component Types,
  • Creating an array,
  • Getting and setting elements.

25
Identifying arrays among attributes
  • void printArrayNames(String name)
  • Class targetClass Class.forName(name),
    typeClass
  • Field publicFields targetClass.getFields()
  • for (int i0 i lt publicFields.length i)
  • typeClass publicFieldsi.getType()
  • if (typeClass.isArray())
  • System.out.println( "Name publicFieldsi.get
    Name() ", Type typeClass.getName())

26
Retrieving Component Types
  • void printComponentType(Object array)
  • Class arrayClass array.getClass(),
    componentClass
  • if (!arrayClass.isArray())
  • return
  • componentClass arrayClass.getComponentType()
  • System.out.println( "Array "
    arrayClass.getName() ", Component "
    componentClass.getName())
  • Example of execution
  • Object objs new Object new Integer(12),
    new Integer(12)
  • printComponentType(objs)
  • int arr new int23
  • printComponentType(arr)
  • Result
  • Array Ljava.lang.Object, Component
    java.lang.Object
  • Array I, Component I

27
Creating an array
  • Object doubleArray(Object source)
  • int sourceLength Array.getLength(source)
  • Class arrayClass source.getClass()
  • Class componentClass arrayClass.getComponentType
    ()
  • Object result Array.newInstance(componentClass,
    sourceLength 2)
  • System.arraycopy(source, 0, result, 0,
    sourceLength)
  • return result

28
Getting and setting element values
  • void copyArray(Object source, Object dest)
  • for (int i0 i lt Array.getLength(source) i)
  • Array.set(dest, i, Array.get(source, i))
  • System.out.println(Array.get(dest, i))

29
Working with arrays (example)
  • Problem
  • Suppose you have an array of some type that is
    full and you want to grow it.
  • And suppose your are sick of writing the
    grow-and-copy code by hand.
  • You can write a generic method to grow an array.
  • Solution using reflection mechanisms
  • Object arrayGrow(Object a)
  • if (!a.getClass().isArray())
  • return null
  • Class compType a.getClass().getComponentType()
  • int length Array.getLength(a)
  • int newLength length 1
  • Object newArray Array.newInstance(compType,
    newLength)
  • System.arraycopy(a, 0, newArray, 0, length)
  • return newArray

30
ClassLoader
  • A class loader is an object that is responsible
    for loading classes
  • Inherits from abstract class java.lang.ClassLoader
  • Given the name of a class, a class loader should
    attempt to locate or generate data that
    constitutes a definition for the class.
  • A typical strategy is to transform the name into
    a file name and then read a "class file" of that
    name from a file system.
  • Applications implement subclasses of ClassLoader
    in order to extend the manner in which the Java
    virtual machine dynamically loads classes.
  • The ClassLoader class uses a delegation model to
    search for classes and resources.
  • Each instance of ClassLoader has an associated
    parent class loader.
  • When called upon to find a class or resource, a
    ClassLoader instance will delegate the search for
    the class or resource to its parent class loader
    before attempting to find the class or resource
    itself.
  • The virtual machine's built-in class loader,
    called the bootstrap class loader, does not
    itself have a parent but may serve as the parent
    of a ClassLoader instance.

31
Example
  • Problem
  • Assume you have to build a tool that analyzes
    java source code
  • e.g., youre building a tool that
    reverse-engineers the class diagram
  • The classes you need the information of are not
    the ones of your program, but the ones of another
    program (the program of which you want to build
    the class diagram)
  • You cannot use the Class instances from the
    ClassLoader in your program
  • You need a new ClassLoader that can look for
    class files in different directories

32
Example (cont.)
  • public class MyClassLoader extends ClassLoader
  • private String thePath
  • // the directory where the program to analyze is
    located (.class files)
  • public MyClassLoader()
  • public void setPath(String p)
  • thePath p
  • if ( (!thePath.endsWith("/"))
    (!thePath.equals("")) )
  • thePath "/"
  • public Class findClass(String className) throws
    ClassNotFoundException
  • protected byte loadClassBytes(String className)
    throws IOException

33
Example (cont.)
  • public Class findClass(String className) throws
    ClassNotFoundException
  • byte classBytes null
  • Class cl
  • try
  • classBytes loadClassBytes(className)
  • // Reads a class definition from a .class file
  • catch (IOException e)
  • throw new ClassNotFoundException(className)
  • try
  • cl defineClass(className, classBytes, 0,
    classBytes.length)
  • // Method from class ClassLoader Converts an
    array of bytes into
  • // an instance of class Class
  • catch (NoClassDefFoundError r)
  • throw new ClassNotFoundException(className)
  • if (clnull)
  • throw new ClassNotFoundException(className)
  • return cl

34
Example (cont.)
  • protected byte loadClassBytes(String className)
    throws IOException
  • String cName
  • FileInputStream in null
  • ByteArrayOutputStream buffer null
  • byte b
  • int ch
  • cName thePath className.replace('.', '/')
    ".class"
  • try
  • in new FileInputStream(cName)
  • buffer new ByteArrayOutputStream()
  • while ((chin.read())! -1)
  • b (byte)ch
  • buffer.write(b)
  • in.close()
  • return buffer.toByteArray()
  • finally
  • if (in ! null)
  • in.close()

35
Two Case Studies
  • Writing a correct equals()
  • Inside the design of JUnit

36
A Correct equals()
  • Recall that according to the Java specs the
    equals() method should be an equivalence relation
    and therefore obey the following specifications
  • reflexive x.equals(x) true
  • symmetric x.equals(y) y.equals(x)
  • transitive
  • if ((x.equals(y)) (y.equals(z)))
  • then (x.equals(z) true)

37
A Correct equals()?
  • Below is an equals() method written for class
    Point
  • public class Point
  • private int x, y
  • public boolean equals(Object other)
  • if (other instanceof Point)
  • otherP (Point) other
  • return this.x otherP.x this.y
    otherP.y
  • else return false
  • Is this method following the specs?

38
A Correct equals()!
  • public boolean equals(Object other)
  • if (this.getClass() other.getClass())
  • otherP (Point) other
  • return this.x otherP.x this.y
    otherP.y
  • else return false
  • Note the use of instead of equals() to
    compare the classes
  • the class variable is a singleton, we can just
    compare the references

39
Use of Reflection in JUnit
  • Recall that each test case must be implemented as
    a public method with a name that starts with
    testXXX
  • Such a convention makes life easy for the
    developer
  • But the JUnit framework needs to manipulate each
    test case as a separate object, in order to
    invoke setUp(), run() and tearDown() for each.
  • JUnit creates instances of class TestCase and
    invokes such methods on them
  • it does so using reflection!
  • In fact, there JUnit uses many design patterns
    that are interesting to study by their own right
  • http//junit.sourceforge.net/doc/cookstour/cooksto
    ur.htm
Write a Comment
User Comments (0)
About PowerShow.com