Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Java Generic Code - Power Of Reflection

0.00/5 (No votes)
30 Sep 2004 1  
Java's Reflection enables programs to automatically flesh out simple interfaces to create automated data objects

Introduction

Whenever there is an application to write, breaking it up to small pieces is a great idea. The smallest piece of any application would probably be a data object, or a simple Bean in Java. Java Beans are simple Java classes that have a distinctive look and behavior. Their simplest purpose is to contain data and they accomplish this by having properties. Each property is actually a data-member containing/referencing the actual data and a couple of methods, a getter method and a setter method. Thus, the simplest data-bean describing a person could be expressed as such:

public interface Person {
  // Getter method for FirstName property..
  public String getFirstName();
  // Setter method for FirstName property..
  public void setFirstName(String name);
  // Getter method for LastName property..
  public String getLastName();
  // Setter method for LastName property..
  public void setLastName(String name);
  // Getter method for Age property..
  public int getAge();
  // Setter method for Age property..
  public void setAge(int age);
}

Your first response could probably be, "where are the data-members?", or "why did you use an interface and not a class?" and you would be perfectly right in asking either one of those two important questions. The whole idea of breaking things down to small pieces is to create an API that need not be changed after it is agreed upon by all parties involved in the design and development of the code. Only then, should we generate code to support and use such APIs. However, during that first stage when APIs are developed, sometimes you need to add a property, change a property or maybe introduce a whole new Bean into the system. Testing your APIs is impossible if your Beans don't actually support their properties, so you have to actually implement some sort of a basic bean, or the Data-Bean as I call it.

In this article, I will make use of Java's Reflection to handle the automation of Data-Beans without writing more code than the previously mentioned interface or more like it.

Background

The code in this article uses the Arguments class I have described in an earlier article titled: "Java Generic Code - Reflection, the Easy Way", and although the Arguments class is included in the supplied source, I would advise you to read my article about Reflection just so that my DataBeanProxy class will be easier to understand.

How the Code is Organized

Simply run the dev.easyref.tester.DemoApplication class or double click on the JAR file supplied. The class structure is as follows:

Package Source File Purpose
dev.easyref.tester DemoApplication The demo's main class.
dev.easyref.data Person A simple data bean interface describing a Person's properties.
Employee An extension to the Person interface adding the Salary property.
User An extension to the Employee interface adding the Password property.
dev.easyref.util Arguments A utility class used to perform all the Reflection work.
DataBean An interface describing basic methods a Data-Bean will need.
DataBeanProxy An extension of the Arguments class that automatically provides code to support Data-Bean properties.

How Things Work

Let's examine the main method of DemoApplication:

01  public static void main(String[] args) {
02    ArrayList list = new ArrayList();
03    // Create 3 users..
04    addUser(list, "WOOGA", 1500.0f, 25, "Ruth", "Barak");
05    addUser(list, "TESTER", 2000.0f, 40, "Odded", "Barak");
06    addUser(list, "BOOGA", 3000.0f, 35, "Doron", "Barak");
07    // Sort the list by the FirstName..
08    Collections.sort(list, new Comparator() {
09      public int compare(Object o1, Object o2) {
10        String s1 = ((User)o1).getFirstName();
11        String s2 = ((User)o2).getFirstName();
12        return s1.compareTo(s2);
13      }
14    });
15    // Print out the list..
16    System.out.println(list);
17  }

We can see that the interesting part is between lines 4 to 6, where three User instances are created. Looking at the addUser(...) method clears up things a little:

01  public static void addUser(Collection list, String psswd, 
    float salary, int age, String firstName, String lastName) {
02    // Create a User DataBeanProxy object..
03    User user = (User)DataBeanProxy.newDataBean(User.class);
04    // Set the properties..
05    user.setAge(age);
06    user.setSalary(salary);
07    user.setPassword(psswd);
08    user.setLastName(lastName);
09    user.setFirstName(firstName);
10    // Add the User instance to the list..
11    list.add(user);
12  }

The important bit here is line 3 where the DataBeanProxy class is used as a Factory to create a User instance. The newly created instance does implement the User interface but to find out how, and where the data-properties are kept, you'll have to peek under the hood of the DataBeanProxy class.

In Conclusion

Hopefully this article helps in realizing the power of Reflection and also how Reflection -- although arguably breaks OOP methodologies -- can be useful as an API building tool.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here