22
14/04/15 1 Run-Time Type Identification and Reflection Advanced Programming 14/04/15 Barbara Russo Motivation Since all Java classes are derived from Object, its easy to mix objects of different types together into a collection The retrieving objects from collections creates problem, because the actual type of the objects is lost Solution: RTTI is used to reveal the true types at run time 14/04/15 Barbara Russo

RTTI And reflection - Free University of Bozen-Bolzano › ~russo › AP › RTTI.pdf · 2016-02-04 · Reflection API • The reflection API comprises the • java.lang.reflect package

  • Upload
    others

  • View
    1

  • Download
    0

Embed Size (px)

Citation preview

Page 1: RTTI And reflection - Free University of Bozen-Bolzano › ~russo › AP › RTTI.pdf · 2016-02-04 · Reflection API • The reflection API comprises the • java.lang.reflect package

14/04/15

1

Run-Time Type Identification and Reflection

Advanced Programming

14/04/15 Barbara Russo

Motivation

•  Since all Java classes are derived from Object, it’s easy to mix objects of different types together into a collection

•  The retrieving objects from collections creates problem, because the actual type of the objects is lost

•  Solution: RTTI is used to reveal the true types at run time

14/04/15 Barbara Russo

Page 2: RTTI And reflection - Free University of Bozen-Bolzano › ~russo › AP › RTTI.pdf · 2016-02-04 · Reflection API • The reflection API comprises the • java.lang.reflect package

14/04/15

2

RTTI

•  RTTI lets you find the exact type of an object when you only have a reference to the base type

14/04/15 Barbara Russo

Collections in Java •  Array

–  has a special language support

•  Iterators

–  Iterator(I)

•  Collections also called containers

–  Collection(I)

–  Set(I)

•  HashSet(c), TreeSet(c)

–  List(I)

•  ArrayList(c), LinkedList(c)

–  Map(I)

•  HashMap(c), TreeMap(c)

14/04/15 Barbara Russo

Page 3: RTTI And reflection - Free University of Bozen-Bolzano › ~russo › AP › RTTI.pdf · 2016-02-04 · Reflection API • The reflection API comprises the • java.lang.reflect package

14/04/15

3

The collections interfaces

14/04/15 5

RTTI with polymorphism

•  Consider the class hierarchy that uses polymorphism.

•  The generic type is the base class Shape, and the specific derived types are Circle, Square, and Triangle:

14/04/15 Barbara Russo

Page 4: RTTI And reflection - Free University of Bozen-Bolzano › ~russo › AP › RTTI.pdf · 2016-02-04 · Reflection API • The reflection API comprises the • java.lang.reflect package

14/04/15

4

Goal of RTTI

•  You can manipulate references to the base type (Shape, in this case) and

•  when extending the program by adding a new class (Triangle, derived from Shape, for example), the original code is not affected

14/04/15 Barbara Russo

RTTI examples

•  Casting

•  instanceOf operator

14/04/15 Barbara Russo

Page 5: RTTI And reflection - Free University of Bozen-Bolzano › ~russo › AP › RTTI.pdf · 2016-02-04 · Reflection API • The reflection API comprises the • java.lang.reflect package

14/04/15

5

Casting •  import java.util.*; •  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"; } •  }

14/04/15 Barbara Russo

Example: casting at run time public class Shapes {

public static void main(String[] args) {

ArrayList s = new ArrayList();

s.add(new Circle());

s.add(new Square());

s.add(new Triangle());

Iterator e = s.iterator();

while(e.hasNext()) (Shape)e.next()).draw();

}

} 14/04/15 Barbara Russo

I just need to cast for the base, then polymorphism applies

e.next() returns a type Object : Object x=newCircle() Down casting here is safe as there is no assignement

Page 6: RTTI And reflection - Free University of Bozen-Bolzano › ~russo › AP › RTTI.pdf · 2016-02-04 · Reflection API • The reflection API comprises the • java.lang.reflect package

14/04/15

6

Interpreting the example

•  The class Shape contains draw( ) that indirectly uses toString( ) to print an identifier for the class by passing this to System.out.println( )

•  If that function sees an object, it automatically calls the toString( ) method to produce a String representation.

•  Each of the derived classes overrides the toString( ) method (from Object) so that draw( ) ends up printing something different in each case

14/04/15 Barbara Russo

Interpreting the example •  In main( ), specific types of Shape are created and then added to an

ArrayList. This is the point at which the downcast occurs because the ArrayList holds only Object references

•  when we access the ArraList we just get Object: we have lost the specializations of the objects in the array

•  Therefore next( ) naturally produces an Object reference (Object x)

•  So a cast to Shape is necessary

•  Down casting is the first example of RTTI, since in Java all casts are checked for correctness at run-time!

14/04/15 Barbara Russo

Page 7: RTTI And reflection - Free University of Bozen-Bolzano › ~russo › AP › RTTI.pdf · 2016-02-04 · Reflection API • The reflection API comprises the • java.lang.reflect package

14/04/15

7

Interpreting the example •  In

((Shape)e.next()).draw();

•  we mean the next object is referenced by a reference variable of type Shape:

Shape aShape

•  Then we pass an object of the children type at run time (the entry in the array)

Shape aShape = new Circle();

•  We have manipulated the base with casting and we have used polymorphism with the instantiation above

14/04/15 Barbara Russo

Note on casting types •  (Downcasting) A conversion from type Object to type Shape requires a run-

time check to make sure that the run-time value is actually an instance of class Shape or one of its subclasses; if it is not, an exception is thrown.

Shape aShape= (Shape) getDog();

–  if the returning object of getDog() is not a subtype of Shape, this throws an exception

•  (Upcasting) A conversion from type Shape to type Object requires no run-time action; Shape is a subclass of Object, so any reference produced by an expression of type Shape is a valid reference value of type Object. In this case, the reference variable points to the internal object of the object of Shape of type Object

14/04/15 Barbara Russo

Page 8: RTTI And reflection - Free University of Bozen-Bolzano › ~russo › AP › RTTI.pdf · 2016-02-04 · Reflection API • The reflection API comprises the • java.lang.reflect package

14/04/15

8

RTTI with

•  instanceof operator

14/04/15 Barbara Russo

Instanceof •  The operator instanceof is applied to recognize the type of the object passed

as reference

–  instanceof compares an object to a specified type and returns true or false.

•  In inheritance, as derived classes (Circle and Triangle) are a base class (Shape), the method can be applied without any casting

•  returns false when given a null value or the object is not of a given class

14/04/15 Barbara Russo

Page 9: RTTI And reflection - Free University of Bozen-Bolzano › ~russo › AP › RTTI.pdf · 2016-02-04 · Reflection API • The reflection API comprises the • java.lang.reflect package

14/04/15

9

Example: instanceof() class InstanceofTest { public static void main(String[] args) { Shape obj1 = new Shape(); Shape obj2 = new Circle(); System.out.println("obj1 instanceof Shape: " + (obj1 instanceof Shape));

System.out.println("obj1 instanceof Circle: " + (obj1 instanceof Circle)); System.out.println("obj1 instanceof MyInterface: " + (obj1 instanceof MyInterface)); System.out.println("obj2 instanceof Shape: " + (obj2 instanceof Shape)); System.out.println("obj2 instanceof Circle: " + (obj2 instanceof Circle)); System.out.println("obj2 instanceof MyInterface: " + (obj2 instanceof MyInterface));

} } class Shape{} class Circle extends Shape implements MyInterface{} interface MyInterface{}

14/04/15 Barbara Russo

instanceOf() Output:

obj1 instanceof Shape: true

obj1 instanceof Circle: false

obj1 instanceof MyInterface: false

obj2 instanceof Shape: true

obj2 instanceof Circle: true

obj2 instanceof MyInterface: true

14/04/15 Barbara Russo

Circle is a child of Shape so if I ask whether it is of type Shape I get true

Page 10: RTTI And reflection - Free University of Bozen-Bolzano › ~russo › AP › RTTI.pdf · 2016-02-04 · Reflection API • The reflection API comprises the • java.lang.reflect package

14/04/15

10

instanceof

•  Avoid to use the instanceOf operator to call a method based explicitly on the class of some object, instead of implicitly using an overridden method and polymorphism

14/04/15 Barbara Russo

do not use instanceof instead of polymorphism! class Shape { void draw() { System.out.println(“Shape”); } } class Circle extends Shape { public String drawCircle() {System.out.println("Circle”); } } class Square extends Shape { public String drawSquare() {System.out.println(“Square”); } } public static void draw(Shape o){ if (o instanceof Circle){ Circle circle = (Circle) o; o.drawCircle();} else if (o instanceof Square){ Square circle = (Square) o; o.drawSquare();} }

14/04/15 Barbara Russo

Page 11: RTTI And reflection - Free University of Bozen-Bolzano › ~russo › AP › RTTI.pdf · 2016-02-04 · Reflection API • The reflection API comprises the • java.lang.reflect package

14/04/15

11

Accessing Class objects // static method of Class (at run time):

Class circle = Class.forName(“Circle“);

// class literal (at compile time):

Class rectangle = Square.class;

// method of Object (at run time):

Class x = x.getClass();

•  Class literals are more efficient since they are checked at compile time.

•  With getClass() you have dynamic access to the unknown type of an object.

14/04/15 Barbara Russo

Example in Java (1/4)

14/04/15 Barbara Russo

public class Animal {

private String name; public Animal(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String toString() { return "<" + name + ">"; }

} public class Cat extends Animal {

public Cat(String name) { super(name); }

} public class Dog extends Animal { public Dog(String name) {

super(name); }

}

Page 12: RTTI And reflection - Free University of Bozen-Bolzano › ~russo › AP › RTTI.pdf · 2016-02-04 · Reflection API • The reflection API comprises the • java.lang.reflect package

14/04/15

12

Example in Java (2/4)

14/04/15 Barbara Russo

import java.util.*; public class BagOfObjects {

private ArrayList listOfObjects = new ArrayList(); private int noCats = 0; private int noDogs = 0; private int noOthers = 0; public void add(Object o) { if (o instanceof Cat) noCats++; else if (o instanceof Dog) noDogs++; else noOthers++; listOfObjects.add(o); }

// continue …

Using the operator instanceof we detect the true type of the object being added to the bag. This is fine as we are using instanceof explicitly and not with method overriding

Example in Java (3/4)

14/04/15 Barbara Russo

// continued class BagOfObjects…

public String toString() { String res = "In total there are: \n"; res += " " + noCats + " cats,\n"; res += " " + noDogs + " dogs, and\n"; res += " " + noOthers + " others\n\n"; for (int i = 0; i < listOfObjects.size(); i++) { Object t = listOfObjects.get(i); res += "\tElement " + i + " is an object of " + t.getClass(); if (t instanceof Dog || t instanceof Cat) { Animal a = (Animal) t; res += "\t --- Name: " + a.getName() + " \n "; } else res += "\n"; } return res; }

}

Here we use the method getClass(), inherited from Object, which indirectly accesses the class object of t in order to display its class name at run time

We check at run time the type of t, then we downcast it to a reference to Animal in a safe way as t still remains a reference to an Object . Then we apply polymorphism to get the right name of the children at run time. Again the use of instanceof is explicit

Page 13: RTTI And reflection - Free University of Bozen-Bolzano › ~russo › AP › RTTI.pdf · 2016-02-04 · Reflection API • The reflection API comprises the • java.lang.reflect package

14/04/15

13

Example in Java (4/4)

14/04/15 Barbara Russo

public class BagTest {

public static void main(String argv[]) { BagOfObjects aBag = new BagOfObjects(); aBag.add(new Object()); aBag.add(new Cat("Fuffy")); aBag.add(new Cat(“Garfield")); aBag.add(new Dog("Fido")); System.out.println(aBag); }

}

Interpreting the example

•  The method toString() of Object is overridden by the toString() of BagOfObjects and the console displays the nested information returned with the String “res”

14/04/15 Barbara Russo

Page 14: RTTI And reflection - Free University of Bozen-Bolzano › ~russo › AP › RTTI.pdf · 2016-02-04 · Reflection API • The reflection API comprises the • java.lang.reflect package

14/04/15

14

RTTI vs reflection API

•  With RTTI we need to have all the types we use at run time available at compile time

•  Many times this is not possible

–  if we receive data that represents classes remotely. At compile time we do not have them •  e.g. with Remote Method Invocation (RMI) we can call methods

distributed on remote machines. As such locally at compile time we do not know the types used by these methods

14/04/15 Barbara Russo

The Reflection API

•  To solve this issue we use the reflection API

•  Objects of the java.lang.reflect package are created by the JVM at run time to represent the corresponding member of the class / interface unknown at compilation time (we need to have the .class files available only at run time)

14/04/15 Barbara Russo

Page 15: RTTI And reflection - Free University of Bozen-Bolzano › ~russo › AP › RTTI.pdf · 2016-02-04 · Reflection API • The reflection API comprises the • java.lang.reflect package

14/04/15

15

Extending RTTI: use of reflection

•  In the above example, the down cast is checked at run time and at run time we can call the appropriate method of the child

•  Sometimes we want to know the exact type of the reference for this we use reflection

14/04/15 Barbara Russo

Java reflection API

•  The reflection API reflects, the classes, interfaces, and objects accessible by the current JVM

14/04/15 Barbara Russo

Page 16: RTTI And reflection - Free University of Bozen-Bolzano › ~russo › AP › RTTI.pdf · 2016-02-04 · Reflection API • The reflection API comprises the • java.lang.reflect package

14/04/15

16

Reflection API

•  The reflection API comprises the

•  java.lang.reflect package and

•  java.lang.Class

14/04/15 Barbara Russo

Use of API reflection •  The reflection API represents, or reflects, the classes,

interfaces, and objects in the current Java Virtual Machine

•  Use the reflection API if you are writing development tools such as debuggers, class browsers, and GUI builders

•  Be careful to use it when you have security issues

http://docs.oracle.com/javase/tutorial/reflect/

14/04/15 Barbara Russo

Page 17: RTTI And reflection - Free University of Bozen-Bolzano › ~russo › AP › RTTI.pdf · 2016-02-04 · Reflection API • The reflection API comprises the • java.lang.reflect package

14/04/15

17

With the reflection API you can ü  Determine the class of an object

ü  Get information about a class's modifiers, fields, methods, constructors, and superclasses

ü  Find out what constants and method declarations belong to an interface

ü  Create an instance of a class whose name is not known until runtime

ü  Get and set the value of an object's field, even if the field name is unknown to your program until runtime

ü  Invoke a method on an object, even if the method is not known until runtime

ü  Create a new array, whose size and component type are not known until runtime, and then modify the array's components

14/04/15 Barbara Russo

java.lang.Class http://docs.oracle.com/javase/7/docs/api/java/lang/Class.html

•  Instances of the class Class represent classes and interfaces in a running Java application –  There is a Class object for each class or interface

–  Every array is reflected as a Class object that is shared by all arrays with the same element type and number of dimensions

–  The primitive Java types (boolean, byte, char, short, int, long, float, and double), and the keyword void are also represented as Class objects

14/04/15 Barbara Russo

Page 18: RTTI And reflection - Free University of Bozen-Bolzano › ~russo › AP › RTTI.pdf · 2016-02-04 · Reflection API • The reflection API comprises the • java.lang.reflect package

14/04/15

18

Understanding Class •  Every time we write and compile a new class one

object of Class is created. It is saved in a file .class and called with the same name of the class

•  At run time when we want to create a given object of the class, the JVM checks first if the object of Class has been loaded

•  If not the JVM loads it searching for the file .class with the same name of the class

14/04/15 Barbara Russo

Example: forName()

•  The static method forName(String s) of Class receives a string with the exact name of a class and returns a reference to the object of Class for that type

•  Class.forName(“Shape”); returns a reference to the object of Class of type Shape

14/04/15 Barbara Russo

Page 19: RTTI And reflection - Free University of Bozen-Bolzano › ~russo › AP › RTTI.pdf · 2016-02-04 · Reflection API • The reflection API comprises the • java.lang.reflect package

14/04/15

19

14/04/15 CASE 37

import java.util.*; public final class Sample {

private String fName; public Sample(String fName){ super(); this.fName = fName; } public String toString() { StringBuffer result = new StringBuffer(); String newLine = System.getProperty("line.separator"); // returns the line separator result.append( this.getClass().getName() ); result.append( " Object {" ); result.append(newLine); java.lang.reflect.Field[] fields = this.getClass().getDeclaredFields(); for ( int fieldIdx=0; fieldIdx < fields.length; ++fieldIdx ) { result.append(" "); try { result.append( fields[fieldIdx].getName() ); // returns the String value of the field: “fName” result.append(": "); result.append( fields[fieldIdx].get(this) ); // it returns the value of the Field of the object of type Sample :“CIAO”…

Exercise

Exercise cont.

… } catch ( IllegalAccessException ex ) { System.out.println(ex);

} result.append(newLine); } result.append("}"); return result.toString();

}

public static void main ( String[] arguments ) { Sample sample = new Sample( “CIAO"); System.out.println(sample); }

}

14/04/15 CASE 38 Write the output!

Page 20: RTTI And reflection - Free University of Bozen-Bolzano › ~russo › AP › RTTI.pdf · 2016-02-04 · Reflection API • The reflection API comprises the • java.lang.reflect package

14/04/15

20

Solution Sample Object {

fName: CIAO

}

14/04/15 CASE 39

Example with reflection

•  Bag of objects using reflection

•  Consider the aforementioned bag of object example

•  We change the BagOfObjects class implementation and add an helper class ClassCount in order to use reflection

14/04/15 Barbara Russo

Page 21: RTTI And reflection - Free University of Bozen-Bolzano › ~russo › AP › RTTI.pdf · 2016-02-04 · Reflection API • The reflection API comprises the • java.lang.reflect package

14/04/15

21

Example

14/04/15 Barbara Russo

class ClassCount { // helper class to keep track of occurrences

private Class classOfObjects; private int occurrences;

Class getClassOfObjects() { return classOfObjects; } void setClassOfObjects(Class v) { this.classOfObjects = v; } int getOccurrences() { return occurrences; } void setOccurrences(int v) { this.occurrences = v; } void incrementOccurrences() { occurrences++; }

ClassCount(Class c, int n) { classOfObjects = c; occurrences = n; }

}

The class and all its methods have default access level, because we don’t need to use them outside the package

Example in Java (1/3)

14/04/15 Barbara Russo

public class BagOfObjects {

private ArrayList listOfObjects = new ArrayList(); private ArrayList listOfCounts = new ArrayList(); public void add(Object o) { boolean found = false; for ( int i = 0; i < listOfCounts.size(); i++ ) { ClassCount c = (ClassCount) listOfCounts.get(i); if ( c.getClassOfObjects().equals( o.getClass() ) ) { c.incrementOccurrences(); found = true; break; } } if (!found) { ClassCount c = new ClassCount( o.getClass(), 1 ); listOfCounts.add(c); } listOfObjects.add(o); } // continue …

indicates whether the two references point to the same object of type Class

Page 22: RTTI And reflection - Free University of Bozen-Bolzano › ~russo › AP › RTTI.pdf · 2016-02-04 · Reflection API • The reflection API comprises the • java.lang.reflect package

14/04/15

22

Example in Java (2/3)

14/04/15 Barbara Russo

// continued class BagOfObjects…

public int getHowMany(Class aClass) { for ( int i = 0; i < listOfCounts.size(); i++ ) { ClassCount c = (ClassCount) listOfCounts.get( i ); if ( c.getClassOfObjects().equals( aClass ) ) { return c.getOccurrences(); } } return 0; // No objects found in listOfCounts! }

// continue …

Example in Java (3/3)

14/04/15 Barbara Russo

// continued class BagOfObjects…

public String toString() { String res = "In total there are: \n"; for (int i = 0; i < listOfCounts.size(); i++) { ClassCount c = (ClassCount) listOfCounts.get(i); res += "\t" + c.getOccurrences() + " elements of " +

c.getClassOfObjects() + "\n"; } res += "\n-----\n"; for ( int i = 0; i < listOfObjects.size(); i++ ) { Object t = listOfObjects.get(i); res += "\tElement " + i + " is " + t + " of " + t.getClass() + " \n "; } return res; }

} // end of class BagOfObjects