Java Objects and Classes in ColdFusion
In this and following chapters, we examine the nature of objects and types of objects and how they interact with one another.
Classes are factories for objects. Once a class defines the kind of data it can hold and the operations it is capable of performing, a particular object can be made. For instance, "Ludwig" is an instance of the "person" class. Once instantiated (once a particular instance of a class has been brought into existence), the object often needs to relate to other objects similarly constructed in order to have a meaningful existence. Once the object can no longer fulfill the obligations of meaningful service to the organization of objects to which it belongs, it is taken out of service. Understanding the concepts presented in this chapter is crucial to excelling at Java development, as the object is the foundation of Java.
In Java, as in life, the rules regarding the creation of objects follow clearly defined and relatively simple patterns. In this chapter, we engage the complexities of the hierarchical relations involved in objects performing their functions. These relations or relational descriptors include packages and documentation, constructors, abstractions, inner classes, exceptions, and finalityfew of which have meaningful corresponding terms or concepts in ColdFusion. For that reason I have tried where possible to approach the subject cautiously and from different angles up to this point.
7.1 Packages
We will begin with packages for three reasons. First, they should be somewhat familiar at this point because they have been mentioned previously. Second, working with packages is very straightforward. Finally, we will use packages to organize much of the remainder of our work, so understanding how they are used is necessary.
Applications are organized into packages, the fundamental organizational unit in Java. A package is simply a directory, itself composed of Java classes, interfaces, and other packages.
Use packages in a manner similar to how you use directories for storing files on your computer. Package names are hierarchical, corresponding to physical directories on your hard drive. You may create as few or as many packages as you like for your applications. Use your best judgment to decide when it makes sense to create a new package. Think about portability, code reuse, and the audience and purpose of your application.
You have encountered packages many times already. For this book, I have a root package called JavaForCF. Inside this package is one package for each chapter in which we write code examples, such as chp6. Classes in the standard API created by Sun are generally in the java package, and they have a subgroup when it makes sense. Packages are referenced using dot notation. So, for instance, the java.sql package contains classes relevant for creating connections to databases. The java.nio package contains new classes for input and output. That means that there is a folder called java that has a folder called nio inside it that contains the source files.
NOTE
Where is this folder? Installing the JDK on your system includes an archive called src.jar. This archive contains all of the source files used to create the JDK. You can view the source file for any given Java class by unpacking the src.jar archive. To unpack the archive, navigate to the JDK directory via a command prompt. Then type this command: jarv xf src.jar C:/jdk1.4/src/java/sql/Statement.java. This command will create the new directories src, java, and sql. You can then open and view the Statement.java file. This is the object used for executing static SQL statements and returning the results. Depending on your file associations, you might need to replace the file name src.jar with src.zip in the above command.
You will readily see the importance of using packages if you have worked with XML at all. Because XML allows you to define your own tags, just as Java allows you to define your own classes, you must have some way of indicating the uniqueness of your work to distinguish it from the work of others. That is, you have to avoid name conflicts. In XML, you do this with namespaces. In Java, you use packages.
Packages can be nested. For instance, the String class is in the lang package, which is nested in the java package: Any reference to String is really an implicit reference to java.lang.String.
Sun recommends using your Internet domain name for your packages, because these are already known to be unique. Generally, packages are created with the domain name as a subpackage of the name extension. For instance, packages created by Apache Software Foundation can be found inside the org.apache package. Here's another example: I have registered the domain CoreColdFusion.com. I might create packages for this book and this chapter in com.corecoldfusion.javaforcf.chp7.
7.1.1 Designing Packages
Creating unique names is the real reason for package nesting. The compiler honors no relationship whatsoever between com.corecoldfusion.javaforcf and com.corecoldfusion.javaforcf.chp7. They are organized in your mind, perhaps, but otherwise they are totally unrelated.
However, packages should be designed with care. Think of the access you want to allow, and plan for it. Classes in a package have total access to each other's non-private members. Anything not explicitly marked private opens your class members up for unexpected reference by unrelated classes.
Group your packages logically. This will help other programmers find your code. There is no added benefit to obscurity when placing classes in packages.
7.1.2 The package Object
There is a package object in the java.lang package is not used in creating or working with packages. You don't need to reference it when defining packages for your classes. It is useful for discovering metadata about a package, such as version information about a package's implementation and specification.
This can be useful to you as a programmer. For instance, you may need your program to inspect the package object for version information and then implement certain functionality depending on the result. You could also need this information in order to work around bugs that may exist in a certain package.
You gain access to this information by calling the main methods of the package object, which are shown here:
public String getName()
returns the name of this package.
public String getSpecificationTitle()
returns the title of the specification implemented by this package. If unknown, returns null.
public String getSpecificationVersion()
returns a string describing the version of the specification implemented by this package. If unknown, returns null.
public String getSpecificationVendor()
returns a string naming the owner and maintainer of this specification implemented by this package. If unknown, returns null.
public boolean isCompatibleWith(String desiredVersion)
returns a boolean indicating whether the package is compatible with the version indicated.
7.1.3 Working with Packages
There are two kinds of classes that a class can use: classes in their own package, and public classes in other packages. If you want to use a public class in another package, you have two options:
Add the full package name to every reference you make to the class. For instance:
package chp7; public class Test { public static void main(String [] a) { java.io.File myFile = new java.io.File("Dude.txt"); } }
Import the package and reference the class name directly:
package chp7; import java.io.File; public class Test { public static void main(String [] a) { File myFile = new File("Dude.txt"); } }
Importing the packageName.className as shown above allows the shortcut reference to only that class, not other classes in the same package. You can use multiple import statements for the same package or different packages, like this:
import java.io.BufferedReader; import java.io.BufferedWriter; ...
If you are going to import more than one or two classes in the same package, use the wildcard character to import all of the classes in a package, like this:
import java.io.*;
When importing a package, you can import the package name with a trailing * to indicate that you want to import all of the classes in that package.
NOTE
Using the * to indicate the import of all classes in a package does NOT import nested packages. For instance, importing java.util.* will import all classes located directly in that package, but not the java.util.jar or java.util.zip subpackages.
You can only import classes. You cannot import objects.
The only time you need to worry about your imports is when you have two classes that have the same name in different packages. A common example of this kind of conflict is with two different Date classes provided by the JDK. There is one in java.sql and another in java.util. So while the following will compile,
import java.util.*; import java.sql.*;
you won't be able to reference the Date class in this program without the package name, like this:
Date hireDate; // Error!
because the compiler won't know if you mean java.util.Date or java.sql.Date. If you need to use both Date classes, you don't have a choice but to explicitly reference each one:
java.sql.Date hireDate = new java.sql.Date(); java.util.Date fireDate = new java.util.Date();
7.1.4 Packaging a Class
It is easy to add classes to a package: Create a directory. You do so using the package keyword at the top of your class definition:
package chp7; public class Test { //... code here }
This command must be the first non-comment line of code in your class definition.
It is not necessary to put your class into a package. If you do not include a package command in your source file, the classes therein are added to the default package. The default package has no name. If the directories don't exist, some IDEs will create the packages for you and place the resultant class in there. The compiler won't check directories, however, when source files are compiled, and the virtual machine may not be able to find the resulting class file. For that reason, put your source files and class files in the same directory structure.