Showing posts with label classes. Show all posts
Showing posts with label classes. Show all posts

Sunday, January 8, 2012

Java’s Class Library

A library in Java is a collection of classes - usually providing related facilities - that you can use in your programs. The Java class library provides you with a whole range of goodies, some of which are essential for your programs to work at all, and some of which make writing your Java programs easier. To say that the standard class library covers a lot of ground would be something of an understatement, so I won’t be going into it in detail here; however, you will be looking into how to apply many of the facilities it provides throughout the book of Java.

Since the class library is a set of classes, it is stored in sets of files where each file contains a class definition. The classes are grouped together into related sets that are called packages, and each package is stored in a separate directory. A class in a package can access any of the other classes in the package. A class in another package may or may not be accessible.

The package name is based on the path to the directory in which the classes belonging to the package are stored. Classes in the package java.lang for example are stored in the directory path java\lang (or java/lang under Unix). This path is relative to a particular directory that is automatically known by the Java run-time environment that executes your code. You can also create your own packages that will contain classes of your own that you want to reuse in different contexts, and that are related in some way.

The JDK includes a growing number of standard packages - well over 100 the last time I counted. Some of the packages you will meet most frequently are:

[1] java.lang :-
These classes support the basic language features and the handling of arrays and strings. Classes in this package are always available directly in your programs by default because this package is always automatically loaded with your program.

[2] java.io :-
Classes for data input and output operations.

[3] java.util :-
This package contains utility classes of various kinds, including classes for managing data within collections or groups of data items.

[4] javax.swing :-
These classes provide easy-to-use and flexible components for building graphical user interfaces (GUIs). The components in this package are referred to as Swing components.

[5] java.awt :-
Classes in this package provide the original GUI components (JDK 1.1) as well as some basic support necessary for Swing components. java.awt.geom These classes define two-dimensional geometric shapes.

[6] java.awt.event :-
The classes in this package are used in the implementation of windowed applications to handle events in your program. Events are things like moving the mouse, pressing the left mouse button, or clicking on a menu item.

As noted previously, you can use any of the classes from the java.lang package in your programs by default. To use classes from the other packages, you typically use import statements to identify the names of the classes that you need from each package. This allows you to reference the classes by the simple class name. Without an import statement you would need to specify the fully qualified name of each class from a package each time you refer to it. As we will see in a moment, the fully qualified name for a class includes the package name as well as the basic class name. Using fully qualified class names would make your program code rather cumbersome, and certainly less readable. It would also make them a lot more tedious to type in.

You can use an import statement to import the name of a single class from a package into your program, or all the class names. The two import statements at the beginning of the code for the applet you saw earlier in this post are examples of importing a single class name. The first was:

import javax.swing.JApplet;

This statement imports the JApplet class name that is defined in the javax.swing package. Formally, the name of the JApplet class is not really JApplet - it is the fully qualified name javax.swing.JApplet. You can use the unqualified name only when you import the class or the complete package containing it into your program. You can still reference a class from a package even if you don’t import it though - you just need to use the full class name, javax.swing.JApplet. You could try this out with the applet you saw earlier if you like. Just delete the two import statements from the file and use the full class names in the program. Then recompile it. It should work the same as before. Thus, the fully qualified name for a class is the name of the package in which it is defined, followed by a period, followed by the name given to the class in its definition. You could import the names of all the classes in the javax.swing package with the statement:

import javax.swing.*;

The asterisk specifies that all the class names are to be imported. Importing just the class names that your source code uses makes compilation more efficient, but when you are using a lot of classes from a package you may find it more convenient to import all the names. This saves typing reams of import statements for one thing. We will do this with examples of Java code in the book to keep the number of lines to a minimum. However, there are risks associated with importing all the names in a package. There may be classes with names that are identical to names you have given to your own classes, which would obviously create some confusion when you compile your code.

As I indicated earlier, the standard classes do not appear as files or directories on your hard disk. They are packaged up in a single compressed file, rt.jar, that is stored in the jre/lib directory. This directory is created when you install the JDK on your computer. A .jar file is a Java archive - a compressed archive of Java classes. The standard classes that your executable program requires are loaded automatically from rt.jar, so you don’t have to be concerned with it directly at all.

Classes and Subclasses

Many sets of objects that you might define in a class can be subdivided into more specialized subsets that can also be represented by classes, and Java provides you with the capability to define one class as a more specialized version of another. This reflects the nature of reality. There are always lots of ways of dividing a cake - or a forest. Conifer, for example, could be a subclass of the class Tree. The Conifer class would have all the instance variables and methods of the Tree class, plus some additional instance variables and/or methods that make it a Conifer in particular.

You refer to the Conifer class as a subclass of the class Tree, and the class Tree as a superclass of the class Conifer. When you define a class such as Conifer using another class such as Tree as a starting point, the class Conifer is said to be derived from the class Tree, and the class Conifer inherits all the attributes of the class Tree.

Classes and Data Types

Programming is concerned with specifying how data of various kinds is to be processed, massaged, manipulated, or transformed. Since classes define the types of objects that a program will work with, you can consider defining a class to be the same as defining a data type. Thus, Hat is a type of data, as is Tree, and any other class you care to define. Java also contains a library of standard classes that provide you with a whole range of programming tools and facilities. For the most part then, your Java program will process, massage, manipulate, or transform class objects.

There are some basic types of data in Java that are not classes, and these are called primitive types. I will go into these in detail in the next chapter, but they are essentially data types for numeric values such as 99 or 3.75, for single characters such as A or ?, and for logical values that can be true or false. Java also has classes that correspond to each of the primitive data types for reasons that you will see later on, so there is an Integer class that defines objects that encapsulate integers, for example. Every entity in your Java program that is not of a primitive data type will be an object of a class - either a class that you define yourself, a class supplied as part of the Java environment, or a class that you obtain from somewhere else, such as from a specialized support package.

Operating on Objects

A class object is not just a collection of various items of data. In addition to the parameters that characterize an object, a class specifies what you can do with an object of the class - that is, it defines the operations that are possible on objects of the class. Clearly, for objects to be of any use in a program, you need to decide what you can do with them. The operations that you specify for objects of a given type will depend on what sort of objects you are talking about, the attributes they contain, and how you intend to use them.

For the CowboyHat class, you may want to have operations that you could refer to as putHatOn and takeHatOff, which would have meanings that are fairly obvious from their names, and do make sense for CowboyHat objects. These operations on a particular CowboyHat object would set the value of hatOn for the object. To determine whether your CowboyHat was on or off, you would just need to look at this value. Conceivably, you might also have an operation changeOwner by which you could set the instance variable recording the current owner’s name to a new value.

Of course, for each type of object you can have any operation that makes sense for you. If you want to have a shootHoleIn operation for Hat objects, that’s no problem. You just have to define what that operation does to an object. You are probably wondering at this point how an operation for a class is defined. As you’ll see in detail a bit later, it boils down to a self-contained block of program code called a method that is identified by the name you give to it. You can pass data items - which can be integers, floating-point numbers, character strings, or class objects - to a method, and these will be processed by the code in the method.

A method may also return a data item as a result. Performing an operation on an object amounts to executing the method that defines that operation for the object. Just so you’ll recognize one when you see it, let’s take a look at an example of a complete class definition. The code for the class CowboyHat we have been talking. This code would be saved in a file with the name CowboyHat.java. The name of a file that contains the definition of a class is always the same as the class name, and the extension will be .java to identify that the file contains Java source code. The code for the class definition appears between the braces that follow the identification for the class.

The code for each of the methods in the class also appears between braces. The class has three instance variables, owner, size, and hatOn, and this last variable is always initialized as false. Each object that is created according to this class specification will have its own independent copy of each of these variables in Java program, so each object will have its own unique values for the owner, the hat size, and whether the hat is on or off. I omitted the type parameter in this version of the class to make the code a little bit shorter. The keyword private, which has been applied to each instance variable, ensures that only code within the methods of the class can access or change the values of these directly.

Methods of a class can also be specified as private. Being able to prevent access to some members of a class from outside is an important facility. It protects the internals of the class from being changed or used incorrectly. Someone using your class in another program can get access only to the bits to which you want them to have access. This means that you can change how the class works internally without affecting other programs that may use it. You can change any of the things inside the class that you have designated as private, and you can even change the code inside any of the public methods, as long as the method name and the number and types of values passed to it or returned from it remain the same.

Our CowboyHat class also has five methods, so you can do five different things with a CowboyHat object. One of these is a special method called a constructor, which creates a CowboyHat object - this is the method with the name, CowboyHat, that is the same as the class name. The items between the parentheses that follow the name of the constructor specify data that is to be passed to the method when it is executed - that is, when a CowboyHat object is created.

What Defines a Class of Objects?

A class definition identifies all the parameters that define an object of that particular class, at least, so far as your needs go. Someone else might define the class differently, with a larger or smaller set of parameters to define the same sort of object - it all depends on what you want to do with the class. You decide what aspects of the objects you include to define that particular class of object, and you choose them depending on the kinds of problems that you want to address using the objects of the class. Let’s think about a specific class of objects.

If you were defining a class Hat, for example, you might use just two parameters in the definition. You could include the type of hat as a string of characters such as “Fedora” or “Baseball cap” and its size as a numeric value. The parameters that define an object of a class are referred to as instance variables or attributes of a class, or class fields. The instance variables can be basic types of data such as numbers, but they can also be other class objects. For example, the name of a Hat object could be of type String - the class String defines objects that are strings of characters.

Of course there are lots of other things you could include to define a Hat if you wanted to, color, for example, which might be another string of characters such as “Blue”. To specify a class you just decide what set of attributes meet your requirements, and those are what you use. This is called data abstraction in the parlance of the object-oriented aficionado because you just abstract the attributes you want to use from the myriad possibilities for a typical object. In Java the definition of the class Hat would look something like this:

class Hat {
// Stuff defining the class in detail goes here.
// This could specify the name of the hat, the size,
// maybe the color, and whatever else you felt was necessary.
}

The name of the class follows the word class, and the details of the definition appear between the curly braces. I won’t go into the detail of how the class Hat is defined, since you don’t need it at this point. The lines appearing between the braces above are not code; they are actually program comments, because they begin with two successive forward slashes. The compiler will ignore anything on a line that follows two successive forward slashes in your Java programs, so you’ll use this to add explanations to your programs. Generally, the more useful comments you can add to your programs, the better. You will see in next post that there are other ways you can write comments in Java.

Each object of your class will have a particular set of values defined that characterize that particular object. You could have an object of type CowboyHat, which might be defined by values such as “Stetson” for the type of the hat, “White” for the color, and the size as 7. Although shows CowboyHat objects defined by a set of three values that you would not normally expect to change for a given instance, in general the parameter values that define an object are not necessarily fixed. You would expect the type and size attributes for a particular CowboyHat object to stay fixed since hats don’t usually change their size - at least, not unless it’s raining - but you could have other attributes.

You might have a parameter owner, which would record the owner’s name, so the value stored as the attribute owner could be changed when the hat was sold or otherwise transferred to someone else. You might also have a parameter hatOn, for example, which would indicate whether the hat was on or off the owner’s head; the value true would indicate that the owner was indeed wearing the hat, whereas the value false would mean that the hat had been removed and was just lying about somewhere.