Java Understanding Properties in Java and C#

Understanding Properties in Java and C#

Java Programming Notes # 2100


Preface

Six parts to this tutorial

This is a long and technically complex tutorial lesson.  Therefore, I have
broken it into six parts.  You should be able to finish reading each part in one
sitting.

Part 1 explains properties in general, based on a real-world scenario with which
we are all familiar.

Part 2 provides a detailed explanation of Java properties including:

  • Simple and indexed properties.
  • Bound and constrained properties.
  • Introspection based on design patterns and low-level reflection.
  • Introspection based on explicit BeanInfo information.

Part 3 explains C# properties from the viewpoint of the general user, and
compares C# properties at that level with Java properties.

Part 4 explains C# properties from the viewpoint of the sophisticated user
(based on reflection) and compares C# properties at that level with Java
properties.

Part 5 provides a summary of the entire tutorial lesson.

Part 6 contains complete program listings for several Java and C# programs used
for illustration elsewhere in the lesson.

Viewing tip

You may find it useful to open another copy of this lesson in a separate
browser window.  That will make it easier for you to scroll back and
forth among the different listings and figures while you are reading about
them.

Supplementary material

I recommend that you also study the other lessons in my extensive collection
of online Java tutorials.  You will find those lessons published at
Gamelan.com
However, as of the date of this writing, Gamelan doesn’t maintain a consolidated
index of my Java tutorial lessons, and sometimes they are difficult to
locate there.  You will find a consolidated index at
www.DickBaldwin.com.


Part 1, Properties in General

What is a traffic light?

This question may appear to be trivial at first glance.  However, this
is not a trivial question.  How would you explain a traffic light to an
alien from outer space who has never seen a transportation system like we have
on Earth?

Assume that the alien has never seen an automobile, a street, an
intersection, a traffic jam, or any of the other things that we commonly
associate with the flow of traffic.  Providing an explanation of a traffic
light to our alien friend would not be easy. 

What is a property?

Explaining what a property is can be equally difficult.  Before you can
explain how you implement a property, you need to be able to explain what it is
that you are implementing.

Two blocks past the red light …

In the small town where I grew up, the traffic lights were commonly referred
to as "red lights."  Someone might make a statement similar to
"My house is on the corner of the third street past the red light."

Obviously describing a traffic light as a red light is inadequate. 
A traffic light is red only part of the time.  It is also green part of the
time and amber part of the time.  So, we need a better explanation
that that.

Light sources and colors

Let’s assume that our alien friend does understand the concepts of light
sources and colors.  For brevity, we will refer to light sources simply as
lights.

We might describe a traffic light as a group of lights, always
including red, green, and amber, which are used for a specific purpose. 
However, that would also be an inadequate description.  In every town,
there are many groups of lights that may include red, green, and amber, which
are not traffic lights.  Rather, those groups of lights may be used for a
variety of purposes, such as advertising or simple illumination.

Must be uniquely identifiable

Therefore, our explanation of a traffic light would need to be much more
specific that that.  When you drive, it is very important that you are able
to identify the traffic lights.  Therefore, very important to our
explanation would be the information that makes it possible to always identify
traffic lights as such, and to separate them from the many other groups of
colored lights that we see when we look around.

An array of lights

For example, we might say that a traffic light is always an array of three or
more lights arranged in a horizontal or vertical line.  We might explain
that in the case of the horizontal arrangement, the red light is always on the left,
and the green light is always on the right.  (At least that appears to
be the case based on observation.)

We might explain that traffic lights are always located in specific positions
relative to the geometry of the intersection.  We would probably need to
describe other unique characteristics of traffic lights before our alien friend
could learn to always recognize them as such.  Hopefully, by describing
enough of the characteristics of traffic lights, we could teach our alien
friend to always recognize one when she sees one.  As you can see, however,
explaining a traffic light to our alien friend would not be an easy task.

When is a traffic light really a traffic light?

The bottom line to this discussion, however, is that a traffic light is
really a traffic light only when drivers recognize it as such.  If everyone
in town were to suddenly forget how to recognize traffic lights, they would
change from being traffic lights to being big ugly boxes with lights blinking in them. 
Chaos would reign, and there would be lots of collisions at the intersections.

Similarly, I’m going to tell you later that a property is really a property only
when other programs recognize it as such.  If other properly-written programs can’t recognize a
property, then it is not a property after all.  It is simply another value among many values contained in a program.

What is a property?

Explaining a property is just about as difficult as explaining a traffic
light.

As in the case of a traffic light, we could begin by saying that it
should always be possible for a programmer or another program to recognize a property
as being a property.  Therefore, a property must have some attribute that
makes it instantly recognizable as such and distinguishable from other values
that are not properties.

The purpose of a property

Beyond this, we might say that a property is a value that is used for
specific purposes, although the purpose of using a property in one program may
be different from the purpose of using a property in another program.

(In this sense, a property is more complex than a traffic light, which
usually has only one overall purpose (to control the flow of traffic)
regardless of the observer.)

Objects may have properties

We could explain that objects may have properties, and in most cases, a
property is a value that is stored in, or accessible by way of, a member
variable belonging to the object.  However, this is not true in all cases. 
It is perfectly legal for a property value to be generated on-the-fly when it is
requested.  It is not absolutely necessary for the property value to be
stored in a member variable of the object.

Limit properties to member variables

Even if we were to impose the (artificial) limitation that properties must be stored in
member variables, we would still have problems with our explanation.  Just
as a city can have many red, green, and amber lights that are not traffic
lights (particularly when the Christmas decorations are up), an object can encapsulate many member variables that are not properties. 
Therefore, under this limitation, we might say that the value of a property is
stored in a member variable, but a value stored in a member variable is not
necessarily a property.

Can you recognize a property?

In the case of traffic lights, we can say that because of the convergence of
many visual patterns, most people who see a traffic light will have learned to
recognize it as a traffic light.  Similarly, we can say that most
programmers and programs that have learned the rules for recognizing properties
will recognize a property when they see one.  However, the recognition
methodology is different in Java and C#, (and such recognition is somewhat easier
in Java than in C#.)

When is a property really a property?

A property is really a property only when other programs recognize it as such. 
If a program can’t recognize a property, then it is simply a value among many
values contained in a program.

Why should I care?

It is my belief that most people who plan to make a living as computer
programmers during the next ten years will need to be proficient in both Java
and C#, particularly if they ever plan to change jobs.

The platform independent marketplace

Java is already well established as the de facto standard programming
language for computer programs that need a wide degree of platform independence. 
I don’t see that changing in the foreseeable future.

The Windows programming marketplace

Although C# hasn’t really taken off as of the Spring of 2003, this new
language, along with VB.NET, in conjunction with MS.NET, appears to be the
programming vehicle that Microsoft will promote heavily for programs that run on Windows
platforms.  I believe that to some extent the slowdown in the economy has slowed down the acceptance of MS.NET,
C#, and VB.NET.

Will MS.NET be successful?

Will MS.NET be successful in the marketplace?  Let me simply say that
Bill Gates has had few (if any) failures in the marketplace since I first
heard his name back around 1981 when I was using a VisiCalc spreadsheet on a
TRS-80 computer that I purchased from Radio Shack.  I bought my first IBM
personal computer running Gate’s operating system around that time and the rest
is history.  I don’t believe that MS.NET, C#, and VB.NET will fail in the
marketplace.  I believe that they will succeed and really take off as soon
as the high-tech economy recovers from its current slump.

And you need to be ready when that happens.

The good news

The good news is that Java and C# are very similar.  If you understand
Java, it is easy to learn and understand C#.  If you understand C#, it is
very easy to learn and understand Java.

The bad news

The bad news is that Java and C# are not identical.  There are a few
areas where they are significantly different, and the implementation of
properties is one of those areas.  Therefore, in order to be proficient in
both languages, you will need to understand the differences in the way that
properties are implemented in each of the two languages.

In order to be proficient in both languages, you will also need to understand
the implementation differences in some other areas as well, such as event
handling and arrays.  I hope to be able to find the time to publish
additional lessons that explain the other significant differences between Java
and C# in the future.

Why do we need properties?

Different authors will provide different reasons for the need for
properties to exist.  For example, some authors will tell you that
properties are needed to support a concept known as information hiding. 
I personally disagree with that assessment.  While information hiding
is a very important design goal, there are much easier ways
to accomplish information hiding than through the mechanism of properties.

Some programs need to identify properties

My explanation is that some programs need to be able to positively identify
and possibly modify a specific set of values associated with an object. 
One way to make that happen is to cause those values to become properties of the
object, and to cause the program to recognize them as properties.

Property editors

The most familiar example of the use of properties is the case of high-level IDEs, such as Microsoft’s
Visual Studio.net.  (For brevity, I will refer to Visual Studio.net
simply as MSVS during the remainder of this lesson.)
  For example, when you drag a Button
object onto a Form object in MSVS, (while in C# designer mode),
and select the button with your mouse, a Properties Window, similar to
that shown in Figure 1 opens. 

Figure 1 MSVS Property Window

The property window lists more than forty different properties associated with the Button
object, along with their default values.

The list includes properties with names like Location, Size, BackColor, and
ForeColor, and each of the properties has a default value.

Purpose of a property editor

The values for each of the properties will either be stored in member variables of the Button object
at runtime, or

generated on-the-fly based on values stored in other member variables. 
The purpose of the property editor is to allow the programmer to modify the default property values
at design time so that the Button object
will look and behave more to the programmer’s liking when the program starts
running than would otherwise be the
case.

The ability to recognize properties is a critical feature of MSVS and other
similar software development environments.

Member values that are not properties

Although I have never looked at the source code for the Button class,
my guess is that there are numerous other values stored in member variables of the
Button
class that are not recognized by MSVS as properties. 
For example, this might include values that control those aspects of the three-dimensional
appearance of the button that cannot be modified by the programmer at design
time.

The FlatStyle property

The FlatStyle property of a C# button, as created by MSVS, can have
any of the following four values:

  • Flat
  • Popup
  • Standard
  • System

The appearance and behavior of the button is somewhat different, depending on
the value of the FlatStyle property.

A Standard button

For
example, the default appearance of a Standard button is to protrude from
the screen.  The behavior of the button is to appear to be pressed into the
screen when you point to it with the mouse pointer and press the left button on
the mouse.

An optical illusion

This appearance is the result of an optical illusion produced by
highlighting the left and top of the button and placing a shadow on the right
and bottom of the button when it is in the default position (see Figure 2).  The
highlighted portion appears to be a lighter color than the background color of the
button, and the shaded portion appears to be a darker color than the background
color.

Figure 2 A C# form with buttons of different colors

I may be wrong, but I don’t believe that the programmer has independent control over
the difference in colors between the highlighted portion and the background
color.  The programmer has control only over the background color through a
property named BackColor.  Different buttons on a form can have different background
and highlight colors as shown in Figure 2.

The main point

The background color is a property named BackColor.  However, the information that makes
it possible to create the corresponding highlight color is not recognized as a
property.  This information may be generated on the fly when needed, or may
be stored in a member variable of the button that is not recognized as a
property.  As I mentioned earlier, there are probably many other values
stored in member variables of a Button that also are not recognized as
properties.

An automatic code generator

MSVS is a program whose primary purpose is to generate code automatically. 
The use of a code generator like MSVS can greatly reduce the programming effort
required of the programmer.

When operated in designer mode, the MSVS has the
ability to write the code required to instantiate the buttons and to place them
on the form at runtime.  While in designer mode, the program must have the
ability to recognize those values that are to be treated as properties and to
expose them to the programmer for editing.  Therefore, the program
must have, and does have the ability to tell the difference between member
values of the class that are to be treated as properties and member values of
the class that are not to be treated as properties.

A more subtle use of properties

A somewhat more subtle use of properties is illustrated by the code in the
lessons entitled JavaServer Pages and JavaBeans Components, Parts I, II, and
III.
 You will find these lessons published as lessons number 762, 764,
and 766 on my Web Site.

For example, lesson 766 explains the use of the
jsp:getProperty tag when creating Java Server Pages.  The JSP
engine knows how recognize the properties belonging to a JavaBeans component when it encounters
this tag in the JSP code.  Thus, this tag, in conjunction with the JSP
engine, makes it possible to get and use
a property value of a JavaBeans component when creating Java Server Pages for
whatever purpose that property value may be needed.

Different approaches

While both Java and C# make use of properties for similar reasons, the
approach to the creation and recognition of properties is handled much
differently in Java and C#.  You will need to understand those differences
to be proficient in both languages.  This lesson will explain those
differences.

Part 2, Properties in
Java, Detailed Explanation

What is a JavaBeans component?

According to Sun,

"The goal of the JavaBeans APIs is to define
a
software component model for Java,
so that third party ISVs can create and ship Java components that can be
composed together into applications by end users.
"

In other words, the JavaBeans component model is the standard software
component model for Java.

Serialization or Externalization

Without getting into the details as to why, I will tell you that
all beans must support either Serialization or
Externalization.  To qualify as a JavaBeans component, a class must
implement either the Serializable interface or the Externalizable
interface.  Thus, the JavaBeans component classes that I will present in
this lesson will implement the Serializable interface.

(If you are familiar with the Serializable
interface, you already know that nothing is required to implement the interface
other than to declare that it is implemented by the class.  There are no
declared methods in the interface that must be defined in your class.)

The Java Introspector

In order for a Java property to be a property, it must be recognized as such by
the Java Introspector.  According to Sun,

"The Introspector class provides a standard way for tools to learn about
the properties, events, and methods supported by a target Java Bean."

In this part of the lesson, I will show you how to use the Introspector class to
discover and display information about the properties, events, and methods
for three simple bean classes.

Continuing with Sun’s explanation,

"For each of those three kinds of information, the Introspector will
separately analyze the bean’s class and superclasses looking for either
explicit or implicit information and use that information to build a
BeanInfo
object that comprehensively describes the target bean."

What is a BeanInfo object?

BeanInfo is an interface.  An object of a class that implements
the BeanInfo interface is a BeanInfo object.  Such an object
encapsulates information about the properties, events, and methods of the Java
Bean that it describes.  Sun goes on to say,

"For each class "Foo", explicit information may be available if there
exists a corresponding "FooBeanInfo" class that provides a non-null value when
queried for the information."

Will provide BeanInfo for one bean class

I will provide a class that implements the BeanInfo interface for one
of the three bean classes that I will discuss in this lesson.

Continuing with Sun’s description,

"If we don’t find explicit BeanInfo on a class, we use low-level
reflection to study the methods of the class and apply standard design
patterns to identify property accessors, event sources, or public methods."

Two ways to make a bean’s properties recognizable

Thus, the author of a Java Bean class can make the properties recognizable in
either of two ways:

  • Provide an auxiliary class that implements the BeanInfo interface
    to identify and provide information about the properties.
  • Rely on low-level reflection based on standard Java design patterns.

Two of the bean classes that I will discuss in this lesson will depend on
low-level reflection for introspection.  I will define a class that
implements the BeanInfo interface for the third bean class.

Simple and indexed properties

Java properties come in two varieties, simple and indexed.  A simple
property is a single-valued property.  An indexed property is a property
that may consist of more than one value where the individual values are accessed
via a numeric index.

I will illustrate both simple and indexed properties in this lesson.

Bound properties

Whether simple or indexed, a property may also be a bound property. 
According to Sun,

"A component can choose to provide a change
notification service for some or all of its properties.  Such properties
are commonly known as
bound
properties, as they allow other components to bind special behavior to property
changes.
"

The enabled property

One of the best examples of bound properties that I can think of is the
relationship that exists between menu items and corresponding buttons on a
button bar.  Many graphical user interfaces provide several buttons, each
of which is tied specifically to an item on a menu.  Pressing the button or
selecting the corresponding menu item always produces the same result.

(For example, the Back button on the Internet Explorer browser corresponds
to a selection on the View menu.)

Synchronization is critical

It is critical that a button on the button bar and the corresponding menu
item track one another in terms of being enabled or disabled.

In Java, menu items and buttons on a button bar have an enabled
property, which is either true or false.  When you create a button bar and
associate the buttons with menu items, you can set things up so that a change in
the value of the enabled property on one will cause the other to be notified of
the change.  This mechanism can be used to assure that the button and the
corresponding menu item track one another in terms of being enabled or disabled. 
I discuss this scenario in detail in the lesson entitled
Understanding
Action Objects in Java
.

One of the bean classes that I will discuss in this lesson has a bound
property.  I will use that example to explain how to create and service
bound properties.

Constrained properties

Whether simple or indexed, a property may also be a constrained
property.  According to Sun,

"Sometimes when a property change occurs some
other bean may wish to validate the change and reject it if it is inappropriate. 
We refer to properties that undergo this kind of checking as

constrained properties."

The control logic required to support constrained properties is somewhat more
complex than that required to support bound properties.  This lesson does
not provide sample code to support constrained properties.

Enough talk, let’s see some code

I will begin by discussing the program named PropertyDisplay01, which
is used in this part of the lesson to display information about the properties, events, and
methods belonging to a JavaBeans component.

As usual, I will discuss the program in fragments.  A complete listing
of the program is provided in Listing J33 near the end of the lesson.

The display method

This program consists of a single static method named display
To display information about a bean, invoke the display method passing
the name of the JavaBeans component class as a String parameter.

The beginning of the class definition and the beginning of the method named
display is shown in Listing J1.

public class PropertyDisplay01{

  public static void display(String beanClass)
                                throws Exception{

    Class myBeanClassObject = Class.forName(
                                      beanClass);

Listing J1

Get a Class object that describes the bean class

The code in Listing J1 shows the incoming String parameter known
locally by the parameter name beanClass.

A little later, we will invoke the static method of the Introspector
class named getBeanInfo.  At that time, we will need a Class
object that describes the target bean class.  The code in Listing J1
creates such a Class object.  The static forName method of
the class named Class returns a reference to such a Class
object, given the name of the target bean class as a String parameter.

Get a BeanInfo object that describes the bean
class

Given the Class object that describes the bean’s class, the code in
Listing J2 uses the static getBeanInfo method of the Introspector class to obtain
a BeanInfo object containing information about the class of the bean. 
The BeanInfo object’s reference is saved in the reference variable
named beanInfo.

    BeanInfo beanInfo = Introspector.getBeanInfo(
              myBeanClassObject,
              myBeanClassObject.getSuperclass());

Listing J2

According to Sun, the getBeanInfo method

"will separately analyze the bean’s class and superclasses looking for
either explicit or implicit information and use that information to build a
BeanInfo object that comprehensively describes the target bean."

Behavior of the getBeanInfo method

There are several overloaded versions of the getBeanInfo method. 
The version used in Listing J2 takes two parameters.  The first parameter
is a reference to a Class object describing the bean class.  The
second parameter is a Class object describing a stopClass. 
Paraphrasing Sun, the stopClass is the superclass at which to stop the
analysis.  Any methods, properties, or events in the stopClass or its
superclasses will be ignored in the analysis.

In Listing J2, the stopClass is the immediate superclass of the target bean
class.  Therefore, the BeanInfo object produced by the code in
Listing J2 will contain information about the bean class, but will not contain
information about any of its superclasses.

Get a BeanDescriptor object

From this point forward, all information about the bean and its properties will
be obtained by performing various manipulations on the BeanInfo
object.  We begin by invoking the getBeanDescriptor method on the
BeanInfo object to get and process a BeanDescriptor object, as
shown in Listing J3.

    BeanDescriptor beanDescriptor =
                    beanInfo.getBeanDescriptor();
    System.out.println("Name of bean:  " +
                       beanDescriptor.getName());
    System.out.println("Class of bean: " +
                  beanDescriptor.getBeanClass());

Listing J3

What is a BeanDescriptor object?

According to Sun,

"A BeanDescriptor provides global information about a "bean", including
its Java class, its displayName, etc.  This is one of the kinds of
descriptors returned by a BeanInfo object, which also returns descriptors for
properties, methods, and events."

Having obtained the BeanDescriptor object, the code in Listing J3
invokes appropriate methods on the object to get and display the name and the
class of the target bean.  As an example, the code in Listing J3 produced
the following screen output for one of the beans that will be discussed later
in this lesson.

Name of bean:  Prop02BeanX
Class of bean: class Prop02BeanX

Get and display exposed methods

A bean is said to expose all of its public methods.  According to
Sun,

"A MethodDescriptor describes a particular method that a Java Bean
supports for external access from other components."

Thus, each of the methods exposed by a bean is described by an object of the
type MethodDescriptor.  The code in Listing J4 invokes the
getMethodDescriptors
method on the BeanInfo object to get an array of
MethodDescriptor objects, where each object in the array describes one of
the exposed methods.

    MethodDescriptor[] methodDescriptor =
                 beanInfo.getMethodDescriptors();

    for (int i=0;i < methodDescriptor.length;
                                            i++){
        System.out.println(
                  methodDescriptor[i].getName());
    }//end for-loop

Listing J4

The names of the exposed methods

Several kinds of information about an exposed method are contained in the
corresponding MethodDescriptor object.  The code in Listing J4
iterates on the array to get and display the name of each method exposed by
the bean.  For example, the code in Listing J4 produced the following
list of exposed method names for one of the beans that will be discussed later in this
lesson.

fetchSize
getColor
getData
putSize
setColor
setData

A PropertyDescriptor object

According to Sun,

"A PropertyDescriptor describes one property that a Java Bean exports
via a pair of accessor methods."

The code in Listing J5 invokes the getPropertyDescriptors method on
the BeanInfo object to get an array of PropertyDescriptor
objects, where each object in the array describes one of the properties of
the target bean.

    PropertyDescriptor[] propertyDescriptor =
               beanInfo.getPropertyDescriptors();

    for (int i=0; i < propertyDescriptor.length;
                                           i++) {
      System.out.println("Name: " +
                propertyDescriptor[i].getName());
      System.out.println(" Type:       " +
        propertyDescriptor[i].getPropertyType());

      System.out.println(" Get method: " +
          propertyDescriptor[i].getReadMethod());
      System.out.println(" Set method: " +
         propertyDescriptor[i].getWriteMethod());

      System.out.println(" Bound: " +
                propertyDescriptor[i].isBound());
      System.out.println(" Constrained: " +
          propertyDescriptor[i].isConstrained());
    }//end for-loop

Listing J5

Property name and type

Then the code in Listing J5 iterates on the array to get and display
various attributes of each property.

Every Java property has a name and a type.  These attributes are
obtained and displayed by invoking the appropriate methods on each
PropertyDescriptor
object in Listing J5.

Property accessor methods

Every Java property may have a read method, a write method, or both. 
(Java jargon often refers to these methods as setter and getter methods,
or accessor methods.)

The code in Listing J5 invokes the appropriate methods to get and display
information about the accessor methods.

Bound and constrained properties

Earlier in this lesson, I discussed bound and constrained properties. 
The final two statements in Listing J5 get and display whether or not each
property is bound or constrained (I will have more to say about this
later).

The screen output for a bean

The code in Listing J5 produced the following screen output
for one of the beans that will be discussed later in this lesson.  This
particular bean had two properties, one named color and the other
named data.

Name: color
 Type:       class java.awt.Color
 Get method: public java.awt.Color Prop02BeanX.
             getColor()
 Set method: public void Prop02BeanX.
             setColor(java.awt.Color)
 Bound: false
 Constrained: false
Name: data
 Type:       class [Ljava.lang.Integer;
 Get method: public java.lang.Integer[]
             Prop02BeanX.getData()
 Set method: public void Prop02BeanX.
             setData(java.lang.Integer[])
 Bound: false
 Constrained: false

An EventSetDescriptor

According to Sun,

"An EventSetDescriptor describes a group of events that a given Java
bean fires.  The given group of events are all delivered as method calls
on a single event listener interface, and an event listener object can be
registered via a call on a registration method supplied by the event source."

Event-driven programming in Java

One of the beans that I will discuss later has a bound property.  An
understanding of bound properties depends on an understanding of event-driven
programming in Java.  The overall topic of event-driven programming is
far too complex to cover in this lesson.  I have published numerous
tutorial lessons on event-driven programming on my
web site.

Because of the relationship between bound properties and event-driven
programming, I included the code in Listing J6 in this program for the purpose
of getting and displaying information about the events that a bean can fire.

    EventSetDescriptor[] eventSetDescriptor =
               beanInfo.getEventSetDescriptors();

    for (int i=0; i < eventSetDescriptor.length;
                                            i++){
      System.out.println("Event Name: " +
                eventSetDescriptor[i].getName());
      System.out.println(" Add Method:    " +
                         eventSetDescriptor[i].
                         getAddListenerMethod());
      System.out.println(" Remove Method: " +
                      eventSetDescriptor[i].
                      getRemoveListenerMethod());

      methodDescriptor = eventSetDescriptor[i].
                  getListenerMethodDescriptors();

      for (int j=0; j < methodDescriptor.length;
                                            j++){
          System.out.println(" Event Type: " +
                  methodDescriptor[j].getName());
      }//end for-loop
    }//end for-loop

Listing J6

Additional complexity in the code

The pattern for the code in Listing J6 is pretty-much the same as before,
but a little more complicated.  The additional complexity derives from
the fact that each type of event can have multiple listener methods. 
For example, an event of type WindowEvent has the following listener methods:

  • windowOpened
  • windowClosing
  • windowClosed
  • windowActivated
  • windowDeactivated
  • windowIconified
  • windowDeiconified

The getEventSetDescriptors method is invoked on the BeanInfo
object to get an array of EventSetDescriptor objects in Listing J6. 
Then nested for loops are used to iterate and display information
about each event that the bean can fire.  I will defer further
discussion of this topic until the discussion of the bean with a bound
property later in the lesson.

Analyze bean properties

Now that you understand how the introspection program that we will use to
analyze our beans works, we will begin analyzing the properties of several
beans.  We will analyze three separate beans.  Each of the beans
will illustrate some important characteristics of properties in Java.

The bean class named Prop02BeanX

The class definition for the first bean class named Prop02BeanX begins in
Listing J7.

class Prop02BeanX implements Serializable{
  private String size = "Medium";
  private Color color = Color.RED;
  private Integer data[];

  public void setColor(Color color){
    this.color = color;
  }//end setColor

  public Color getColor(){
    return color;
  }//end getColor

Listing J7

Introspection was performed on this bean by invoking the following
statement in the main method of a test class named Prop02Test.

PropertyDisplay01.display(“Prop02BeanX”);

(Note that complete listings of all the programs used in this lesson
are shown near the end of the lesson.)

Exposed methods

Before getting into the details of the code in this bean class, let’s take
a look at the introspection output for the exposed methods of this bean:

fetchSize
getColor
getData
putSize
setColor
setData

This bean exposes six different public methods.  As you will see
later, the four methods shown in boldface in the above list match the
JavaBeans design
patterns for properties, and are thus recognized as properties by the
introspection process.  The other two methods do not match design
patterns, and therefore are not recognized as properties by the introspection
process.

Instance variables

Listing J7 begins by declaring three instance variables, two of which are used
to store the values of the two properties.

(Note that the names that I gave the instance variables match the names
of the properties.  However, that is not a requirement.  I did so
solely for convenience.  There is no connection between the name of a
property and the name of an instance variable used to store the property’s
value.)

Setter and getter methods for a simple property

The two methods shown in Listing J7 match the design patterns for a simple
property named color.

(To learn a lot more about the rules for property design patterns, see the
lessons on JavaBeans components, beginning with lesson number 500, on my
web site.)

An indexed property

The two methods shown in Listing J8 match the design patterns for an
indexed property named data.

  public void setData(Integer[] data){
    this.data = data;
  }//end setData

  public Integer[] getData(){
    return this.data;
  }//end getData

Listing J8

Ordinary accessor methods

The two methods shown in Listing J9 are accessor methods, which support the
design objective of information hiding.  Note, however, that they do not
match the design pattern for properties.

  public void putSize(String size){
    this.size = size;
  }//end putSize()

  public String fetchSize(){
    return size;
  }//end fetchSize()

Listing J9

Properties based on design patterns

I did not provide explicit BeanInfo information regarding
the properties for this bean.  (I will provide explicit information
for the third bean that I will discuss later.

Here is a repeat of a quotation from Sun that I provided earlier:

"If we don’t find explicit BeanInfo on a class, we use low-level
reflection to study the methods of the class and apply standard design
patterns to identify property accessors, event sources, or public methods."

Since I did not provide explicit BeanInfo information for this
bean, the introspection process identified two properties for this bean based
on low-level reflection and design patterns.  Here is the screen output for one of the properties. 
This output was produced when the introspection process was applied to this bean.
(Note that I manually inserted some line breaks to force the material to fit
in this narrow publication format.)

Name: color
 Type:       class java.awt.Color
 Get method: public java.awt.Color Prop02BeanX.
             getColor()
 Set method: public void Prop02BeanX.
             setColor(java.awt.Color)
 Bound: false
 Constrained: false

The name of the property

The reported name of the property is color.  Using low-level
reflection and design patterns, the name is derived from the names of the
setter and getter methods shown in Listing J7.

(There are some special rules regarding the case of the first character
in the property name, which you will find in the JavaBeans component lessons
on my web site.)

The type of the property

The type of the property, Color, is the same as the parameter and
return types of the setter and getter methods in Listing J7.

Get and Set methods

The description of the Get method and Set method in the output matches the
signatures of the getter and setter methods in Listing J7.

Neither bound nor constrained

I did not provide the code to establish this property as a bound property
or a constrained property.  (I will provide a bound property for the
second bean, which I will discuss later in this lesson.)
  Thus, the introspection
process reported this property to be neither bound nor constrained.

A simple property

A careful examination of the type of the property, as well as the
parameter type for the setter method and the return type for the getter
method indicates that this is a simple (single-valued) property.

An indexed property

As I indicated earlier, this bean also has an indexed property (shown
in Listing J8).
  The introspection output for the indexed property is
shown below.

Name: data
 Type:       class [Ljava.lang.Integer;
 Get method: public java.lang.Integer[]
             Prop02BeanX.getData()
 Set method: public void Prop02BeanX.
             setData(java.lang.Integer[])
 Bound: false
 Constrained: false

The property type

Although you may not be familiar with this nomenclature, the square
bracket shown in the description of the type indicates that the type of this
property is an array of type Integer.  This indicates that this
is an indexed property.

The fact that this is an indexed property is also indicated by the return
type of the Get method and the parameter type of the Set method in the
introspector output.  The introspector output indicates that the return
type of the Get method is a reference to an array object of type Integer
The output also indicates that the parameter type of the Set method is a
reference to an array object of type Integer.

Another indexed property design pattern

Although I didn’t illustrate it in this program, there is another design
pattern for indexed properties that supports setting and/or getting a single
value belonging to the property based on a numeric index.  Again, you
can read about that in the JavaBeans component lessons on my
web site.

A simple bound property

Now let’s take a look at the class definition for a bean that has one
simple bound property.  As before, we will analyze this bean using the
introspection program discussed earlier.

Before getting into the details of the class definition, lets examine a
list of exposed methods for this class, as identified by the introspection
process.

The ordinary accessor methods

As before, I did not provide explicit BeanInfo information for this
bean.  Therefore, the introspector based its output on low-level
reflection and design patterns.

As with the previous bean, the following two exposed methods did not match
the design patterns, and therefore, were not identified as properties.

fetchSize
putSize

The setter and getter methods

The introspection process based on low-level reflection and design
patterns identified the following two methods as the accessor methods for a
simple property named color.

setColor
getColor

Event registration methods

As discussed earlier in this lesson, a bound property has the ability to
register interested listeners, and to notify them whenever the value of the
property changes.  The simple property in this bean is a bound property. 
Therefore, the bean has the ability to fire events of type
PropertyChangeEvent
.

As a result, the bean exposes the following two event registration
methods, which were included in the list of exposed methods identified by the
introspection process.

addPropertyChangeListener
removePropertyChangeListener

The Prop02BeanY bean class definition

Now that you have seen the list of exposed methods, lets examine the class
definition for the bean class in fragments.  (A complete listing is
provided near the end of the lesson.)

The class definition for the class named Prop02BeanY begins in
Listing J10.

class Prop02BeanY implements Serializable{
  private String size = "Medium";
  private Color color = Color.RED;

  private PropertyChangeSupport changes =
                 new PropertyChangeSupport(this);

Listing J10

The class definition begins with the declaration of two rather
uninteresting instance variables named size and color
However, this is followed by a very interesting declaration of an instance
variable of type PropertyChangeSupport named changes.

Registration and notification

A bound property must have the ability to register interested listeners
and to notify them when the value of the property changes.  Obviously it
is possible to start from scratch and to write your own code to accomplish
those tasks.  However, the code required to accomplish those tasks is
far from trivial.

Fortunately, Sun has provided a helper class named
PropertyChangeSupport
, to relieve us of the requirement to write that code

The PropertyChangeSupport class

Here is part of what Sun has to say about the
PropertyChangeSupport
class.

"This is a utility class that can be used by beans that support bound
properties. You can use an instance of this class as a member field of your
bean and delegate various work to it."

Basically, an object of this class can be used to create and maintain a
registration list of interested listeners, and to notify those listeners of a
change in a property value when instructed to do so.  This can save you
a large amount of programming and testing effort.

Constructing the PropertyChangeSupport object

As of the Java SDK, v1.4.1, this class has only one constructor.  The
constructor requires one parameter of type Object, which, according to
Sun, is "The bean to be given as the source for any events."

As you can see in Listing J10, a new object of the PropertyChangeSupport
class is instantiated, passing a reference to the bean object as a parameter
to the constructor.  A reference to the PropertyChangeSupport
object is saved in the instance variable named changes.

PropertyChangeSupport methods

The PropertyChangeSupport class has about a dozen methods, of which
there are about six different overloaded method names.  We will be
interested in the three methods discussed below.

addPropertyChangeListener(
             
PropertyChangeListener listener)

This method adds a PropertyChangeListener to the registration list.
The listener is registered for all properties.  (A more selective
overloaded version of this method can be used to register a listener for a
specific individual property.)

removePropertyChangeListener(
             
PropertyChangeListener listener)

This method removes a PropertyChangeListener from the registration
list. This removes a PropertyChangeListener that was registered for all
properties.  Again, a different overloaded version is available to remove a
listener that was registered for a specific individual property.

firePropertyChange(String propertyName,
                  
Object oldValue,
                  
Object newValue)

According to Sun, this method reports a bound property update to any registered listeners. In
other words, this is the method that can be used to notify all registered
listeners of a change in a property value.  No event is fired if old value and
the new value are equal and non-null.

Method wrappers

The PropertyChangeSupport object’s reference, shown in Listing J10,
is held as a private instance variable of the bean class.  Therefore,
the registration methods of the PropertyChangeSupport object are not
directly accessible to listener objects that need to register.

The code in Listing J11 exposes a pair of public registration methods for
the bean class, and wraps those methods around calls to the registration methods of
the PropertyChangeSupport object.

(The registration methods exposed
by the bean class have identical signatures to the registration methods of
the PropertyChangeSupport
object.)

  public void addPropertyChangeListener(
                   PropertyChangeListener lstnr){
    changes.addPropertyChangeListener(lstnr);
  }//end addPropertyChangeListener

  public void removePropertyChangeListener(
                   PropertyChangeListener lstnr){
    changes.removePropertyChangeListener(lstnr);
  }//end removePropertyChangeListener

Listing J11

When a listener
object invokes one of the registration methods on an object of the bean
class, the action required to handle that registration is delegated to the
PropertyChangeSupport
object.

The setter method for the color property

Listing J12 shows the setter method for the property named color.

(The syntax of this setter method is a design pattern for a simple
property named color.)

  public void setColor(Color color){
    Color oldColor = this.color;
    this.color = color;
    changes.firePropertyChange(
                        "color",oldColor, color);
  }//end setColor

Listing J12

The code in Listing J12 begins by saving the current value of the color
property in a local variable named oldColor.  Then it stores
the new value of the property in the instance variable named color.

Firing a PropertyChangeEvent

Then the code in Listing J12 invokes the firePropertyChange method
on the PropertyChangeSupport object.  This causes all listener
objects registered on the PropertyChangeSupport
object to be notified of the change in the property value.  The
PropertyChangeSupport
object assumes responsibility for notifying the
registered listeners.  This relieves the bean programmer of having to
write the code to accomplish that task.

Several overloaded versions of the firePropertyChange method are
defined in the PropertyChangeSupport class.  Here is some of what
Sun has to say about the version that I elected to use in this program.

"Report a bound property update to any registered listeners. No event
is fired if old and new are equal and non-null."

The propertyChange method

All listeners registered on the PropertyChangeSupport object must
implement the PropertyChangeListener interface and must define the
propertyChange
method declared in that interface. 

Each registered
listener is notified of the change in property value by invoking its propertyChange method and passing
a PropertyChangeEvent object’s reference as a parameter.  As we
will see later, methods of the PropertyChangeEvent object can be used
to extract the name of the property, the old property value, and the new
property value.

Remaining code in the bean class

The remaining code in the bean class named Prop02BeanY is shown in
Listing J13.

  public Color getColor(){
    //This is a property based on design
    // patterns
    return color;
  }//end getColor

  public void putSize(String size){
    //This is not a property based on
    // design patterns
    this.size = size;
  }//end putSize()

  public String fetchSize(){
    //This would not be a property based on
    // design patterns
    return size;
  }//end fetchSize()

}//end class Prop02BeanY

Listing J13

This is essentially the same as the code that you saw before.  The
first method in Listing J13, named getColor, is the design-pattern getter method for
the property named color.

The remaining two methods do not meet the syntax requirements for design patterns. 
Therefore, an analysis of the properties of the bean using introspection
based on low-level reflection would identify only one property for this bean
class.  That property would be named color.

Performing introspection

Introspection was performed on this bean by invoking the following
statement in the main method of a test class named Prop02Test.

PropertyDisplay01.display(“Prop02BeanY”);

Exposed methods

The exposed methods identified by the introspection process were:

setColor
getColor
fetchSize
putSize
addPropertyChangeListener
removePropertyChangeListener

As discussed earlier, the first two methods in the above list are the setter and
getter methods for the property named color.  The last two
methods in the list are the registration methods for property-change
listeners.  The two methods in the middle are simply public methods.

Properties

The introspection process produced the following information for
properties:

Name: color
 Type:       class java.awt.Color
 Get method: public java.awt.Color Prop02BeanY.
             getColor()
 Set method: public void Prop02BeanY.
             setColor(java.awt.Color)
 Bound: true
 Constrained: false

This bean class did not provide explicit information for properties,
events, and methods.  Hence, the introspection process identified one simple bound
property named color.  That property was not constrained. 
The getter and setter methods match the design-pattern syntax for a simple
property.

Events

Here is something that we haven’t seen previously in this lesson.  Because the property
is bound, the bean has the ability to register and notify a collection of
interested listeners of changes in the value of the property named color
The output produced by the introspection process follows:

Event Name: propertyChange
 Add Method:   public void Prop02BeanY.
               addPropertyChangeListener(
               java.beans.PropertyChangeListener)
 Remove Method:public void Prop02BeanY.
               removePropertyChangeListener(
               java.beans.PropertyChangeListener)
 Event Type: propertyChange

The above information regarding events should be self-explanatory based on the earlier
discussion.

Exercise the bean

In addition to analyzing the bean using introspection, the code in the
main
method of a test class named Prop02Test also exercises the
behavior of the bean insofar as the bound property is concerned.  The
following code is executed in the main method:

Prop02BeanY aProp02BeanY = new Prop02BeanY();
aProp02BeanY.addPropertyChangeListener(
                           new PropListener());
aProp02BeanY.setColor(Color.BLUE);
aProp02BeanY.setColor(Color.GREEN);

As you can see, the above code instantiates a new object of the bean class
and registers a listener object on the bean object.  (The listener
object is instantiated anonymously from the class named PropListener.)

Then the above code invokes the setter method to change the property value
from its default value (RED) to BLUE.  Following that, it invokes
the setter method again to change the property value from BLUE to GREEN.  As we
will see shortly, each of these changes produces a PropertyChange
event.

The PropListener class

Before examining the output produced by the above code, let’s examine the
class definition for the class named PropListener, from which the
listener object was instantiated.

The entire class definition is shown in Listing J14.

class PropListener implements
                          PropertyChangeListener{
  public void propertyChange(
                        PropertyChangeEvent evt){
    System.out.println("PropertyChangeEvent");
    System.out.println(" Property Name: "
                        + evt.getPropertyName());
    System.out.println(" Old Value: "
                            + evt.getOldValue());
    System.out.println(" New Value: "
                            + evt.getNewValue());
  }//end propertyChange
}//end PropListener

Listing J14

If you are familiar with event-driven programming in Java, this class
definition should look pretty much like what you would expect.

The PropertyChangeListener interface

To begin with, the class implements the PropertyChangeListener
interface.  Thus, objects instantiated from the class can be treated as
type PropertyChangeListener.  This makes them eligible for
being registered on a PropertyChangeSupport object.

(The addPropertyChangeListener registration method of the
PropertyChangeSupport
class will only accept incoming parameters of type
PropertyChangeListener.)

The propertyChange method

The PropertyChangeListener interface declares a single method named
propertyChange, which receives an incoming parameter of type
PropertyChangeEvent
.

The PropertyChangeEvent class

As of SDK version 1.4.1, the PropertyChangeEvent class defines five
methods that can be invoked on the incoming parameter to the
propertyChange
method.

The code in Listing J14 invokes three of those methods to get the name of
the property, the old property value, and the new property value each time
the method is invoked.

The output

The remaining output produced by executing statements in the main
method to change the property values is shown below (note that I manually
inserted a line break to separate the output produced from the first event
from the output produced by the second event).

PropertyChangeEvent
 Property Name: color
 Old Value: java.awt.Color[r=255,g=0,b=0]
 New Value: java.awt.Color[r=0,g=0,b=255]

PropertyChangeEvent
 Property Name: color
 Old Value: java.awt.Color[r=0,g=0,b=255]
 New Value: java.awt.Color[r=0,g=255,b=0]

The RGB syntax

In case you are unfamiliar with the RGB color syntax, the letters and the
associated values in the square brackets above indicate the color in terms of

red, green, and blue components.  A value of zero means no
contribution from that color.  A value of 255 means a maximum
contribution from that color.

As you can see, the first event was accompanied by a change in the value
of the color property from all red to all blue.  The second event
was accompanied by a change from all blue to all green.  Of course, this
matches what we knew to be the case based on the parameters passed to the
setter method in the main method.

Now for a change of pace

Neither of the bean classes examined so far provides explicit information
regarding properties, methods, and events.  Rather, introspection on
each of those bean classes relies upon design patterns and low-level
reflection.

The next bean that we examine, Prop02BeanZ, will provide explicit
information regarding properties, but will rely upon design patterns and
low-level reflection for methods and events.

The Prop02BeanZ bean class

The beginning of the class definition for this bean is shown in Listing J15.

class Prop02BeanZ implements Serializable{
  private String size = "Medium";
  private Color color = Color.RED;

  public void setColor(Color color){
    this.color = color;
  }//end setColor

  public Color getColor(){
    return color;
  }//end getColor

Listing J15

As you can see, the two methods defined in Listing J15 match the
design-pattern syntax for the setter and getter methods of a simple property. 
However, we will explicitly instruct the introspection process to ignore
design patterns.  Therefore, unlike in the previous case, the
introspection process will not identify color as a simple
property of the bean.

The size property

The remainder of the bean class definition is shown in Listing J16.

  public void putSize(String size){
    this.size = size;
  }//end putSize()

  public String fetchSize(){
    return size;
  }//end fetchSize()

}//end class Prop02BeanZ

Listing J16

As you can see, the two accessor methods in Listing J16 do not match the
design-pattern syntax for setter and getter properties of a bean. 
However, we will explicitly instruct the introspection process to treat these
two methods as the setter and getter methods of a simple bean. 
Therefore, the introspection process will identify size as a simple
property of the bean.

Explicit information for properties, events, and
methods

To explain the process of providing explicit information for the
properties, events, and methods of a bean, I’m
going to repeat some of the information from Sun that I provided earlier, and
show how it applies in this case.

"The Introspector class provides a standard way for tools to learn
about the properties, events, and methods supported by a target Java Bean.

For each of those three kinds of information, the Introspector will
separately analyze the bean’s class and superclasses looking for either
explicit or implicit information and use that information to build a
BeanInfo object that comprehensively describes the target bean."

Explicit information for properties only

For this bean class, I will provide explicit information only for properties. 
I will not provide explicit information for events or methods.  Continuing
with the material from Sun,

"For each class "Foo", explicit information may be available if there
exists a corresponding "FooBeanInfo" class that provides a non-null value when
queried for the information."

In this case, I will provide a corresponding class named
Prop02BeanZBeanInfo
.  Various methods can be invoked on an object
instantiated from that class to provide explicit information regarding
properties.

"If a class provides explicit BeanInfo about itself … we regard the
explicit information as being definitive…  If we don’t find explicit
BeanInfo on a class, we use low-level reflection to study the methods of the
class and apply standard design patterns to identify property accessors, event
sources, or public methods."

Low-level reflection and design patterns not used

I interpret this to mean that low-level reflection is used only in those
cases where the class doesn’t provide explicit BeanInfo about itself. 
In the case of this bean class, I will provide explicit BeanInfo regarding
properties.  Thus, the introspection process will ignore the fact that
the class contains methods that satisfy the design-pattern syntax for
properties.  As a result, the accessor methods named setColor and
getColor will not result in the introspection process identifying
color
as a property.

Implementing the BeanInfo interface

Here is part of what Sun has to say about implementing the BeanInfo
interface.

"A bean implementor who wishes to provide explicit information about
their bean may provide a BeanInfo class that implements this BeanInfo
interface and provides explicit information about the methods, properties,
events, etc, of their bean.

A bean implementor doesn’t need to provide a complete set of explicit
information. You can pick and choose which information you want to provide
and the rest will be obtained by automatic analysis using low-level
reflection of the bean classes’ methods and applying standard design
patterns."

In particular, you can provide lots of information by defining methods
such as getEventSetDescriptors to return explicit information. 
However, if you elect not to provide explicit information of a particular type
(such as events), you can simply define the method so that it will return
null.  This will cause the introspection process to obtain BeanInfo of that
type on the basis of design patterns and low-level reflection.

The SimpleBeanInfo class

This is a convenience class that makes it easier to provide classes that
implement the BeanInfo interface.  According to sun, the methods in
this class default to

"…providing "noop" information, and can be selectively
overridden to
provide more explicit information on chosen topics. When the introspector sees
the "noop" values, it will apply low level introspection and design patterns
to automatically analyze the target bean."

Presumably, the reference to "noop" information in the above
quotation means that the default versions of the methods return null.

The class named Prop02BeanZBeanInfo

Explicit information about this bean class was provided by defining a
public class named Prop02BeanZBeanInfo that extends SimpleBeanInfo
and overrides the method named getPropertyDescriptors(None
of the other methods were overridden.)

The entire class definition is shown in Listing J17.

public class Prop02BeanZBeanInfo
                          extends SimpleBeanInfo{

  public PropertyDescriptor[]
                        getPropertyDescriptors(){
    try{
      PropertyDescriptor pd =
                          new PropertyDescriptor(
                               "size",
                               Prop02BeanZ.class,
                               "fetchSize",
                               "putSize");
      PropertyDescriptor[] pda = {pd};
      return pda;
    }catch(IntrospectionException e){
      return null;
    }//end catch
  }//end getPropertyDescriptors()

}//end class Prop02BeanZBeanInfo

Listing J17

The getPropertyDescriptors method

The getPropertyDescriptors method must return a reference to an
array object of type PropertyDescriptor.  Each element in the
array describes one property belonging to the bean being described.

In this case, a one-element array object was created and a reference to
that object was returned.

The PropertyDescriptor class

According to Sun,

"A PropertyDescriptor describes one property that a Java Bean exports
via a pair of accessor methods."

As of SDK version 1.4.1, the class defines three overloaded constructors. 
I elected to use the version of the constructor that requires the following
four parameters:

  • The programmatic name of the property as type String(For
    this case, the name is size.)
  • The Class object for the target bean as type Class.
  • The name of the method used for reading the property value as type
    String
    . May be null if the property is write-only.  (For this case,
    the method is named fetchSize.)
  • The name of the method used for writing the property value as type
    String
    . May be null if the property is read-only. (For this case, the
    method is named putSize.)

Using the BeanInfo object

When the introspection process instantiates an object of the class and
invokes the getPropertyDescriptors method on it, the process will
conclude that there is one simple property named size, with the setter
and getter methods named putSize and fetchSize.

(Note that I did not define the methods named setColor and
getColor
as setter and getter methods for a property.  Therefore, in
spite of the fact that these methods satisfy design patterns, the
introspection process will not identify a property named color.)

Analyze the bean

Introspection was performed on this bean by invoking the following
statement in the main method of the test class named Prop02Test.

PropertyDisplay01.display(“Prop02BeanZ”);

Methods

This produced the following list of exposed methods belonging to the bean:

fetchSize
getColor
putSize
setColor

You will recognize two of these methods as the setter and getter methods
defined in Listing J17.

Properties

The introspection process produced the following information regarding
properties:

Name: size
 Type:       class java.lang.String
 Get method: public java.lang.String Prop02BeanZ.
             fetchSize()
 Set method: public void Prop02BeanZ.putSize(
             java.lang.String)
 Bound: false
 Constrained: false

As you might expect, the information regarding the name of the property
and the names of the setter and getter methods corresponds exactly to the
information regarding properties defined in Listing J17.

Since the bean class definition didn’t provide registration methods for
either bound or constrained properties, the introspection process reported
that the property named size is neither bound nor constrained.

Events

The introspection process reported that this bean is not the source of any
events.

Hopefully by now you have a pretty good idea how properties work in Java. 
That brings us to the third major part of this lesson, having to do with
properties in C#.

Part 3,
Comparison with C# Properties for the General User

This part of the lesson concentrates on
properties in C# and a comparison of C# properties with Java properties. 
A sample C# program is provided to illustrate C# properties.  A sample
Java program is also provided to illustrate the similarity of properties
between C# and Java.

This part of the lesson explains and compares Java and C#
properties up to, but not including the use of reflection and introspection. 
Reflection and introspection are covered in Part 4.

Methods and fields

You will see that C# properties act like methods to the creator of the
class but look like public fields to clients of the class.  As a result,
public fields and properties are indistinguishable to readers of the C#
code who don’t have ready access to documentation on the class.

As you saw in Part 2, Java properties look like methods to clients
of the class, and it is impossible to confuse properties with public fields
in Java.

Properties are used for essentially the same purpose in both languages.

Properties support data hiding

Both C# properties and Java properties provide the data hiding generally
required by good object-oriented design.  However, properties are
not a prerequisite for data hiding.  Data hiding can be easily accomplished
in either C# or Java in the absence of properties.

Reflection and introspection

Perhaps the most important characteristic of properties has to do with
reflection and introspection.  This is a process whereby one object can
discover and manipulate the properties belonging to another object, instantiated
from a class that may not have existed when the class of the first object was
defined.  Reflection and introspection will be discussed in detail in Part
4.

Bound properties and constrained properties

Another important characteristic of properties has to do with bound
properties and constrained properties.  This is a process by which
an object can be automatically notified when the value of a bound or constrained
property belonging to another object changes.  Bound properties were
discussed in detail in Part 2.  A brief discussion
of bound and constrained properties will also be provided in Part 4.

C# and Java properties are very similar

Properties are so similar between C# and Java that if you understand
properties in either language, you should have no difficulty understanding
properties in both languages.

Once again, what is a property?

In C#, unlike Java, a property is created by including a special block of code
having a unique syntax in
a class definition.  The syntax of this special block of code is unlike
anything else in C#, and is unlike anything in Java.

As you learned in Part 2, a property is created in Java by including one or both of a pair of
set
and get methods meeting a certain (design pattern) format specification in a class
definition.  Alternatively, a property is created in Java by providing a
class that implements the BeanInfo interface.  The methods belonging
to the BeanInfo object provide explicit information about the properties,
events, and methods of a corresponding bean object.

By the time you finish studying this lesson
in its entirety, you should
know what properties are, and you should know how to create and use them
in both C# and Java.

What others have to say about C# properties

Let’s begin with what others have to say about properties in C#.  Here
is what Microsoft has to say in the documentation for the PropertyInfo
class:

“Properties are logically the same as fields. A property
is a named aspect of an object’s state whose value is typically accessible
through get and set accessors. Properties may be read-only, in which case
a set routine is not supported.”

Programming C# by Jesse Liberty

Here’s what Jesse Liberty has to say about properties in his O’Reilly
book entitled Programming
C#
.

“… properties … act like methods to the creator of the
class but look like fields to clients of the class.

Properties allow clients to access class state as if they were accessing
member fields directly, while actually implementing that access through
a class method.

Properties provide a simple interface to the client, appearing to
be a member variable.  They are implemented as methods, however, providing
the data hiding required by good object-oriented design.”

As you learned in Part 2, this description is true for C# properties, but
is not true for properties in general.

C# In A Nutshell

Here is what the authors of C#
In A Nutshell
from O’Reilly have to say on the matter:

“Properties can be characterized as object-oriented fields. 
Properties promote encapsulation by allowing a class or struct to control
access to its data, and by hiding the internal representation of the data.”

This is true, of course, but there seems to be something missing. 
The same data-hiding benefits can be, and have been, achieved by C++ and Java programmers
for years, using simple accessor methods.  Data hiding is made possible
by the availability of access modifiers for class members.  Typically
data hiding is achieved by providing public methods for accessing
private
instance variables.  While properties generally use this same scheme,
properties are not a prerequisite for data hiding.

C# Primer, A Practical Approach

Here is what Stanley Lippman has to say in
C#
Primer, A Practical Approach
from Addison-Wesley.

“A property typically is a public class member providing
read and possibly write access to a private data member of the class. 
We define a property by specifying an access level, type, and property
name.”

What does Dick Baldwin have to say on the matter?

In my opinion, the above descriptions have missed the mark in
terms of what properties are really all about.  If the benefits of
properties were limited to the above descriptions, it would not have been
worth the effort for Microsoft to develop a new and unique syntax for
properties.  It would not have been worth the effort for
Sun to develop design patterns for properties.  It would not have
been worth the effort for both Microsoft and Sun to develop the reflection and
introspection capability for properties discussed in Part 2 and Part 4 of this
lesson.

The real importance of properties is not based on making methods look
like fields.  Also, the importance is not based on data hiding. 
Rather, the real importance of properties has to do with reflection
and
introspection, which I discussed in Part 2 (for Java) and will
discuss further in Part 4 (for both C# and Java).

(Another important aspect of Java properties has to do with
bound properties and constrained properties.  I discussed this aspect in
Part 2, and will discuss it further in Part 4.)

Fields or methods?

Liberty’s statement that “properties, … act like methods to the
creator of the class but look like fields to clients of the class

is true for C#, but is not true in Java.  In my opinion, whether properties look like fields or look like methods
is immaterial to the experienced programmer.  I can’t imagine that
an experienced OOP programmer would care one way or the other.

Java has provided the benefits of properties in its JavaBeans Component
technology for several years, and Java properties do not look like fields
to clients of the class.  Rather, they look like simple method invocations
to clients of the class.  In the six or more years that I have been
involved in Java, I have yet to hear anyone complain that Java properties
don’t
look like fields.

However, programmers are entitled to their own preferences,
and some programmers
may prefer for properties to look like fields instead of methods.

Not a prerequisite for data hiding

As mentioned earlier, the availability of properties is not a prerequisite
for the “data hiding required by good object-oriented design.” 
Data hiding has been easily accomplished for many years in C++ using private
instance variables and public accessor methods with no concept of properties
being involved.

My description of a property

As I indicated at the beginning of this lesson, it can sometimes be difficult to describe a property.  The following paragraphs contain
another of my descriptions of a property. 
This description is based on practical considerations.  For the most
part, I will describe the things that must be true for a property to exist,
and more importantly, to be really useful.

Name, type, and value

First, a property must have a name, a type, and a value,
and possibly some other attributes as well, (such as being read only
or read/write).

(I discussed indexed properties that
have more than one value in Part 2.)

Same name and type, but different value

A property belongs to an object.  Every object instantiated from
the same class will have the same set of properties.  The properties
belonging to all the objects instantiated from the same class will have
the same names and types, but won’t necessarily have the same values from
one object to the next.

Where is the value stored?

The value of a property is probably most commonly stored in an instance
variable belonging to the object, but that is not a requirement. 
The value could be stored in a database, or a disk file, or elsewhere,
or could be computed on-the-fly when requested.

The state of the object

The value of a property generally contributes to the state of the object
to which it belongs, and when the value of the property changes, the state
of the object changes accordingly.

(When the state of an object changes due to a change in
a bound property value, other interested objects can be automatically notified
of that change of state.)

Standardization is required

To be really useful, the access methodology for a property must be predefined
and standardized within a given programming language.  However, the
access methodology need not be the same from one language to the next. 
As mentioned earlier, C# accesses properties as fields, while Java accesses
properties as methods.

The real importance of properties

It must be possible for executing code to learn everything there is
to know about the properties belonging to a (previously unknown)
object at runtime, and to be able to access those properties for reading
and writing at runtime.  This must be possible even though the author
of the executing code had no knowledge of the unknown object’s class when
the code was originally written.

(In C#, this is referred to as reflection.  In Java,
it is referred to as introspection based on low-level reflection.)

Because .NET is language-neutral, this capability must exist across all languages supported by .NET, even
if the language used to define the class and its properties is different
from the language used to instantiate objects from the class.

A real-world example

Let me describe a real-world example of what I mean.  Ever since
the introduction of Visual Basic several years ago, software developers
have been interested in using standard software components to develop software. 
Using software components to develop software is similar to using electronic
components to manufacture electronic devices.

The great promise of using standard software components to develop software
is that it can reduce the cost of software development in the same way
that the use of standard electronic components has reduced the manufacturing
cost of electronic devices such as computers.

A toolkit full of software components

In this style of programming, the programmer has access to a toolkit
full of software components, and a builder tool that can be used to wire
those software components together to produce a software application.

A sophisticated computer program

The builder tool itself is a very sophisticated and complex computer
program.  In order for the builder tool to wire software components
together, according to the wishes of the programmer, the builder tool must
be able to extract the following information (as a minimum) from
each software component that is installed in the toolkit:

  • Properties
  • Events
  • Methods

Components need to communicate

For example, when two components are wired together, one component may
need to access, and possibly modify, property values belonging to the other
component.  This is only possible if the builder tool can discover
everything that it needs to know about the properties of every component
in the toolkit.  (The builder tool is unable to read the documentation
for a software component the way you and I do.)

Property editors

Even before getting to the point where one component needs to access
the properties belonging to another component, the builder tool itself
usually needs to discover and access the properties of every component
being used to develop an application.

Most builder tools provide a property editor as a graphical user interface
(GUI).
The property editor makes it possible for the programmer to set initial
property values on every software component so that the program being developed
will start running with all of its component objects in the correct state. 
For example, the programmer will normally want to set the location, height,
width, text, and color of each button in a GUI so that it will be in the
correct location with the correct size, text, and color when the program
starts running.  (A screen shot of the C# property editor for the MSVS
builder tool is shown in Figure 1.)

As distinguished from data hiding

In my opinion, the ability to accomplish this under software control
is what separates properties from the ordinary data hiding that we have been
practicing for many years.

Should properties look like fields or methods?

The ability to accomplish the discovery of properties at runtime has
nothing to do with whether the property looks like a field or looks like
a method.  It has been done successfully both ways.  Some programmers
may prefer one approach to the other, but in reality, the difference is
trivial.  To an experienced programmer, the difference in programming
effort between the two approaches is negligible.

Self-documenting code

In my opinion, however, the approach where the property looks like a
method is the more self-documenting of the two.  This approach produces
code that is easier to read and understand by interested third parties
who don’t have ready access to the class documentation.

We have been striving for years to develop better self-documenting programming
styles.  Making properties look like fields instead of methods is
a step backwards in my opinion.  However, from a technical viewpoint,
it can obviously be done either way.

What really matters is …

What really matters is that the mechanism for accessing properties be
predefined and standardized so that code can discover
and manipulate the properties at runtime.

Common at the MSIL level

It is also a requirement that regardless of the programming syntax used
by the different languages supported by .NET, they must all compile to
the same result at the Microsoft Intermediate Language (MSIL) level.

(Interestingly, according to C# In A Nutshell, even though
the property programming syntax at the source code level used by C# is
radically different from that used by Java, the MSIL representation produced
by C# looks like the Java source code representation.)

C# and Java approach standardization in different ways, and they both seem
to work very well.  Even though the standardization approach is different
between the two languages, the underlying concepts being implemented are
very similar.

The C# approach to standardization

The C# approach uses a special source-code syntax to create a property. 
You will see an example of this syntax in the sample program to be discussed
later.  As far as I know, this special syntax must be used in all
cases where you need to create a property in C#.

The Java approach to standardization

As you learned in Part 2, Java allows for two different approaches to
standardization.  The simplest Java approach
makes use of JavaBeans Design Patterns, which are nothing more than
a set of well-defined naming conventions.  Using this approach, you
can create a property in Java by causing the signatures of a pair of set
and get methods to adhere to the design pattern format specifications. 
This was illustrated in Part 2.  You will also see an example of this approach in the programs to be discussed
later.

The other approach allowed by Java involves considerably more work. 
With this approach, you must define a companion or helper class that implements
a rather complex interface named BeanInfo.  An object instantiated
from this helper class can be queried to discover the properties belonging
to objects of the class that it is designed to represent.  This was also
illustrated in Part 2.

It’s time to look at some code

I’m going to show you a C# program named Props01.cs that illustrates properties from
three different viewpoints:

  • The viewpoint of the developer of the class that defines properties.
  • The viewpoint of the user of the class to simply set and get property values.
  • The viewpoint of the sophisticated user of the class to discover and use
    properties at runtime.

The first two viewpoints are illustrated in this part of the lesson.  The third viewpoint contains some powerful material, and the discussion
of the third viewpoint will be deferred until Part 4.

A comparable Java program

In addition, I’m going to show you a comparable Java program named
Props01.java
that accomplishes
exactly the same thing.  I will compare the code between the two programs
and discuss the similarities and the differences.  You will see that
even at the complex level of the third viewpoint, the concepts involved are very
similar to the Java program.  Even
the syntax in the C# program is very similar to the Java program.

Explain in fragments

The complete C# program is shown in Listing C19, and the complete Java
program is shown in Listing J36.  These two listings are near the end
of the lesson in Part 6.

In order to help you to focus specifically on important sections of
code, I will explain the behavior of these programs in fragments.

A target class

The C# program consists of two classes.  The first class that I
will discuss is named TargetClass.  This class defines some
properties (as well as some other members), which are accessed by
code in the Main method of the other class named Props01.

Listing C1 shows the beginning of the code for the definition of the
class named TargetClass.  Here we are seeing things from the
viewpoint of the developer of the class named TargetClass.

 

public class TargetClass{

  public string text;

Listing C1

A public instance variable

The class named TargetClass declares a public instance variable
of type string named text.  There’s nothing exciting
about a public instance variable.  I included it for demonstration
purposes only.  I will show that there is no discernible difference
between accessing a public instance variable and accessing a property in
C#.

Implementing data hiding the "old" way

Listing C2 shows a pair of set and get methods that accomplish
data hiding for this C# program.

(The signatures of these two methods also satisfy the JavaBeans
Design Pattern for property accessor methods.  If this were a Java
program, the existence of these two methods would indicate a simple property named
color.)

  private int colorData = 0;

  public void setColor(int data){
    //Validating code goes here
    colorData = data;
  }//end setColor

  public int getColor(){
    return colorData;
  }//end getColor

Listing C2

Not a property in C#

However, this is not a Java program.  This is a C# program. 
The signatures of these two methods do not indicate a property in C#. 
A different syntax is required to create a property in C#.  The fact that
this is not a property will
be confirmed in Part 4 when we write code to discover the properties of an object of this class.

A C# property

C# uses the special syntax shown in boldface in Listing C3 to create a property
named height.
 

  private int heightData;

  public int height{
    get{
      return heightData;
    }//end get

    set{
      //Validating code goes here
      heightData = value;
    }//end set
  }//end height property

Listing C3

(If the set code block is omitted, the
property is a read-only property.)

Special syntax

There isn’t much for me to
explain about this syntax.  You will
simply need to memorize it.

(Pay particular attention to the number and
locations of the curly braces.  Also pay attention to the hidden parameter
named value, which I will explain shortly.)

The property value

In this case, the property value is stored in the instance variable
named heightData.  However, that is not a requirement. 
The code could be written to store the property value in a database, in
a disk file, or in any other location accessible by the code in the object.

The name and type of the property

The name and type of the property is established by the line of code
that reads

public int height{

In this case, the property is named height and it is type int.

The get method

Although they don’t look like methods, this code effectively contains
two methods named get and set.

Whenever the using code references the property name in a fetching
sense, the code in the get block is executed.  This block must
contain a return statement to return a value of the specified type. 
The get block could also contain any other code that you might want
to have executed in conjunction with such a fetch operation.  An example
of a fetch operation is highlighted in boldface below, where obj
is a reference to an object instantiated from this class.

Console.WriteLine("height: " + obj.height);

The set method and the value parameter

Whenever the using code references the property name in a storage
sense (as the left operand of an assignment operator, for example),
the code in the set block is executed.

The value to be stored (the right operand of the assignment operator,
for example)
is passed to the set code as a hidden parameter
named value.  The name of this hidden parameter never changes. 
The code in the set block must save the value of the hidden parameter
named value in an appropriate location if it is to be successfully
returned later.

Additional code

You can place any code that you might want to have executed in conjunction
with such a set operation in the set block.  Data validation
code is particularly appropriate here.

An example of such a storage operation is shown below where obj
is a reference to an object instantiated from this class.

obj.height = 20;

In this case, the hidden parameter named value will contain an int
value of 20.

Another property named width

Listing C4 shows code that defines another property of type int
named width.  This code uses the same syntax as that used for
the property named height.

 

  private int widthData;

  public int width{
    get{
      return widthData;
    }//end get
    set{
      //Validating code goes here
      widthData = value;
    }//end set
  }//end width property

Listing C4

This is the end of the class definition for the class named
TargetClass.

An object of type TargetClass

An object instantiated from the class named TargetClass contains:

  • One public instance variable of type string named text
    Data hiding is not accomplished with respect to this instance variable.
  • One private instance variable named colorData protected by
    accessor methods named setColor and getColor.  Data
    hiding is accomplished with respect to this instance variable without the
    use of properties.  (The use of properties is not necessary to
    accomplish data hiding.)
  • Two properties of type int named height and width
    Data hiding is accomplished here also.

Switching viewpoints

Now its time to switch to the viewpoint of the user of the class
named TargetClass.  This user already knows the names and the types
of the properties and has no interest in discovering properties at runtime.

The Main method

Listing C5 shows the beginning of the class named Props01 and
the beginning of the Main method in that class.

This code begins by instantiating and saving a reference to a new object
of the class named TargetClass discussed above.  The reference
is saved in the reference variable named obj.  The reference
to this object will be used to access the public instance variable, the
hidden data, and the properties of this object.

(The reference will also be used in Part 4, along with reflection, to discover the properties belonging
to the object at runtime.)

public class Props01{
  static TargetClass obj;
  
  public static void Main(){
    obj = new TargetClass();

Listing C5

Access the public instance variable

The code in Listing C6 uses the object’s reference to directly store
the string “Quit” in the public instance variable named text
Following this, the code uses the object’s reference to directly get and
display the value in the public instance variable named text.

 

    obj.text = "Quit";
    Console.WriteLine(
                  "text: " + obj.text);

Listing C6

Will compare with property access methodology

There is nothing particularly interesting about the code in Listing
C6.  This code is presented here for later comparison with code that
accesses the properties.  The code in Listing C6 produces the following
output on the screen.

text: Quit

Accessing the hidden data

The code in Listing C7 uses the two accessor methods to first set a
value in the private instance variable, and then to get and display that
value.  Note that data hiding is fully supported here without the
use of properties.

 

    obj.setColor(15);

    Console.WriteLine(
           "color: " + obj.getColor());

Listing C7

Listing C7 is a straightforward application of simple data hiding using
accessor methods.  No special support of any kind is required to use
this technique.  The code in Listing C7 produces the following output
on the screen:

color: 15

Accessing a property

Now we are going to access a C# property in a simple non-discovery way. 
This is shown in Listing C8.

 

    obj.height = 20;

Listing C8

The code in Listing C8 sets the value 20 in the property named height.

Appears to access a public field

Note that the syntax of this statement looks exactly like the syntax
of the first statement in Listing C6 (except that the data types and variable
names are different).
  The code in Listing C6 assigns a value directly to a public instance variable.  Without
having access to the documentation for the class named TargetClass,
it would not be possible for the reader of this code to know whether height
is the name of a property or is the name of a public instance variable.

Not self-documenting code

This is what I meant earlier when I said that this approach to property
access is not self-documenting.  For the experienced programmer, the
first statement in Listing C7, which invokes a method, is no more challenging
than the statement in Listing C8, which appears to access a public field.

As I mentioned earlier, I can’t imagine why an experienced programmer would prefer for properties
to look like public fields instead of methods, given the significant loss in self-documentation
that results from that design.  Obviously, however, experienced programmers
at Microsoft have this preference.  Other than the self-documentation
aspect, it seems to me that this difference is a trivial syntax
issue.

Display the property value.

Listing C9 gets and displays the value stored in the property named
height.

 

    Console.WriteLine(
              "height: " + obj.height);

Listing C9

Again, this looks like the code is accessing a public field named height
Without having access to the documentation for the class named
TargetClass,
the reader of the code would have no way of knowing any different.

The code in Listing C9 produces the following output on the computer
screen:

height: 20

Accessing another property

Listing C10 first sets, and then gets and displays the value of the
property named width.

 

    obj.width = 50;
    Console.WriteLine(
                "width: " + obj.width);

Listing C10

There’s nothing new here.  The code in Listing C10 produces the
following output on the computer screen:

width: 50

A comparable Java program

Now I’m going to show you a Java program named Props01.java that accomplishes exactly the
same thing as the C# program discussed above.  As with the C# program,
the Java program will illustrate properties from three significantly different
viewpoints:

  • The viewpoint of the developer of the class that defines properties.
  • The viewpoint of the user of the class to simply set and get property values.
  • The viewpoint of the sophisticated user of the class to discover and use
    properties at runtime.

As was the case with the C# program, the third viewpoint contains some
powerful material, and will be discussed in detail in Part 4.

The most significant aspect of the third viewpoint will be the remarkable
similarity between the C# code and the Java code, even at this complex
level.

Explain in fragments

The complete Java program is shown in Listing J36 near the end of the
lesson.  As usual, in order to help you to focus on important sections
of code, I will explain the behavior of this program in fragments.

A target class

As was the case with the C# program, the Java program consists of two
classes.  The first class that I will discuss is named TargetClass
This class defines some properties, which are accessed by code in the main
method of the other class named Props01.

Listing J18 shows the beginning of the definition of a Java class that
mimics the behavior of the C# class shown in Listings C1 through C4. 
Here we are seeing things from the viewpoint of the developer of the class
named TargetClass.

 

class TargetClass 
               implements Serializable{

  public String text;

Listing J18

Serializable interface

This Java class implements the Serializable interface. 
Without getting into the details, let me just say that this is required
to cause the class to satisfy the JavaBeans Component specification,
making it suitable for introspection.  (Introspection was discussed in
Part 2, and will be explained
and illustrated again in Part 4.)

Class not declared public

Note that unlike the C# class in Listing C1, I didn’t declare the Java
class public.  Rather, by not declaring an access level, I
caused this class to be package private by default.  This was
done strictly for convenience.  In Java, every public class
must be defined in a separate source code file.  I made this class
package
private
to avoid the requirement to create and maintain separate source
code files for each of the class definitions in the program. (Java access
of package private is similar to internal access in C#.)

A public instance variable

As was the case with the C# class in Listing C1, this class definition
begins with the declaration of a public instance variable.  This instance
variable will be used later to illustrate that access to a property in
Java has no resemblance to access to a public instance variable. 
Therefore, it isn’t possible to confuse the two.

A property named color

The Java code in Listing J19 is identical to the C# code in Listing C2.

 

  private int colorData = 0;

  public void setColor(int data){
    //Validating code goes here
    colorData = data;
  }//end setColor

  public int getColor(){
    return colorData;
  }//end getColor

Listing J19

As is the case in C#, the code in Listing J19 accomplishes data hiding
by providing public accessor methods for a private instance variable. 
Perhaps more important, by adhering to JavaBeans Design Patterns, the code in Listing J19 creates a Java property
named color.

This is all that is required to create a property in Java.  No
special and unusual source code syntax is required.  All that is required
is to provide accessor methods that satisfy the JavaBeans Design Patterns
for property accessor methods, and these two methods meet that requirement.

The name and type of the property

According to the JavaBeans Design Pattern for property accessor
methods, the name of the Java property is the word following get
or set in the name of the accessor methods, with the case of the
first character flipped.  The type of the property is the same as
the type of the single argument of the set method, which must match
the return type of the get method.

The property value

For the code in Listing J19, the property value is stored in the instance
variable named colorData.  However, as with C#, this is not
a requirement.  The code could be written to store the property value
in a database, in a disk file, or in any other location accessible by the
code in the object.

Properties named height and width

The code in Listing J20 creates two more Java properties named height
and width.

 

  private int heightData;

  public void setHeight(int data){
   //Validating code goes here
   heightData = data;
  }//end setHeight

  public int getHeight(){
    return heightData;
  }//end getHeight


  private int widthData;

  public void setWidth(int data){
   //Validating code goes here
   widthData = data;
  }//end setwidth

  public int getWidth(){
    return widthData;
  }//end getwidth
  
Listing J20

The code in Listing J20 is different from the C# code in Listings C3
and C4 used to create C# properties named height and width
This is because Listings C3 and C4 use the special syntax required to
create properties in C#.  In the end, however, the properties behave
essentially the same way in both languages.

Listing J20 is also the end of the Java class definition for the class
named
TargetClass.

An object of type TargetClass

A Java object instantiated from the class named TargetClass contains:

  • One public instance variable of type string named text
    Data hiding is not accomplished with respect to this instance variable.
  • Three properties of type int named color, height,
    and width.  Because the property value is stored in a private
    instance variable, this code also accomplishes data hiding.

Switching viewpoints

Now its time to switch to the viewpoint of the user of the class
named TargetClass.  This user knows the names and types of
the properties and has no interest in discovering properties at runtime.
(Discovery of properties will be explained in Part 4.)

The main method

Listing J21 shows the beginning of the class named Props01 and
the beginning of the main method for that class.  Except for
the difference in the signature of the main method, the Java code in Listing J21 is identical
to the C# code in Listing C5.

 

public class Props01{
  static TargetClass obj;
  
  public static void main(String[] args){
    obj = new TargetClass();

Listing J21

The code in Listing J21 begins by instantiating and saving a reference
to a new object of the class named TargetClass discussed above. 
The reference is saved in the reference variable named obj
The reference to this object will be used to access the public instance
variable and the properties of this object.

(The reference will also be used in Part 4, along with introspection, to discover the properties belonging
to the object at runtime.)

Access the public instance variable

As was the case in the C# program, the code in Listing J22 uses the object’s
reference to directly store the string “Quit” in the public instance variable
named text.  Following this, the code uses the object’s reference
to directly get and display the value in the public instance variable named
text.

(Except for the different syntax required for console output,
this code is identical to the C# code in Listing C6.)

    obj.text = "Quit";
    System.out.println(
                  "text: " + obj.text);

Listing J22

Will compare with property access methodology

There is nothing particularly interesting about the code in Listing J22.  This code is presented here for later comparison with code that
accesses the properties.  The code in Listing J22 produces the following
output on the screen.

text: Quit

Accessing the property named color

The code in Listing J23 uses the two property accessor methods to first
set a value in the property named color, and then to get and display
that value.  Note that data hiding is fully supported here.

 

    obj.setColor(15);

    System.out.println(
           "color: " + obj.getColor());

Listing J23

Again, except for the different syntax used for console output, the
Java code in Listing J23 is identical to the C# code in Listing C7. The
difference, however, is that this Java code involves setting and getting
a property value, while that is not the case with the C# code.

The code in Listing J23 produces the following output on the screen:

color: 15

Syntax comparison

It is also important to note that this property access syntax bears
no resemblance to the code in Listing J22, which accesses a public instance
variable.  There is no chance of confusing public instance variables
with properties in Java.  Thus, the syntax used for accessing properties
in Java is more self-documenting than the syntax used for accessing properties
in C#.

Accessing the properties named height and width

The code in Listing J24 uses the property access methods to first set,
and then get and display the values in the properties named height
and width.

 

    obj.setHeight(20);
    System.out.println("height: " + 
                      obj.getHeight());

    obj.setWidth(50);
    System.out.println("width: " + 
                       obj.getWidth());

Listing J24

Compare the bottom half of the code in Listing J24 (width property
access)
with the C# code in Listing C10 to see a direct comparison
of the difference in property access mechanisms in C# and Java.  There’s
nothing new here, so I won’t discuss it further.

The code in Listing J24 produces the following output on the computer
screen:

height: 20

width: 50

Review of Part 3

In Part 3, you have learned:

  • C# properties act like methods to the creator of the class but look like
    public fields to clients of the class.  As a result, public fields
    and properties are indistinguishable to readers of the C# code who don’t
    have ready access to documentation on the class.
  • Java properties look like methods to clients of the class, and it is impossible
    to confuse properties with public fields in Java.
  • Properties are used for essentially the same purpose in both C# and Java.
  • Both C# properties and Java properties provide the data hiding generally
    required by good object-oriented design.
  • Properties are not a prerequisite for data hiding.  Data hiding can
    be easily accomplished in C#, Java, or C++ in the absence of properties.
  • The most important aspect of properties in both C# and Java is their involvement
    in the processes of reflection and introspection at runtime.
  • Properties are so similar between C# and Java that if you understand properties
    in either language, you should have no difficulty understanding properties
    in both languages.  While they differ in syntax between the two languages,
    they are very similar in concept.

Except for reflection and introspection, Part 3 also provided sample programs to illustrate the items in the above
list.


Part 4, Comparison with C# Properties for the Sophisticated User

Reflection and introspection

As stated above, the most important aspect of properties has to do with
reflection and introspection.  This is a process whereby one object can
discover and manipulate the properties belonging to another unknown object even
though the author of the executing program had no knowledge of the unknown
object’s class when the executing program was originally written. 
Reflection and introspection are discussed in detail in this part of the lesson.

(Although introspection for Java properties was discussed in Part 2, the
discussion of reflection and introspection is somewhat deeper in this section
than was the case in Part 2.)

Bound properties and constrained properties

Another important characteristic of properties has to do with bound
properties and constrained properties.  This is a process by which
an object can be automatically notified when the value of a bound or constrained
property belonging to another object changes.  A detailed discussion was
provided in Part 2.  An additional brief discussion of bound and
constrained properties will be provided in this part of the lesson.

The most important aspect of properties

It must be possible for executing code to learn everything there is
to know about the properties belonging to an object at runtime, and to
be able to access those properties for reading and writing at runtime.

(In C#, this is referred to as reflection.  In Java,
it is referred to as introspection, possibly based on low-level reflection.)

For .NET, this capability must exist across several languages, even if
the language used to define the class and its properties is different from
the language used to instantiate objects from the class.

Let’s see some code

In this part of the lesson, I will continue my discussion of a C# program that illustrates properties from
three different viewpoints:

  • The viewpoint of the developer of the class that defines properties.
  • The viewpoint of the user of the class to simply set and get property values.
  • The viewpoint of the sophisticated user of the class to discover and use
    properties at runtime.

The first two viewpoints were covered in Part 3.  The third viewpoint is the primary topic of this
part of the lesson.  While you might find it complex, I hope that you will
stick with it until you understand the concepts involved.

A comparable Java program

In addition, I will continue my discussion of a comparable Java program that accomplishes
exactly the same thing as the C# program.  I will compare the code
between the two programs and discuss the similarities and the differences. 
You will see that even at the complex level of the third viewpoint, the
C# and Java programs are very similar both in terms of concepts and syntax.

Explain in fragments

The complete C# program is shown in Listing C19, and the complete Java
program is shown in Listing J36.  These two listings are near the end
of the lesson in Part 6.

In order to help you to focus on important sections of code, I will
explain the behavior of these programs in fragments.

A target class

The C# program consists of two classes.  The first class, which
I discussed in detail in Part 3, is named TargetClass.  This
class defines some properties (as well as some other members), which
are accessed by code in the Main method of the other class named
Props01.

Listing C11 shows the entire definition of the class named TargetClass
Of particular interest in this part of the lesson is the boldface material,
which defines two properties, named height and width.
 

public class TargetClass{
  //A public instance variable
  public string text;
  
  //This would be a property named
  // color in Java, but not in C#
  private int colorData = 0;
  public void setColor(int data){
    //Validating code goes here
    colorData = data;
  }//end setColor
  public int getColor(){
    return colorData;
  }//end getColor
  
  //This is a property named height
  private int heightData;
  public int height{
    get{
      return heightData;
    }//end get
    set{
      //Validating code goes here
      heightData = value;
    }//end set
  }//end height property

  //This is a property named width
  private int widthData;
  public int width{
    get{
      return widthData;
    }//end get
    set{
      //Validating code goes here
      widthData = value;
    }//end set
  }//end width property
  
}//end TargetClass

Listing C11

An object of type TargetClass

An object instantiated from the class named TargetClass contains:

  • One public instance variable of type string named text.
  • One private instance variable named colorData protected by
    accessor methods named setColor and getColor.
  • Two properties of type int named height and width.

The Main method

Listing C12 shows the beginning of the class named Props01 and
the beginning of the Main method in that class.

This code, (which you have seen before) begins by instantiating and saving a reference to a new object
of the class named TargetClass discussed above.  The reference
is saved in the reference variable named obj.

The reference to this object was used in Part 3 to access the public
instance variable, the hidden data, and the properties of this object. 
The reference will be used in this part of the lesson to discover
the properties belonging to the object at runtime.

 

public class Props01{
  static TargetClass obj;
  
  public static void Main(){
    obj = new TargetClass();

Listing C12

The user viewpoint

In this part of the lesson, we will look at C# properties from the viewpoint of the
sophisticated user who needs to first discover and then use properties
at runtime.

Three steps

Basically, this process will consist of three steps:

  • Get a reference to an object of the type Type, which represents
    the type of an object instantiated from the class named TargetClass
    (This is similar to getting an object of the type Class in Java.)
  • Use the Type object to get an array of objects of
    type
    PropertyInfo.  This array will contain one object for
    each property belonging to the target object of type TargetClass.
    (From
    the previous discussion, you already know that the target object contains
    two properties, one named height and the other named width
    Therefore, the array will have two elements.)
  • Iterate on the array object, using each object in the
    array to determine the name, type, and current value of the
    corresponding property belonging to the TargetClass object.

C# and the Object class

Listing C13 shows the first step in this process.  (Note that
I skipped the code in the Main method that was covered in Part 3.)


 

    //Some code skipped in Main method

    Type theType = obj.GetType();

Listing C13

All classes in C# (and Java as well) derive either directly or
indirectly from the class named Object.  The class named
Object
defines several methods that are inherited into all other classes. 
Some of those methods, (such as Equals and ToString),
are meant to be overridden in new classes.  In C#, those methods are declared to be
virtual

The GetType method is not virtual

Some of the methods
of the Object class, (such as GetType),
are meant to be used as is, without overriding them.  Those methods
are not declared to be virtual, so they cannot be overridden.


(Note that the GetType method in C# has the same purpose as the
getClass
method in Java.  Note also that all methods in Java are
virtual by default unless they are marked as final.  All non-final
methods, including getClass, can be overridden in Java.)

A Type object

When the GetType method is invoked on an existing object, it
returns a reference to an object of the type Type.  According
to Microsoft,

“The Type object exposes the metadata associated
with the class of the current Object.”

Metadata vs. runtime type information

In Java jargon, it would be said that the Type object exposes the
runtime type information (RTTI) of the object on which the method
is invoked (except that in Java the method is named getClass,
and the object that is returned by the method is type Class instead
of type Type).

(Actually, the .NET documentation for the typeof
operator contains the following statement, “To obtain the run-time type
of an expression, you can use the .NET Framework method GetType.” 
It appears that Microsoft uses the terms metadata and run-time type
interchangeably.)

Alternate ways to get a Type object

There are several other ways to get a Type object as well, including
the typeof operator and the static GetType method of the
Type
class (the GetType method invoked in Listing C13 is an instance
method, defined in the Object class, and inherited into the TargetClass
class).

The static GetType method

The static GetType method
of the Type class returns a Type object representing
a type specified by the name of a class as a string.  (The corresponding
method in Java is the method named forName, which is a static method of
the class named Class.)

The typeof
operator

The typeof operator returns a Type object
representing a type specified by the name of its operand.

(This is similar to the instanceof operator in Java, which is used to determine
the type of an object based on its reference.  However, the instanceof
operator is used with a different syntax and returns type boolean.)

What is a Type object?

Here is what Microsoft has to say about a Type object:

“This class is the primary way to access metadata, and it
acts as a gateway to the Reflection API. Use the members of Type
to get information about a type declaration, such as the constructors,
methods, fields, properties, and events of a class …”

Step 1: Getting the Type object

The code in Listing C13 invokes the GetType method on the object
instantiated earlier from the class named TargetClass.  The
GetType
method returns a reference to an object of the type Type.  This
object represents the class from which the object was instantiated,
TargetClass
in this case.  The reference to the Type object is saved in
the reference variable named theType.

Step 2:  Getting property information

In this step, we will get information about the properties defined in
the class named TargetClass, which is represented by the object
of the type Type.

The Type class provides several methods that can be invoked on
an object of the Type class, to get information about the type represented
by the Type object.  A few of those methods are shown in the
following list to illustrate some of the information that is available. 
(In general, the names of the methods indicate the type of information
that they are designed to provide.)

  • GetProperties
  • GetEvents
  • GetFields
  • GetInterfaces
  • GetMembers
  • GetMethods
  • GetConstructors

Invoking the GetProperties method

The code in Listing C14 invokes the GetProperties method on the
Type
object.

 

    PropertyInfo[] propInfo = 
               theType.GetProperties();

Listing C14

According to Microsoft, the GetProperties method “Returns
all the public properties of the current Type.”
  The information
is returned as an array of objects where each object in the array is of
type PropertyInfo.

One PropertyInfo object for
each property

Each object of type PropertyInfo in the array
represents one of the properties belonging to the target object under investigation. 
In this case, the target object is the object instantiated from the class
named TargetClass

Number of properties equals number of elements

The number of elements in the array indicates the number of properties belonging
to the target object.

Using the Length property of the array

Every array object in C# has a property named Length, whose value
is “The total number of elements in all the dimensions of the Array.” 
Since this is a one-dimensional array, the value of Length is the
same as the number of properties belonging to the target object. 
The code in Listing C15 gets and displays the value of the Length
property.

 

    Console.WriteLine(
        "Number of Public Properties: "
                    + propInfo.Length);

Listing C15

The number of properties

The code in Listing C15 produces the following output on the screen,
which matches what we already know about the number of properties defined
in the class named TargetClass.

Number of Public Properties: 2

Getting information about each property

Each of the PropertyInfo objects contained in the array can be
queried to obtain information about the specific property that it represents. 
The code in Listing C16 displays some explanatory text on the screen and
then calls the method named DisplayPropertyInfo, passing a reference
to the array of PropertyInfo objects to the method.

 

    Console.WriteLine(
        "Descriptions of Properties:");

    DisplayPropertyInfo(propInfo);

Listing C16

The method named DisplayPropertyInfo is designed to get and display
information from each element in the array.  As a result, this method
gets and displays information about each property in the class named TargetClass.

PropertyInfo objects

An object of the PropertyInfo type contains properties and methods
that can be accessed to obtain information about the property that the
object represents.  For example, the name and the type of the property
represented by the object are stored in the object’s properties named Name
and
PropertyType(Here we have the properties of one object
representing attributes of a property of another object.)

The DisplayPropertyInfo method

The method named DisplayPropertyInfo receives a reference to
the array of PropertyInfo objects as an incoming parameter. 
The entire method consists of a single for loop, and is shown in
Listing C17.

 

  public static void 
            DisplayPropertyInfo(
              PropertyInfo[] propInfo){

    for(int i=0;i<propInfo.Length;i++){
      PropertyInfo myPropInfo = 
                           propInfo[i];

      Console.WriteLine("Name: " + 
                      myPropInfo.Name);

      Console.WriteLine("Type: " + 
              myPropInfo.PropertyType);

     //------------------------------//

      //Get and display the value
      MethodInfo readMethod = 
             myPropInfo.GetGetMethod();
      Console.WriteLine("Value: " +
          readMethod.Invoke(obj,null));

    }//end for loop
  }//end DisplayPropertyInfo

Listing C17

Step 3:  Iterate on the array

This method uses a for loop to iterate on the array, extracting
name,
type,
and value information from each object stored
in the array.

Getting the name and type information is straightforward. 
Getting the value information is a little more complicated. (Listing
C17 contains a comment separator to visually separate the code that gets
the name and type from the code that gets the value.)

Different issues

From a conceptual viewpoint, there is a significant difference between
name
and type on one hand, and
value on the other.  The name
and type of a property is the same for every object instantiated
from a given class.  However, the current value of the property will
vary among different objects instantiated from the same class.  Therefore,
value
is specific to each object instantiated from the class, while
name
and type are the same for all objects instantiated from the class.

Getting the name and type

The code to get and display the name and the type of the property represented
by the PropertyInfo object is shown above the visual separator in
Listing C17.  As mentioned earlier, this code is straightforward. 
All that is required is to access the properties named Name and
PropertyType
belonging to the PropertyInfo object.  The values of these
properties are the name and the type of the property represented by the
PropertyInfo
object.

Getting the property value for a specific object

The code required to get and display the value of a particular property
for a specific object is shown below the visual separator in Listing C17. 
This code consists of the following steps (as you will see later, despite
its complexity, this is essentially the same process used to accomplish
the same task in Java):

  • Invoke the GetGetMethod on the PropertyInfo object to get
    a reference to an object of type MethodInfo that represents the
    get
    method for the particular property represented by the PropertyInfo
    object.
  • Invoke the Invoke method on the MethodInfo object, passing
    a reference to the target object as a parameter.  This causes the
    get
    method to be invoked on the target object, returning the current value
    of the property for that object.

The MethodInfo class

An object of the MethodInfo class represents a specific method. 
It contains numerous properties and methods that allow you to manipulate
the method represented by the object.  For example, there is a method
named GetParameters that can be invoked to get a list that identifies
the number and types of parameters required by the method.

The Invoke method of the MethodInfo class

In this case, we are interested in the Invoke method of the MethodInfo
class.  This method makes it possible for us to invoke the get
method represented by the MethodInfo object on a specific object
of the TargetClass class.

The Invoke method requires two parameters.  The first parameter
is a reference to the object on which we want the get method to
be invoked.  In this case, this is the object of the class named TargetClass,
which has been the target of the investigation from the beginning.

The second parameter is a reference to an array object, where each element
in the array contains a reference to an object that is to be passed as
a parameter to the method being invoked.  In this case, the get
method requires no parameters, so the code in Listing C17 passes null
as the second parameter to the Invoke method.

Invoking the get method on the target object

The result of invoking the Invoke method on the reference to
the object of type MethodInfo, while passing the target object as
a parameter, is to cause the get method to be invoked on the target
object.  The int value returned by the get method is
picked up and returned by the Invoke method.  This value is
passed to the WriteLine method in Listing C17, which causes it to
be displayed on the computer screen.

The screen output

The screen output for the first iteration of the for loop in
Listing C17 is shown below:

Name: height

Type: System.Int32

Value: 20

This output indicates that the name of the first property found by our
discovery process was height.  This agrees with what we already
know to be true.

The property type information

The property type reported by this process looks a little strange. 
What in the world is the type System.Int32?

According to the Microsoft documentation, the type System.Int32 represents
a 32-bit signed integer.  However, when we defined the class named
TargetClass,
we defined the type of the height property as type int, not
type System.Int32.  Here is what Microsoft has to say about
the relationship between type int and type System.Int32,
(with my parenthetical expression inserted):

“The corresponding .NET Framework data type (for type int)
is System.Int32. The properties and methods of the int data type
are the same as the System.Int32 properties and methods.”

Here is what Stanley Lippman has to say in
C#
Primer, A Practical Approach
:

“The keywords for the C# predefined types are aliases for
types defined within the System namespace.  For example, int
is represented under .NET by the System.Int32 type, and float
by the System.single type.”

Thus, when we specified type int, we were actually using an alias
to specify type System.Int32.

The property value

Finally, the current value represented by the height property
on the target object is reported to be 20, which we can verify by examining
Listing C8, which shows the value of the height property being set to 20.

The second property named width

The screen output for the second and last iteration of the for
loop in Listing C17 is shown below:

Name: width

Type: System.Int32

Value: 50

Because we defined the TargetClass, and wrote the program that
defined the properties and set the values of the two properties, we know
these to be the correct
name, type, and current value. 
However, prior knowledge of the answers is not a prerequisite for the correct
operation of this discovery process.  It would work correctly if someone
else had written the class named TargetClass and had provided us
with only the compiled version of the class.

An alternative approach for getting the property
value

The code in Listing C18 uses the GetValue method of the PropertyInfo
class to get and display the current property value.  This single
statement is, in effect, a shorthand replacement for the last two statements
inside the for loop in Listing C17.

 

/***********
      Console.WriteLine("Value: " + 
        myPropInfo.GetValue(obj,null));
***********/

Listing C18

The importance of properties

So now you know the true importance of properties in C#.  In my
opinion, the importance of properties has nothing to do with making properties
look like fields instead of methods.  Similarly, it has nothing to
do with information hiding, although those are two interesting by-products
of properties.  Rather, the importance of properties is that properties
support one aspect of the reflection process.

The reflection process makes it possible for one object to discover
and manipulate the properties, events, methods, constructors, fields, etc.,
belonging to another unknown object, at runtime, with no prior knowledge
of the class from which the other object was instantiated.  This,
in turn, facilitates the development of very sophisticated software that
makes heavy use of information about objects gained at runtime.

A comparable Java program

Now I will continue my discussion of a Java program that accomplishes exactly the
same thing as the C# program discussed above.  As with the C# program,
the Java program illustrates properties from three significantly different
viewpoints:

  • The viewpoint of the developer of the class that defines properties.
  • The viewpoint of the user of the class to simply set and get property values.
  • The viewpoint of the sophisticated user of the class to discover and use
    properties at runtime.

Also, as was the case with the C# program, the first two viewpoints were
covered in Part 3.

The third viewpoint is the primary topic of this part of the lesson. 

I hope that you will stick with
it until you understand the concepts involved.

The most significant aspect of the third viewpoint will be the remarkable
similarity between the C# code and the Java code, even at this complex
level.

Explain in fragments

The complete Java program is shown in Listing J36 in Part 6.  As usual, in order to help you to focus on important sections
of code, I will explain the behavior of this program in fragments.

A target class

As was the case with the C# program, the Java program consists of two
classes.  The first class, which was explained in detail in Part 3,
is named TargetClass.  This Java class mimics the behavior
of the C# class shown in Listing C11.

This class defines some properties, which are accessed by code in the
main
method of the other class named Props01.  Listing J25 shows
the definition of the class named TargetClass in its entirety. 
The boldface code in Listing J25 shows the definition of three properties
named color, height, and width.

 

class TargetClass 
               implements Serializable{
  //A public instance variable
  public String text;
  
  //This is a property named color
  private int colorData = 0;
  public void setColor(int data){
    //Validating code goes here
    colorData = data;
  }//end setColor
  public int getColor(){
    return colorData;
  }//end getColor
  
  //This is a property named height
  private int heightData;
  public void setHeight(int data){
   //Validating code goes here
   heightData = data;
  }//end setHeight
  public int getHeight(){
    return heightData;
  }//end getHeight
  
  //This is a property named width
  private int widthData;
  public void setWidth(int data){
   //Validating code goes here
   widthData = data;
  }//end setwidth
  public int getWidth(){
    return widthData;
  }//end getwidth
  
}//end TargetClass

Listing J25

An object of type TargetClass

A Java object instantiated from the class named TargetClass contains:

  • One public instance variable of type string named text.
  • Three properties of type int named color, height,
    and width.

The main method

Listing J26 shows the beginning of the class named Props01 and
the beginning of the main method for that class.  Except for
the difference in the signature of the main method, the Java code in Listing J26 is identical
to the C# code in Listing C12.

 

public class Props01{
  static TargetClass obj;
  
  public static void main(String[] args){
    obj = new TargetClass();

Listing J26

The code in Listing J26, which you have seen before, begins by instantiating and saving a reference
to a new object of the class named TargetClass discussed above. 
The reference is saved in the reference variable named obj
The reference was used to access the public instance variable and the properties
of this object in Part 3.   In this part of the lesson, the reference will
be used in the introspection process to discover the properties belonging
to the object at runtime.

The user viewpoint

As was the case with the C# program, we’re getting ready to park the
family station wagon and take a ride in a sports car.  We will examine
Java properties from the viewpoint of the sophisticated user of the class
who needs to first discover and then use properties at runtime.  You saw a
preview of this in Part 2, but the code in this part of the lesson goes further
than the code that you saw in Part 2.  In particular, the code in this part
will not only identify the properties, but also will get and display their
current values.

The bottom line at the beginning

I’m going to give you the bottom line at the beginning.  Our objective
is to compare the process of discovering and manipulating properties in
Java with the process of discovering and manipulating properties in C#. 
We will see that even though the names of the classes and methods that
we will use to accomplish this purpose are different, the concepts and
mechanisms involved are remarkably similar.  Once you understand how
to do this in one language, you should understand how to do it in both
languages.

Four steps are required

This process will consist of four steps.  (Recall that only
three steps were required in C#.  An extra step is required in Java.)
 
If you compare the description of these Java steps with the descriptions
of the steps required to accomplish the same thing in C#, you will find
them to be almost identical.

Step 1: A Class object

First I will get a reference to an object of the type Class,
which represents the type of an object instantiated from the class named
TargetClass.

(Recall that the corresponding object was of the type Type
in C#.  Frankly, I prefer the C# name Type to the Java name Class,
because an object of the type Class in Java can also represent primitive
types.  Primitive types are not objects instantiated from classes
in Java.  Also, when lecturing, it is easier to talk about the Type
class than to talk about the Class class.)

Step 2: A BeanInfo object

Next I will use the Class object to get a reference to an object
of type BeanInfo, which represents the class named TargetClass
at
a much deeper level than the object of the class named Class (this
is the extra step that is required in Java).
  The object of type
BeanInfo
provides considerably more information about TargetClass than does
the object of type Class.

(Note that the BeanInfo object can be configured
to represent not only the TargetClass object, but also the superclasses
of TargetClass.  However, in this program, I constrained it
to preclude information about the superclasses for simplicity.)

Step 3: An array of PropertyDescriptor objects

Then I will use the BeanInfo object to get an array of objects
of type
PropertyDescriptor.

(This corresponds to the second
step in C#, which produces an array of objects of type PropertyInfo)

This array will contain one object for each property belonging to the target
object of type TargetClass.

(From the previous discussion, you
already know that the target object contains three properties, named color,
height,
and width.  Therefore, the array will have three elements.)

Step 4: Iterate on the array

Finally, I will iterate on the array object, using each object in the
array to determine the name, type, and current value of the
corresponding property belonging to the TargetClass object.

Java and the Object class

Listing J27 shows the first step in this process.
 

    //Some code skipped in main method

    Class theType = obj.getClass();

Listing J27

(This Java
listing corresponds to the C# listing in Listing C13.  Note that I
skipped the code in the main method that was covered in Part 3.)

Object defines eleven methods

All classes in Java
(and C# as well)
derive either directly
or indirectly from the class named Object.  The class named
Object in Java
defines eleven methods that are inherited into all other classes. 

Some methods may be overridden

Some of those methods, (such as equals and toString),
are intended to be overridden in new classes.  In Java, they are virtual
by default, so they may be freely overridden. 

Some methods are final

Some of the methods,
(such
as getClass),
are intended to be used as is, without overriding
them.  Those methods are declared final so that they cannot
be overridden.

Invoking the getClass method

When the getClass method is invoked on an existing object, it
returns a reference to an object of the type Class.  According
to Sun,

“Instances of the class Class represent classes and
interfaces in a running Java application.”

In Java jargon, it would be said that the Class object exposes the
runtime type information (RTTI) of the object on which the method
is invoked.

Alternate ways to get a Class object

I know of three ways to get a Class object in Java.  One
way is to invoke the getClass method on an object, as illustrated
in Listing J27.  (This is similar to invoking the GetType
instance method in C#.)

The second way is to invoke the static forName method of the
Class
class, passing the name of the target class as a String parameter.
(This
is similar to invoking the static GetType method of the Type
class in C#.)

The third way involves getting Class objects that represent primitive
types.  I will defer an explanation of that process until a future
lesson.

Step 1: Getting the Class object

The code in Listing J27 invokes the GetClass method on the object
instantiated earlier from the class named TargetClass.  The
GetClass
method returns a reference to an object of the type Class.  This
object represents the class from which the object was instantiated,
TargetClass
in this case.  The reference to the Class object is saved in
the reference variable named theType.

The Introspector class

The discovery process in Java is described as introspection using
low-level reflection.
  The class named Introspector plays
an important role in this process.  Here is what Sun has to say about
the Introspector class:

“The Introspector class provides a standard way for tools
to learn about the properties, events, and methods supported by a target
Java Bean.

For each of those three kinds of information, the Introspector will
separately analyze the bean’s class and superclasses looking for either
explicit or implicit information and use that information to build a BeanInfo
object that comprehensively describes the target bean.”

Note that a Java Bean is a standard software component used in the
Java version of software component programming.  Note also that I did not
provide an associated BeanInfo class in this program.  Therefore,
introspection will be performed in this program using low-level reflection and
design patterns.  (See Part 2 for a discussion of explicit BeanInfo
information.)

Step 2: Getting the BeanInfo object

The Introspector class provides several static methods, including
three overloaded versions of a method named getBeanInfo.

The code in Listing J28 uses one of the overloaded versions of the getBeanInfo
method to get a BeanInfo object capable of providing information
about the target object earlier instantiated from the class named TargetClass.

 

      BeanInfo beanInfo = 
        Introspector.getBeanInfo(
                    theType,theType.
                      getSuperclass());

Listing J28

(Since
there is no requirement for this step in C#, there is no C# code listing
corresponding to Listing J28.)

Two parameters required

This version of the getBeanInfo method requires two parameters. 
The first parameter is a Class object representing the class from which
the target object was instantiated, TargetClass in this case.

The second parameter is also a Class object.  This object
represents a superclass of the target object.  The resulting BeanInfo
object will contain information about the target class and all of its superclasses
up to, but not including the class represented by the second parameter. 

Use the direct superclass

In this case, the second parameter
is the direct superclass of the target
class.  Therefore, the resulting BeanInfo object will contain information
about the target class only (information about superclasses was precluded
for simplicity).

Step 3:  Getting property information

This step corresponds to the second step in the C# reflection process. 
We will get information about the properties defined in the class named
TargetClass,
which is now represented by the object of type BeanInfo.

Several methods available

The BeanInfo object provides several methods that can be invoked
to get information about the class represented by the BeanInfo object. 
A few of those methods are shown in the following list to illustrate some
of the information that is available.  (In general, the names of
the methods indicate the type of information they are designed to provide.)

  • getPropertyDescriptors
  • getMethodDescriptors
  • getEventSetDescriptors

Invoking the getPropertyDescriptors method

The code in Listing J29 invokes the getPropertyDescriptors method
on the
BeanInfo object.  (This is similar to invoking the
GetProperties
method on the
Type object in the C# program shown in Listing C14.)


 

      PropertyDescriptor[] propInfo = 
              beanInfo.getPropertyDescriptors();

Listing J29

PropertyDescriptor objects

According to Sun, the getPropertyDescriptors method returns “An
array of PropertyDescriptors describing the editable properties supported
by this bean.”

An array of PropertyDescriptor objects

The information is returned as an array of objects, where each object
in the array is of type PropertyDescriptor.  Each object of
type PropertyDescriptor represents one of the properties belonging
to the target class under investigation. 

The number of properties

In this case, the target
class is the class named TargetClass.  The number of elements
in the array indicates the number of properties belonging to objects of
the target class.

Using the length property of the array

As in C#, every array object in Java has a final public member
variable (constant) named
length, whose value is the number
of elements in the array. 

In this case, the value of length
is the same as the number of properties belonging to the target class. 
The code in Listing J30 gets and displays the value of length. (This
code corresponds to the code in the C# program shown in Listing C15.)


 

      System.out.println(
               "Number of Properties: "
                    + propInfo.length);

Listing J30

The number of properties

The code in Listing J30 produces the following output on the screen,
which matches what we already know about the number of properties defined
in the Java class named TargetClass(Recall that the Java
class has three properties whereas the corresponding C# class has only
two properties.)

Number of Public Properties: 3

Getting information about each property

Each of the PropertyDescriptor objects contained in the array
can be queried to obtain information about the specific property that it
represents.  The code in Listing J31 displays some explanatory text
on the screen and then calls the method named DisplayPropertyInfo,
passing a reference to the array of PropertyDescriptor objects to
the method.  (The Java code in Listing J31 corresponds to the C#
code in Listing C16.)


 

      System.out.println(
        "Descriptions of Properties:");

      displayPropertyInfo(propInfo);

Listing J31

The DisplayPropertyInfo method

As was the case with the C# program, the method named DisplayPropertyInfo
is designed to get and display information from each element in the array. 
As a result, this method gets and displays information about each property
in the class named TargetClass.

The PropertyDescriptor objects

Each object of the PropertyDescriptor type contains several methods
that can be invoked to obtain information about the property that the object
represents.  For example, the name and the type of the property represented
by the object can be obtained by invoking the methods named getName
and
getPropertyType on the PropertyDescriptor object.

(By now, you should suspect that these are properties of
the
PropertyDescriptor object, based on JavaBeans Design Patterns.)

Step 4: Iterate on the array of PropertyDescriptor
objects

The method named DisplayPropertyInfo receives a reference to
the array of PropertyDescriptor objects as an incoming parameter. 
The entire method, consisting of a single for loop, is shown in Listing
J32.

(This corresponds to Listing C17 in the C# program
discussed earlier.  If you compare the two listings, you will find
that they are very similar in both syntax and concept.)

  public static void 
      displayPropertyInfo(
        PropertyDescriptor[] propInfo){

    for(int i=0;i<propInfo.length;i++){
      PropertyDescriptor myPropInfo = 
                           propInfo[i];

      System.out.println("Name: " + 
                 myPropInfo.getName());

      System.out.println("Type: " +
         myPropInfo.getPropertyType());

     //------------------------------//

      //Get and display the value
      Method readMethod = 
            myPropInfo.getReadMethod();
      try{
        System.out.println("Value: " + 
          readMethod.invoke(obj,null));
      }catch(Exception e){
        e.printStackTrace();}
    }//end for loop
  }//end displayPropertyInfo

Listing J32

This method uses a for loop to iterate on the array, extracting
name,
type,
and value information using each object stored
in the array.

Getting the name and type information is straightforward. 
As is the case in C#, getting the value information is a little
more complicated.

(Listing J32 contains a comment separator to visually
separate the code that gets the name and type from the code that gets the
value.)

Different issues

As is the case in C#, there is a significant difference between
name
and type on one hand, and
value on the other.  The name
and type of a property is the same for every object instantiated
from a given class.  However, the current value of the property will
vary among different objects instantiated from the same class.  Therefore,
value
is specific to each object instantiated from the class, while
name
and type are the same for all objects instantiated from the class.

Getting the name and type

The code to get and display the name and the type of the property represented
by the PropertyDescriptor object is shown above the visual separator
in Listing J32.  As mentioned earlier, this code is straightforward. 
All that is required is to invoke the methods named getName and
getPropertyType
belonging to the PropertyDescriptor object.  The values returned
by these methods are the name and the type of the property represented
by the
PropertyDescriptor object.

Getting the property value for a specific object

The code required to get and display the value of a particular property
for a specific object is shown below the visual separator in Listing J32. 
This code consists of the following steps (note that this is essentially
the same process used to accomplish the same task in C#, as shown in Listing C17):

  • Invoke getReadMethod on the PropertyDescriptor object to
    get a reference to an object of type Method that represents the
    get
    method for the particular property represented by the PropertyDescriptor
    object.
  • Invoke the invoke method on the Method object, passing a
    reference to the target object as a parameter.  This causes the
    get
    method to be invoked on the target object, returning the current value
    of the property for that object.

The Method class

An object of the Method class provides information about, and
access to, a single method on a class or interface. The reflected method
may be a class method or an instance method (including an abstract method).

(The Method class in Java is very similar to the
MethodInfo class in C#.)

Numerous methods

The Method object contains numerous methods that allow you to manipulate
the method that it represents.  For example, there is a method named
getParameterTypes that you can use to get a list that identifies
the number and types of parameters required by the method.

(Recall that the C# MethodInfo class has a method
named GetParameters that serves essentially the same purpose as
the getParameterTypes method in Java.)

The invoke method of the Method class

In this case, we are interested in the invoke method of the Method
class.  This method makes it possible to execute the get method
represented by the Method object on a specific object of the TargetClass
class.

Two parameters required

As was the case in C#, the Java invoke method requires two parameters. 
The first parameter is a reference to the object on which we want the get
method to be invoked.  In this case, this is the object of the class
TargetClass,
which has been the target of the investigation from the beginning.

The second parameter is a reference to an array object, where each element
in the array contains a reference to an object that is to be passed as
a parameter to the method being invoked.  In this case, the get
method requires no parameters, so the code in Listing J32 passes null
as the second parameter to the invoke method.

(If you compare this portion of Listing J32 with the corresponding
portion of Listing C17, you will see that the process involved is essentially
the same for C# and Java.  Even the name of the invoke method
is the same, except that in C#, the method is named Invoke instead
of invoke.)

Invoking the get method on the target object

The result of invoking the invoke method on the reference to
the object of type Method, while passing the target object as a
parameter, is to cause the get method to be invoked on the target
object.  The int value returned by the get method is
picked up and returned by the invoke method.  This value is
passed to the println method in Listing J32, which causes it to be
displayed on the computer screen.

The screen output

The screen output for the first iteration of the for loop in
Listing J32 is shown below:

Name: color

Type: int

Value: 15

This output indicates that the name of the first property found by the
introspection process is color.  The property is of type
int,
and the current value is 15.  We know from our prior knowledge of
the behavior of the program that this is a correct report.

The properties named height and width

The screen output for the remaining two iterations of the for
loop in Listing J32 is shown below:

Name: height

Type: int

Value: 20

Name: width

Type: int

Value: 50

Because we defined the TargetClass, and wrote the program that
set the values of the three properties, we know these to be the correct
name,
type,
and current value.  However, prior knowledge of the
answers is not a prerequisite for the correct operation of this introspection
process.  As in C#, the introspection process would work correctly
if someone else had written the class named TargetClass and had
provided us with only the compiled version of the class.

Bound and constrained properties

Properties in Java have an extra capability that apparently doesn’t exist for
properties in C#.

(I strongly suspect that this general capability
does exist somewhere in C# and I simply haven’t discovered it yet. 
I also expect that the day after this article is published, I will receive
a flurry of email telling me that I am wrong and that the capability described
below does exist for properties in C#.  That will be good because
that is how I often learn new things.)

In Java, a bound property has the ability to register interested
observer objects and to notify those observer objects each time the property
value changes.  A constrained property has the ability to do
the same thing with the added stipulation that any observer of a constrained
property has the right to veto the change.

Toolbar buttons and menus

A good example of the use of bound properties involves the construction
of toolbar buttons that correspond to items on a menu. 

The toolbar
button and the corresponding menu item should track one another in terms of being enabled
and disabled.  A toolbar button can register itself as an observer
on the enabled property of a menu item.  Each time the value
of the enabled property of the menu item changes, the toolbar button
will be notified, and can change its own enabled property
accordingly.  See Understanding
Action Objects in Java
for a further discussion of this capability.

Part 5, Summary

This lesson concentrates on properties in Java and C#, and a comparison of
Java properties with C# properties.

C# and Java properties are very similar

Properties are so similar in C# and Java that if you understand properties
in either language, you should have no difficulty understanding properties
in both languages.

Summary of Part 1

It is a little difficult to explain properties in a way that makes sense. 
This is particularly true in Java, which doesn’t use a special syntax to create
a property.  Therefore, Part 1 uses the analogy that trying to explain a
property is sort of like trying to explain a traffic light to an alien from
outer space.

The bottom line is that a traffic light is a traffic light only
when drivers recognize it as such.  Otherwise, it is simply some blinking
light bulbs in an ugly box in the proximity of an intersection. 

Similarly, a property is a property only when other programs recognize it as
such.  Otherwise, it is simply a value, among potentially many values
maintained within a program.

C# programs use reflection to recognize
properties.  Java programs use introspection based on low-level reflection
to recognize properties.

Part 1 also advances the notion that the
major importance of properties has to do with the use of reflection and
introspection.  These processes make it possible to write very
sophisticated programs that recognize and manipulate the values of properties
belonging to previously unknown objects.  Microsoft’s Visual Studio.net
is an example of such a program.

Part 1 also discusses the importance for
programmers to become proficient in both Java and C# so that they will
be able to meet the programming needs of the future.  Fortunately, Java
and C# are very similar.

Summary of
Part 2

Part 2 explains Java properties in detail.  This
includes an explanation of the following concepts:

  • Simple properties
  • Indexed properties
  • Bound properties
  • Constrained properties
  • Introspection based on low-level reflection and design patterns
  • Introspection based on explicit BeanInfo information

A sample program is presented and discussed that illustrates all of the
concepts in the above list except constrained properties.

The sample
program in Part 2 also illustrates the use of introspection to get
information about events and exposed methods.

Summary of Part 3

Part 3 discusses
properties in C#, and compares C# properties with Java properties.

A sample C# program
in Part 3 illustrates C# properties, and a sample Java program illustrates the similarity of properties in C# and Java.

Methods and fields

C# properties act like methods to the creator of the class but look
like public fields to clients of the class.  As a result, public fields
and properties are indistinguishable to readers of the code who don’t have
ready access to documentation on the class.

Java properties look like methods to clients of the class.  As
a result, it is impossible to confuse properties with public fields in
Java.  As a result, Java properties are more self-documenting than
C# properties.  Beyond this, however, properties are used for essentially
the same purposes in both languages.

Properties support data hiding

Both C# properties and Java properties provide the data hiding generally
required by good object-oriented design.  However, properties are
not a prerequisite for data hiding.  Data hiding can be easily accomplished
in C#, Java, or C++ in the absence of properties.

Summary of Part 4

Part 4 continues the discussion of properties in C#, and the comparison of
C# properties with Java properties.

Reflection
and introspection

The most important aspect of properties has to do with reflection
and introspection.  This is a process whereby one object can discover
and manipulate the properties belonging to another unknown object even
though the author of the executing program had no knowledge of the unknown
object’s class when the executing program was originally written.

Sample
programs in Part 4 illustrate reflection and introspection for both C# and
Java.

Part 6, Complete Program Listings


This part of the lesson contains complete program listings for all of the
programs discussed in the body of the lesson.
 

/*File PropertyDisplay01.java
Copyright 2003, R.G.Baldwin

The purpose of this program is to display
information about the properties belonging to a
JavaBeans Component.

To display the information, invoke the static
method named display passing the bean class as a
String parameter.

Tested using SDK 1.4.1 under Win2000.
************************************************/

import java.beans.*;
import java.lang.reflect.*;

public class PropertyDisplay01{

  public static void display(String beanClass)
                                throws Exception{

    //Create an object of type Class that
    // describes the class of the bean. The
    // static method Introspector.getBeanInfo()
    // requires either one or two objects of
    // type Class as parameters.  The forName()
    // method of the Class class returns such an
    // object, given the name of a class as a
    // String parameter.
    Class myBeanClassObject = Class.forName(
                                      beanClass);

    //Given the Class object that describes the
    // bean's class, use the static getBeanInfo()
    // method of the Introspector class to obtain
    // information about the class of the bean.
    // Save this information in an object of type
    // BeanInfo.  The second parameter passed to
    // getBeanInfo() prevents introspection from
    // going further up the inheritance
    // hierarchy.
    BeanInfo beanInfo = Introspector.getBeanInfo(
              myBeanClassObject,
              myBeanClassObject.getSuperclass());

    //A BeanDescriptor object provides global
    // information about a bean, including its
    // Java class, its displayName, etc. Use the
    // getBeanDescriptor() method to extract
    // information of that type from the
    // beanInfo object and store it in a new
    // BeanDescriptor object. Display the
    // information using methods designed to
    // extract the name and class of the bean
    // from the beanDescriptor object.

    BeanDescriptor beanDescriptor =
                    beanInfo.getBeanDescriptor();
    System.out.println("Name of bean:  " +
                       beanDescriptor.getName());
    System.out.println("Class of bean: " +
                  beanDescriptor.getBeanClass());
    System.out.println("");


    //A MethodDescriptor describes a particular
    // method that a Java Bean supports for
    // external access from other components.
    // The getMethodDescriptors() method returns
    // an array of MethodDescriptor objects where
    // each object describes one of the methods.
    System.out.println("==== Methods: ====");
    MethodDescriptor[] methodDescriptor =
                 beanInfo.getMethodDescriptors();
    for (int i=0;i < methodDescriptor.length;
                                            i++){
        System.out.println(
                  methodDescriptor[i].getName());
    }//end for-loop
    System.out.println("");



    //A PropertyDescriptor object describes one
    // property that a Java Bean exports via a
    // pair of accessor methods. Use the
    // getPropertyDescriptors() method to create
    // an array of PropertyDescriptor objects,
    // one for each exported property.  Then
    // display that information using methods
    // designed to extract the name of the
    // property, the type of the property, the
    // name of the get method, and the name of
    // the set method.  Also determine and
    // display whether or not the property is
    // a bound property, and whether or not it
    // is a constrained property.
    System.out.println("==== Properties: ====");
    PropertyDescriptor[] propertyDescriptor =
               beanInfo.getPropertyDescriptors();
    for (int i=0; i < propertyDescriptor.length;
                                           i++) {
      System.out.println("Name: " +
                propertyDescriptor[i].getName());
      System.out.println(" Type:       " +
        propertyDescriptor[i].getPropertyType());
      System.out.println(" Get method: " +
          propertyDescriptor[i].getReadMethod());
      System.out.println(" Set method: " +
         propertyDescriptor[i].getWriteMethod());
      System.out.println(" Bound: " +
                propertyDescriptor[i].isBound());
      System.out.println(" Constrained: " +
          propertyDescriptor[i].isConstrained());
    }//end for-loop
    System.out.println("");


    //An EventSetDescriptor object describes a
    // group of events that a given Java bean
    // fires. Information can be extracted from
    // each object of the type.
    System.out.println("==== Events: ====");
    EventSetDescriptor[] eventSetDescriptor =
               beanInfo.getEventSetDescriptors();
    for (int i=0; i < eventSetDescriptor.length;
                                            i++){
      System.out.println("Event Name: " +
                eventSetDescriptor[i].getName());
      System.out.println(" Add Method:    " +
                         eventSetDescriptor[i].
                         getAddListenerMethod());
      System.out.println(" Remove Method: " +
                      eventSetDescriptor[i].
                      getRemoveListenerMethod());
      methodDescriptor = eventSetDescriptor[i].
                  getListenerMethodDescriptors();
      for (int j=0; j < methodDescriptor.length;
                                            j++){
          System.out.println(" Event Type: " +
                  methodDescriptor[j].getName());
      }//end for-loop
    }//end for-loop

  }//end display method
}//end class

Listing J33

 

/*File Prop02Test.java
Copyright 2003, R.G.Baldwin

Purpose:  This program, in conjunction with the
files named Prop02BeanZBeanInfo.java and
PropertyDisplay01.java, illustrates several
important aspects of properties including:

Simple properties
Indexed properties
Bound properties
Property design patterns
Explicit identification of properties using a
  class that implements the BeanInfo interface.

This program produces the following output on
the screen.  Note that in some cases, line
breaks were manually inserted in this listing to
force the material to fit in this narrow format.

Process Prop02BeanX
Name of bean:  Prop02BeanX
Class of bean: class Prop02BeanX

==== Methods: ====
fetchSize
getColor
getData
putSize
setColor
setData

==== Properties: ====
Name: color
 Type:       class java.awt.Color
 Get method: public java.awt.Color Prop02BeanX.
             getColor()
 Set method: public void Prop02BeanX.
             setColor(java.awt.Color)
 Bound: false
 Constrained: false
Name: data
 Type:       class [Ljava.lang.Integer;
 Get method: public java.lang.Integer[]
             Prop02BeanX.getData()
 Set method: public void Prop02BeanX.
             setData(java.lang.Integer[])
 Bound: false
 Constrained: false

==== Events: ====


Process Prop02BeanY
Name of bean:  Prop02BeanY
Class of bean: class Prop02BeanY

==== Methods: ====
addPropertyChangeListener
fetchSize
getColor
putSize
removePropertyChangeListener
setColor

==== Properties: ====
Name: color
 Type:       class java.awt.Color
 Get method: public java.awt.Color Prop02BeanY.
             getColor()
 Set method: public void Prop02BeanY.
             setColor(java.awt.Color)
 Bound: true
 Constrained: false

==== Events: ====
Event Name: propertyChange
 Add Method:   public void Prop02BeanY.
               addPropertyChangeListener(
               java.beans.PropertyChangeListener)
 Remove Method:public void Prop02BeanY.
               removePropertyChangeListener(
               java.beans.PropertyChangeListener)
 Event Type: propertyChange

Exercise PropertyChangeListener
PropertyChangeEvent
 Property Name: color
 Old Value: java.awt.Color[r=255,g=0,b=0]
 New Value: java.awt.Color[r=0,g=0,b=255]
PropertyChangeEvent
 Property Name: color
 Old Value: java.awt.Color[r=0,g=0,b=255]
 New Value: java.awt.Color[r=0,g=255,b=0]


Process Prop02BeanZ
Name of bean:  Prop02BeanZ
Class of bean: class Prop02BeanZ

==== Methods: ====
fetchSize
getColor
putSize
setColor

==== Properties: ====
Name: size
 Type:       class java.lang.String
 Get method: public java.lang.String Prop02BeanZ.
             fetchSize()
 Set method: public void Prop02BeanZ.putSize(
             java.lang.String)
 Bound: false
 Constrained: false

==== Events: ====
Press any key to continue...


Tested using SDK 1.4.1 under Win 2000.
************************************************/


import java.io.Serializable;
import java.awt.Color;
import java.beans.*;

class Prop02Test{
  public static void main(String[] args)
                                throws Exception{
    System.out.println("Process Prop02BeanX");
    PropertyDisplay01.display("Prop02BeanX");

    System.out.println("");
    System.out.println("nProcess Prop02BeanY");
    PropertyDisplay01.display("Prop02BeanY");
    Prop02BeanY aProp02BeanY = new Prop02BeanY();
    aProp02BeanY.addPropertyChangeListener(
                             new PropListener());
    System.out.println(
            "nExercise PropertyChangeListener");
    aProp02BeanY.setColor(Color.BLUE);
    aProp02BeanY.setColor(Color.GREEN);

    System.out.println("");
    System.out.println("nProcess Prop02BeanZ");
    PropertyDisplay01.display("Prop02BeanZ");

  }//end main
}//end class Prop02Test
//=============================================//

class Prop02BeanX implements Serializable{
  private String size = "Medium";
  private Color color = Color.RED;
  private Integer data[];

  public void setColor(Color color){
    //This would be a property based on design
    // patterns
    this.color = color;
  }//end setColor

  public Color getColor(){
    //This would be a property based on design
    // patterns
    return color;
  }//end getColor


  public void setData(Integer[] data){
    //This would be a property based on design
    // patterns
    this.data = data;
  }//end setData

  public Integer[] getData(){
    //This would be a property based on design
    // patterns
    return this.data;
  }//end getData


  public void putSize(String size){
    //This would not be a property based on
    // design patterns
    this.size = size;
  }//end putSize()

  public String fetchSize(){
    //This would not be a property based on
    // design patterns
    return size;
  }//end fetchSize()

}//end class Prop02BeanX
//=============================================//


class Prop02BeanY implements Serializable{
  private String size = "Medium";
  private Color color = Color.RED;

  private PropertyChangeSupport changes =
                 new PropertyChangeSupport(this);

  public void addPropertyChangeListener(
                   PropertyChangeListener lstnr){
    changes.addPropertyChangeListener(lstnr);
  }//end addPropertyChangeListener

  public void removePropertyChangeListener(
                   PropertyChangeListener lstnr){
    changes.removePropertyChangeListener(lstnr);
  }//end removePropertyChangeListener

  public void setColor(Color color){
    //This would be a property based on design
    // patterns
    Color oldColor = this.color;
    this.color = color;
    changes.firePropertyChange(
                        "color",oldColor, color);
  }//end setColor

  public Color getColor(){
    //This would be a property based on design
    // patterns
    return color;
  }//end getColor

  public void putSize(String size){
    //This would not be a property based on
    // design patterns
    this.size = size;
  }//end putSize()

  public String fetchSize(){
    //This would not be a property based on
    // design patterns
    return size;
  }//end fetchSize()

}//end class Prop02BeanY
//=============================================//

class PropListener implements
                          PropertyChangeListener{
  public void propertyChange(
                        PropertyChangeEvent evt){
    System.out.println("PropertyChangeEvent");
    System.out.println(" Property Name: "
                        + evt.getPropertyName());
    System.out.println(" Old Value: "
                            + evt.getOldValue());
    System.out.println(" New Value: "
                            + evt.getNewValue());
  }//end propertyChange
}//end PropListener
//=============================================//

class Prop02BeanZ implements Serializable{
  private String size = "Medium";
  private Color color = Color.RED;

  public void setColor(Color color){
    //This would be a property based on design
    // patterns
    this.color = color;
  }//end setColor

  public Color getColor(){
    //This would be a property based on design
    // patterns
    return color;
  }//end getColor

  public void putSize(String size){
    //This would not be a property based on
    // design patterns
    this.size = size;
  }//end putSize()

  public String fetchSize(){
    //This would not be a property based on
    // design patterns
    return size;
  }//end fetchSize()

}//end class Prop02BeanZ
//=============================================//

Listing J34

 

/*File Prop02BeanZBeanInfo.java
Copyright 2003, R.G.Baldwin

Purpose:  See Prop02Test.java

Tested using SDK 1.4.1 under Win 2000.
************************************************/

import java.beans.*;

public class Prop02BeanZBeanInfo
                          extends SimpleBeanInfo{

  public PropertyDescriptor[]
                        getPropertyDescriptors(){
    try{
      PropertyDescriptor pd =
                          new PropertyDescriptor(
                               "size",
                               Prop02BeanZ.class,
                               "fetchSize",
                               "putSize");
      PropertyDescriptor[] pda = {pd};
      return pda;
    }catch(IntrospectionException e){
      return null;
    }//end catch
  }//end getPropertyDescriptors()

}//end class Prop02BeanZBeanInfo

Listing J35

 

/*File Props01.cs
Copyright 2002, R.G.Baldwin

This program is intended to explore and
explain the use of properties in C#.

Program tested using:
Microsoft (R) Visual C# .NET Compiler 
version 7.00.9466
for Microsoft (R) .NET Framework 
version 1.0.3705
Under Win2000 Version 5.0 SP 2

Program output is:
text: Quit
color: 15
height: 20
width: 50
Number of Public Properties: 2
Descriptions of Properties:
Name: height
Type: System.Int32
Value: 20
Name: width
Type: System.Int32
Value: 50
**************************************/
using System;
using System.Reflection;

public class TargetClass{
  //A public instance variable
  public string text;
  
  //This would be a property named
  // color in Java, but not in C#
  private int colorData = 0;
  public void setColor(int data){
    //Validating code goes here
    colorData = data;
  }//end setColor
  public int getColor(){
    return colorData;
  }//end getColor
  
  //This is a property named height
  private int heightData;
  public int height{
    get{
      return heightData;
    }//end get
    set{
      //Validating code goes here
      heightData = value;
    }//end set
  }//end height property

  //This is a property named width
  private int widthData;
  public int width{
    get{
      return widthData;
    }//end get
    set{
      //Validating code goes here
      widthData = value;
    }//end set
  }//end width property
  
}//end TargetClass
//===================================//

public class Props01{
  static TargetClass obj;
  
  public static void Main(){
    obj = new TargetClass();
    
    //Access a public instance 
    // variable
    obj.text = "Quit";
    Console.WriteLine(
                  "text: " + obj.text);
    
    //Invoke public accessor methods
    obj.setColor(15);
    Console.WriteLine(
           "color: " + obj.getColor());
    
    //Set and get a property
    obj.height = 20;
    Console.WriteLine(
              "height: " + obj.height);

    //Set and get another property
    obj.width = 50;
    Console.WriteLine(
                "width: " + obj.width);

    //Now do reflection to identify
    // properties of the object
    Type theType = obj.GetType();
    PropertyInfo[] propInfo = 
               theType.GetProperties();
    Console.WriteLine(
        "Number of Public Properties: "
                    + propInfo.Length);
    Console.WriteLine(
        "Descriptions of Properties:");
    // Display all the properties.
    DisplayPropertyInfo(propInfo);

  }//end Main
  
  public static void 
            DisplayPropertyInfo(
              PropertyInfo[] propInfo){
    for(int i=0;i<propInfo.Length;i++){
      PropertyInfo myPropInfo = 
                           propInfo[i];
      Console.WriteLine("Name: " + 
                      myPropInfo.Name);
      Console.WriteLine("Type: " + 
              myPropInfo.PropertyType);

      //Get and display the value
      MethodInfo readMethod = 
             myPropInfo.GetGetMethod();
      Console.WriteLine("Value: " +
          readMethod.Invoke(obj,null));

/*    Alternative approach for value
      Console.WriteLine("Value: " + 
        myPropInfo.GetValue(obj,null));
*/
      
    }//end for loop
  }//end DisplayPropertyInfo
  
}//end class Props01
//===================================//


Listing C19

 
 

/*File Props01.java
Copyright 2002, R.G.Baldwin

This program is intended to explore and
explain the use of properties in Java,
and is designed for comparison with a
similar C# program.

Program tested using:
SDK 1.4.0 under Win2000 V5.0 SP2

Program output is:
text: Quit
color: 15
height: 20
width: 50
Number of Properties: 3
Descriptions of Properties:
Name: color
Type: int
Value: 15
Name: height
Type: int
Value: 20
Name: width
Type: int
Value: 50
**************************************/
import java.beans.*;
import java.lang.reflect.*;
import java.io.*;

//This class is not declared public in
// order to avoid the rqmt for separate
// files
class TargetClass 
               implements Serializable{
  //A public instance variable
  public String text;
  
  //This is a property named color
  private int colorData = 0;
  public void setColor(int data){
    //Validating code goes here
    colorData = data;
  }//end setColor
  public int getColor(){
    return colorData;
  }//end getColor
  
  //This is a property named height
  private int heightData;
  public void setHeight(int data){
   //Validating code goes here
   heightData = data;
  }//end setHeight
  public int getHeight(){
    return heightData;
  }//end getHeight
  
  //This is a property named width
  private int widthData;
  public void setWidth(int data){
   //Validating code goes here
   widthData = data;
  }//end setwidth
  public int getWidth(){
    return widthData;
  }//end getwidth
  
}//end TargetClass
//===================================//

public class Props01{
  static TargetClass obj;
  
  public static void main(
                        String[] args){
    obj = new TargetClass();
    
    //Access a public instance 
    // variable
    obj.text = "Quit";
    System.out.println(
                  "text: " + obj.text);
    
    //Invoke property methods
    obj.setColor(15);
    System.out.println(
           "color: " + obj.getColor());
    
    obj.setHeight(20);
    System.out.println("height: " + 
                      obj.getHeight());

    obj.setWidth(50);
    System.out.println("width: " + 
                       obj.getWidth());

    //Now do reflection and 
    // introspection to identify
    // properties of the object
    Class theType = obj.getClass();

    try{
      BeanInfo beanInfo = 
      Introspector.getBeanInfo(
                    theType,theType.
                      getSuperclass());

    
      PropertyDescriptor[] propInfo = 
            beanInfo.
              getPropertyDescriptors();

      System.out.println(
               "Number of Properties: "
                    + propInfo.length);
      System.out.println(
        "Descriptions of Properties:");
      // Display all the properties.
      displayPropertyInfo(propInfo);
    }catch(IntrospectionException e){
                  e.printStackTrace();}

  }//end Main
  
  public static void 
      displayPropertyInfo(
        PropertyDescriptor[] propInfo){
    for(int i=0;i<propInfo.length;i++){
      PropertyDescriptor myPropInfo = 
                           propInfo[i];
      System.out.println("Name: " + 
                 myPropInfo.getName());

      System.out.println("Type: " +
         myPropInfo.getPropertyType());

      //Get and display the value
      Method readMethod = 
            myPropInfo.getReadMethod();
      try{
        System.out.println("Value: " + 
          readMethod.invoke(obj,null));
      }catch(Exception e){
        e.printStackTrace();}
    }//end for loop
  }//end displayPropertyInfo
  
}//end class Props01

Listing J36

Copyright 2003, Richard G. Baldwin.  Reproduction in whole or in
part in any form or medium without express written permission from Richard
Baldwin is prohibited.

About the author

Richard Baldwin is a college professor (at Austin Community College in Austin, TX) and private consultant whose primary focus is a combination of Java, C#, and XML. In addition to the many platform and/or language independent benefits of Java and C# applications, he believes that a combination of Java, C#, and XML will become the primary driving force in the delivery of structured information on the Web.

Richard has participated in numerous consulting projects and he
frequently provides onsite training at the high-tech companies located
in and around Austin, Texas.  He is the author of Baldwin’s Programming Tutorials,
which has gained a worldwide following among experienced and aspiring programmers.
He has also published articles in JavaPro magazine.

Richard holds an MSEE degree from Southern Methodist University and
has many years of experience in the application of computer technology
to real-world problems.

[email protected]

-end-

Latest Posts

Related Stories