Section 9.6. Reflection

   

9.6 Reflection

Reflection is a powerful aspect of Java. Reflection is what allows a program to inspect the abilities of a Java class at runtime. Reflection is used chiefly to build RAD tools for Java programmers. Because it is a complex topic and is of less interest to the typical Java application developer, it will only be mentioned here. You can safely skim this section and return to it later if you have a need for it.

The java.lang.reflect package is the package that contains the classes and interfaces necessary to obtain this reflective information. Its primary purpose is to allow access to information regarding the constructors, fields, and methods of loaded classes. Once you have inspected these classes, you can use the reflective items to perform operations on their counterpart objects.

Related to reflection are two classes in the java.lang package that we will briefly look at now. These are the class named Class and the class named Object .

9.6.1 final Fields

Using final on variables essentially creates a constant. As with other things final , you cannot change the value of a final variable throughout the life of your program. Use this modifier to declare constants.

9.6.2 FinalFields.java

 package javaforcf.chp9;  public final class FinalFields {   final double VERSION = 1.0;   public static void main(String[] args) {   FinalFields obj  = new FinalFields();   System.out.println(obj.VERSION);   } } 

Trying to write something like

 obj.VERSION = 2.0; 

gets you the following compiler error:

 variable VERSION is declared final; cannot be assigned 

There are a number of methods in the API that are declared final . Some of these, such as methods in java.lang.Class , we will look at below.

9.6.3 The Class Named Class

In one of the more strikingly beautiful aspects of the Java programming language, every object that you create has some knowledge of itself. This information is kept in an object of type Class .

The Class class is important because it aids in the loading of classes. One Class object is made available for each class loaded into the Java Virtual Machine. It holds objects for any Java class, interface, primitive wrappers, or any Java type.

This class does not have a constructor ”you only need to call the getClass() method for any instance, like this:

 System.out.println(someClass.getClass()); 

The following program demonstrates some of the methods made available by the Class class.

 package javaforcf.chp9;  public class TestClass  {      void printClassName(Object obj) {          System.out.println("The class of " + obj +              " is " +              obj.getClass().getName());      }      void printSuper(Object obj) {          System.out.println("The superclass is " +             obj.getClass().getSuperclass());      }      void printPackage(Object obj) {          System.out.println("The field is " +             obj.getClass().getPackage());      }      void printInterface(Object obj) {          System.out.println("Is this class an interface? " +              obj.getClass().isInterface());      }     public static void main(String [] arg) {       TestClass obj = new TestClass();       obj.printClassName(obj);       obj.printSuper(obj);       obj.printPackage(obj);       obj.printInterface(obj);     } } 

Running this program renders the following output:

 The class of javaforcf.chp9.TestClass@720eeb is  javaforcf.chp9.TestClass The superclass is class java.lang.Object The field is package javaforcf.chp9 Is this class an interface? false 

There is an aspect of the Class class that is often useful for Java developers, especially those wishing to connect to a database. This method is called forName() . The forName(String className) method of Class returns the Class object associated with the class or interface named in the parameter. This will make more sense when we get to the discussion of Java database connectivity; for now, it is just interesting to know that when you load a database driver to connect to a database, you're going to use Class.forName("driverNameString") to do it. For example, here is the string used to load a particular driver to use with the MySQL database:

 // load driver              Class.forName("org.gjt.mm.mysql.Driver"); 

You'll notice that the string we're passing is the qualified package name . Think back to ColdFusion 5 when the ability to specify a connect string was added. This gave ColdFusion developers the ability to specify different attributes to be sent along to the database to be used in creating the connection. To get to a database in Java, we have to do a similar deal. But we must also explicitly load the driver. We're used to the ColdFusion Administrator handling that for us when we create a datasource; but using Class.forName("myDriver") is how we do it in Java: it's an object like everything else.

9.6.4 The Class Named Object and clone()

Every object in Java inherits from java.lang.Object . Because every class extends Object , a variable that is of type Object can refer to any object. For the same reason, a number of useful methods are made available by Object .

There are two general categories of methods in Object : utility methods and methods that support threads. Threads are discussed in a later chapter, so for now we will just glance at the more common utility methods.

 public boolean equals(Object o) 

This method indicates whether another object is equal to this one and checks for equality of the values. So given a value x, x.equals(x) will return true . For any reference values, equals() returns true if and only if the two values refer to the same object. The String class overrides the equals method to return true if the two compared strings have the same contents.

 protected Object clone() throws CloneNotSupportedError 

The clone() method returns a clone of this object. A clone is a new object that is a copy of the object on which the method was invoked. Using the clone() method on an object copies not only the structure of an object but its current values at the time it was invoked.

 protected void finalize() throws Throwable 

When the garbage collector has determined that there are no more references to this object, it calls the object's finalize method to destroy it.

 public final Class getClass() 

returns the object's runtime class.

 public toString() 

returns a string representing the object. Whenever you concatenate strings using the + operator, the toString() method is invoked implicitly.

The remainder of the methods in Object relate to threads, which we will look at later. The methods relating to threads in the Object class are all declared final . They can, and often should, be overriden.

The following example simply puts some of the methods of the java.lang.Object package to work. It also incorporates some of the techniques we've learned in the last couple of chapters, including exception handling and interface implementation. We will also override the toString() method of Object .

Specifically, the clone() interface allows us to duplicate objects. In order to clone an object, you need to do two things: override the clone() method made available by Object and implement the Cloneable interface, which is empty.

9.6.5 TestObject.java

 package javaforcf.chp9;  public class TestObject implements Cloneable  {       int i;       int j;       String s = "Hello, ";     // throw the required exception   public Object clone() throws CloneNotSupportedException {       return super.clone();   }     // override toString method   public String toString() {        return s + i + " and " + j;   } public static void main(String [] arg) {   TestObject original = new TestObject();     original.i = 8;     original.j = 7;     try {         // clone the object       Object aClone = original.clone();         // show the properties using our toString         // method which will automatically get called         // prove that the clone and the original have the same         // data         // and same method available to them       System.out.println(original);       System.out.println(aClone);   // get the value of the field   // prints 8   //System.out.println(original.i);   // prints: class javaforcf.chp9.TestObject   // same for calling getClass() on the clone   System.out.println(original.getClass());     // are they really of the same class?     // prints true   System.out.println(  aClone.getClass() ==        original.getClass());   // what is the hashcode for this object?   // returns something like 7474923   System.out.println(aClone.hashCode());     }     catch (CloneNotSupportedException cnse) {           System.out.println(cnse);     } } } 

Running this program produces an output such as this:

 Hello, 8 and 7  Hello, 8 and 7 class javaforcf.chp9.TestObject true 3242435 

An empty interface is one that defines no methods or variables; it just indicates that the class that implements it can be cloned. Trying to invoke clone() on an object that doesn't implement this interface causes the CloneNotSupported exception to be thrown. If you remove the " implements Cloneable " statement from the class definition and recompile it, you'll see the exception we've caught:

 java.lang.CloneNotSupportedException:  javaforcf.chp9.TestObject 

   
Top


Java for ColdFusion Developers
Java for ColdFusion Developers
ISBN: 0130461806
EAN: 2147483647
Year: 2005
Pages: 206
Authors: Eben Hewitt

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net