Object « Class « Java Articles

Home
Java Articles
1.Build Deploy
2.Class
3.Core Library
4.Data Types
5.Database JDBC
6.Design
7.Development
8.File Input Output
9.Graphics Desktop
10.J2EE Enterprise
11.J2ME Wireless
12.JVM
13.Language
14.Library Product
15.Network
16.Security
17.SOA Web Services
18.Test
19.Web Development
20.XML
Java Articles » Class » Object 
In the early 1990s, I learned a new software development methodology -- object-oriented programming (OOP). OOP-created software more realistically models real-world entities -- such as cars, bank accounts, and dogs -- in source and executable code. Structured programming emphasizes making an entity's representation fit the constraints of the programming language; OOP emphasizes making the programming language fit the constraints of the representation. For example, in a structured programming language, a car is represented by a set of functions (named bodies of code) for starting, braking, parking, accelerating, and so on. A separate set of variables defines the car's color, number of doors, make, model, and so on. You initialize the car's variables and call some functions that operate on those variables -- and voilà, you have a car!

Throughout this article, we'll examine how to persist your Java objects, starting with the basics and proceeding to the more advanced concepts. We'll learn three different ways to perform serialization -- using the default protocol, customizing the default protocol, and creating our own protocol -- and we'll investigate concerns that arise with any persistence scheme such as object caching, version control, and performance issues.

Since JavaScript is based on objects, a JavaScript function can easily be turned into an object, and a method for that object. So, not only can you create user-defined objects to do your bidding, you can create your own objects that behave in exactly the way you want. And you can create methods that act upon those objects. While this sounds powerful -- and it is -- the process of creating functions, objects, and methods is very easy in JavaScript.

Initialization is important because, historically, uninitialized data has been a common source of bugs. Bugs caused by uninitialized data occur regularly in C, for example, because it doesn't have built-in mechanisms to enforce proper initialization of data. C programmers must always remember to initialize data after they allocate it and before they use it. The Java language, by contrast, has built-in mechanisms that help you ensure proper initialization of the memory occupied by a newly-created object. With proper use of these mechanisms, you can prevent an object of your design from ever being created with an invalid initial state.

I call this object idiom "canonical" because it represents the simplest form an object should take. The idea behind this idiom is to suggest a baseline functionality that you give by default to any object you design. You may adopt this idiom in your own programming practice, or, if you are developing a set of style guidelines for a team or organization, you may want to make the idiom part of those guidelines. The intent of the idiom is not to force programmers to endow every object with this baseline functionality, but simply to define a default functionality for every object. In other words, programmers would be encouraged to make a new object canonical unless they have specific reasons to depart from the idiom in a given, specific case.

In Part 1, I provided an overview of available persistence mechanisms and their implementations, and introduced the Java Data Objects (JDO) approach to persistence. In Part 2, I conclude this series by looking more closely at the two competing JDO standards: the Sun Microsystems JDO and the Castor JDO. Both specifications provide unified, simple, and transparent persistence interfaces between Java application objects and data stores, and create an interesting alternative to entity beans.

In our first article on object pooling, "Build your own ObjectPool in Java to boost app speed," I implemented a pool of database connections. In this article, I'll expand on that example, adding exception propagation and a clean-up thread.

A Java program that makes use of such an object (one that opens a file in its constructor and closes it in its finalizer) may work fine on some JVM implementations. On such implementations, finalization would occur often enough to keep a sufficient number of file handles available at all times. But the same program may fail on a different JVM whose garbage collector doesn't finalize often enough to keep the program from running out of file handles. Or, what's even more insidious, the program may work on all JVM implementations now but fail in a mission-critical situation a few years (and release cycles) down the road.

To maximize the usefulness of these first articles, I will be focusing on how the basic software design principles apply to Java in light of Java's architecture. For example, when I write about designing objects for proper cleanup, I'll discuss Java's finalization and garbage collection mechanisms and show how they affect design. When I write about designing with class variables and class methods, I'll describe Java's mechanisms for class loading and unloading and show how they affect design. For this article, which looks at designing objects for proper initialization, I've written an entire companion article that describes how object initialization works in the Java virtual machine (JVM). In all the articles of this column, I hope to show how the respective architectures of the Java language, virtual machine, and API affect how you should think about designing Java programs.

The need to persist data created at runtime is as old as computing. And the need to store object-oriented data cropped up when object-oriented programming became pervasive. Currently, most modern, nontrivial applications use an object-oriented paradigm to model application domains. In contrast, the database market is more divided. Most database systems use the relational model, but object-based data stores prove indispensable in many applications. Plus, we also have legacy systems that we often need to interface to.

Welcome to the first of several Java 101 quizzes. I've designed each quiz to help you think about concepts introduced in the Java 101 course and to help prepare you for certification. This first quiz covers material from the previous four Java 101 articles (including the article that accompanies this study guide). I will post answers in next month's study guide. However, you can answer the questions presented in this quiz by reading previous articles. I suggest you sit back and relax, as you have one month to complete the quiz. You may begin!

If you do not declare a field with an access specifier keyword, Java assigns the field a default access level, which makes the field accessible within its class and to all classes within the same package. (Think of packages as libraries of classes -- a concept I'll explore in a future article.) Any class not declared in the same package as the class that contains the field cannot access the field. Take a look at the following example:

Of those who have heard of Java, the majority has learned about the language through the popular press. The statement that crops up a lot is that Java is for "programming small applications, or applets, that can be embedded on a Web page." While correct, this definition conveys only one aspect of the new language; it doesn't describe the whole picture. Perhaps Java can be better described as a language designed to build systems -- large systems -- of well-understood portable pieces of executable code that can be combined, in whole or in part, to produce a desirable whole.

The idea of object pooling is similar to the operation of your local library. When you want to read a book, you know that it's cheaper to borrow a copy from the library rather than purchase your own copy. Likewise, it is cheaper (in relation to memory and speed) for a process to borrow an object rather than create its own copy. In other words, the books in the library represent objects and the library patrons represent the processes. When a process needs an object, it checks out a copy from an object pool rather than instantiate a new one. The process then returns the object to the pool when it is no longer needed.

With this knowledge, we can write a helper method -- stringForKey -- and then rewrite get, put, and remove to use this method on the key objects that are passed to them. The next bit of code shows both the helper method and the rewritten get that implements this solution:

This month, we'll take a look at the issue of object management in Java. Since Java is often in competition with C/C++ as a language choice for implementing applications, we'll start out by reviewing the differences in how these languages manage the allocation and deallocation of objects, and examine what impact these differences have on performance. In the remainder of the article, we'll look at three ways to reduce the amount of object churn in your Java programs.

February 10, 2004—An Internet petition has been posted urging an upgrade to the Java Data Objects specification for Java object persistence, amidst a movement by the Java Community Process (JCP) to merge JDO with Enterprise JavaBeans (EJB).

As we'll see in this article, evidence suggests that simple Java persistence will likely stem from the language itself, while sophisticated database functionality will be offered by database vendors.

In general, this one-to-many relationship of objects is defined by the Observer design pattern. Here, many Observers are related to a common object that provides the data of interest. Java provides the java.util.Observable class and the java.util.Observer interface for implementing the Observer/Observable model. The Observable is the object of interest that provides information to a set of Observers. For example, say there is an Observable class that receives messages from a TCP socket. Each message it receives is observed by three Observers: a DisplayObserver, DbObserver, and LogObserver (see the illustration below). The DisplayObserver is responsible for displaying the text of the message to a user screen. The dbObserver is responsible for extracting a SQL string out of the message, processing the SQL statement, and sending a results message back to the original sender. The LogObserver just logs each message that is received.

Like other persistence frameworks, Hibernate has its own object-oriented query language and supports native SQL. In addition, it includes techniques for avoiding query language statements and for executing queries in an object-oriented way. These may be the preferred techniques for developers used to the object-oriented paradigm. The Hibernate criteria query API features two query types that allow programmatic fetching of persistent objects: query by criteria (QBC) and query by example (QBE). This article illustrates a powerful application of both query APIs (see Hibernate reference documentation for more information on the query APIs). Code examples include a Web-based query, with a full roundtrip from a JSP (JavaServer Pages) page to the persistence layer and back without any query language or select statements. This functionality is achieved by combining JavaServer Faces with Hibernate.

If you follow the Java 101 column, you know that we are currently touring Java's object-oriented language basics. So far, this series has covered class declaration, object creation, field/method declaration and access, object composition, object layering, multiple implementation inheritance, the root of all classes, and interfaces (with multiple interface inheritance). In addition, I have introduced the specialized topics of enumerated types and singletons. Read the whole series on object-oriented language basics, and learn what it means for a Java program to be object oriented:

The example above is not unique. Client-side wallet applications, mobile agent applications, and many kinds of mobile computing applications face the same challenges. This month, I will show you how to protect the contents of serialized objects when they traverse or reside on untrusted media. This information will better prepare you for designing and building distributed applications, especially those that use Java serialization to store state information.

Temporary objects are those that have a short lifetime and generally serve no useful purpose other than to act as containers for other data. Programmers generally use temporary objects to pass compound data to -- or return it from -- a method. Part 1 explored how temporary object creations could have a serious negative impact on a program's performance and showed how certain class interface design decisions virtually guarantee temporary object creation. By avoiding those interface constructs, you can dramatically reduce the need to create temporary objects that can sap your program's performance.

There are several mechanisms for achieving object persistence such as object databases and disk files. Similarly, there are many ways to share objects such as writing data to a socket or implementing CORBA- or SOM-compliant models. Each of these alternatives has its merits and should be considered carefully when you are designing your business solution. But there is also an inexpensive-yet-reliable way to deliver copies of objects around the world using technologies and services accessible by all Internet and intranet users. This is Simple Mail Transport Protocol, or SMTP.

I first learned C++ in early 1992 from Borland's World of C++ videotape, which includes a short introduction by Stroustrup. He begins by saying the main goal of C++ was to raise the level of abstraction in programming. As I watched the tape, I was able to grasp the object-oriented concepts and C++ syntax, but I was puzzled by Stroustrup's comment. I was unsure of what he meant by "raising the level of abstraction" and why he found it desirable.

When a resource, such as a database connection, is required, we do not create the object within the client code. Instead, we go to the resource pool and call the getResource() method, which returns one of the available objects within the pool. Normally, the objects in the pool have been created (instantiated) in advance. When we have finished with the object, we must return it to the ResourcePool. Note that, if all the users of a resource pool are not well-behaved code citizens, doing their job and returning the object to the pool, the benefits of the pooling model are broken, and we would be better off without it. So, as good clients of the pool, when we take an object out, we make a vow that we will put it back some time in the future.

Java supports initialization via language features collectively known as initializers. Because Java handles class initialization differently from object initialization, and because classes initialize before objects, we first explore class initialization and class-oriented initializers. Later, we explore object initialization and object-oriented initializers.

The Java Persistence API is a lightweight, POJO-based framework for object-relational mapping. The mapping between Java objects and a relational database is achieved with the help of Java language metadata annotations and/or XML deployment descriptors (usually XML descriptors are optional). The Java Persistence API heavily depends on the metadata annotations.

In this three-part series, I will compare and contrast two fundamental ways that servers can interact with clients: using documents and using objects. In this article, the first of three parts, I'll look primarily at how objects and documents compare when servers interact with client programs that have no user present.

Java's standard class library contains many examples of class block initializers. In addition to Java Database Connectivity's (JDBC) use of that feature, Object uses a class block initializer to register its native methods (such as clone(), getClass(), and hashCode()) with the JVM. The following Object code fragment takes care of that task:

The built-in objects are Date, Math, String, Array, and Object. Each is used in a unique and not-quite-consistent way. Furthermore, newer versions of JavaScript (as found in Netscape "Atlas," currently in beta) implement several of these objects in a different manner than in Netscape 2.0. In this column we will address these built-in objects and how to use them. And we'll make note of the quirks you'll encounter as you apply these objects to your JavaScript pages.

If you follow the Java 101 column, you know that currently we are touring Java's object-oriented language basics. So far, this series has covered class declaration, object creation, field/method (including constructor method) declaration and access, object layering, and inheritance topics. In addition, I have introduced the specialized topics of enumerated types and singletons.

In the real world, it's common to say that a car has an engine, along with tires and other items. In other words, several items, including an engine, compose a car. In contrast, Listing 1 shows that an Engine does not compose a Car, and it is possible to create a Car object without an associated Engine object -- a situation akin to buying a new car without an engine. Why would anyone do that? The error of creating a new Car without an Engine results from both classes being disconnected. The solution to that error is to connect both classes. In Part 3 of this series on object-oriented language basics I will present that solution: composition.

In this article, I show you how to approach this problem from a different angle: by treating individual objects as documents being indexed by an Internet search engine. I demonstrate how to index individual attributes of standard JavaBeans using a popular third-party indexing/searching library and how to quickly retrieve those attributes from storage. The usual database API consisting of find, retrieve, store, and delete methods is provided.

In this article, however, I'd like to consider another possible use for objects besides being tools for programmers. What if objects were the fundamental abstraction with which people (everyday users, not just programmers) interacted with software?

In the JVM instruction set, all objects are instantiated and accessed with the same set of opcodes, except for arrays. In Java, arrays are full-fledged objects, and, like any other object in a Java program, are created dynamically. Array references can be used anywhere a reference to type Object is called for, and any method of Object can be invoked on an array. Yet, in the Java virtual machine, arrays are handled with special bytecodes.

The presence of these new classes in Java 1.1 makes it possible to transmit a running object over the network. To do this, the object, along with those objects that have been referenced, must be serializable -- that is, able to be converted into a byte stream. Fortunately, in Java 1.1, most built-in classes are serializable. Some classes, however, are not (class Object is a prime example). Not to worry. If your class is derived from a non-serializable class, serialization can be achieved by using method defaultWriteObject() in the ObjectOutputStream class, and can then be deserialized by method defaultReadObject() in class ObjectInputStream.

In real life, objects are often comparable. For example, Dad's car is more expensive than Mom's, this dictionary is thicker than those books, Granny is older than Auntie Mollie (well, yeah, living objects, too, are comparable), and so forth. In writing object-oriented programs, there are often needs to compare instances of the same class. And once instances are comparable, they can be sorted. As an example, given two Employees, you may want to know which one has stayed in the organization longer. Or, in a search method for Person instances with a first name of Larry, you may want to display search results sorted by age. This article teaches you how to design your class to make its instances comparable by using the java.lang.Comparable and java.util.Comparator interfaces and presents three examples that illustrate both interfaces.

The sole purpose of Brainy Draw's existence is to demonstrate polymorphism and object serialization in action. As such, Brainy Draw is kept simple, as a learning tool should be. Nevertheless, it satisfies the requirements of being called a graphics tool: Open New, Open, Save, and Undo features, as well as a click and drag feature to easily draw rectangles, ovals, and lines.

Using generics also saves time. If types are explicitly declared, then it's easy for programmers to figure out the return type of a method, or to determine the types of objects stored in a Vector. If generics aren't used, the alternative is a frustrating rummage through the codebase, looking for a helpful comment or two (something like //This vector can only contain instances of Contractor).

Business workflows require reports to be dynamically generated with current data, potentially from multiple sources. Report content, style and output format are typically user-defined and can be dependent on the requester of the report. Many excellent reporting tools are available today that provide report-generation capabilities but are either costly, use proprietary formats, or don't provide much flexibility to customize the content, style, or final output format. This article describes the architecture, design, and implementation of a reporting tool framework that uses XML standards and tools. The implementation demonstrates how reports are dynamically created using XML, XSL, XSLT, Java, and the Apache XML Formatting Objects Processor (FOP).

An excellent example of using metadata is in validating user input with a simple framework. With this framework, the end result is to allow developers to decorate objects like so:

The NakedObjects framework contains an InternalCollection object that stores objects of a given type. In our case, we are storing Address objects. We also must supply the collection with a parent (the owner), creating a one-to-many relationship. The "getter" method introduces a new method: resolve(NakedObject). The resolve method is a static method on AbstractNakedObject that ensures that the given object exists and is fully formed and in memory before it is used. This means that we can construct a Person and lazy-load the addresses on the first call to getAddresses(). We will talk more about persistent object stores in a bit.

One option is to pool the created objects. The benefit of this approach is that we can still have the flexibility of a runtime-generated proxy for advising domain objects while eliminating much of the object-creation performance concerns. A side note is that Spring makes it very easy to pool objects and retrieve objects from that pool. The drawbacks of this approach are that we now have to deal with:

JXPath is a little-known component of the Apache Commons library that simplifies querying of sets of Java objects by using an XPath-based syntax. This article demonstrates how to use JXPath to replace complex Java code with simple expression-based queries, and how to make use of this in practical scenarios such as JSPs, templates (such as Velocity), and monitoring/management applications.

At first, Java seems to follow the common approach to define object identity through its references. Running a program like this:

Every regular object that you create has a reference to its class definition object; that is, Java objects are conscious--they know their identity. Method getClass defined in class Object can be used to obtain an object's class definition:

One of the nice things about programming in Java is that the language and its class library are designed to provide practical solutions to real object-oriented programming problems. In the object programming community, many of these solutions have been well documented as design patterns; each pattern is a generic solution to a common problem. One such pattern is known as the Observer pattern, which is a solution to the updating problem that arises when some objects have a dependency relationship with others. Java provides a ready-made implementation for this pattern through the Observable class and the Observer interface.

Occasionally, bundles of class methods or bundles of constants Use class members to control access to objects, provide utility methods, or offer bundles of constants. Examples of controlling access to objects, static factory methods, singleton pattern. Hmm, providing access to objects seems to all fall under the category of static factory methods.

This scheme is intended to work with JAR files not with directory-based class hierarchies. There is no easy way to compute a digest over the entire set of directory trees from which HTTP can serve class files. If you are willing to serve things up as JAR files, the normal approach in Jini systems anyway, then you as the server locally compute the digests. You must have local access to the JAR file, so you don't have to worry about its integrity yourself. So offline, or online, or through any means that you trust, you get the JAR file and compute its digest.

Create an inheritance hierarchy of Rodent: Mouse, Gerbil, Hamster, etc. In the base class, provide methods that are common to all Rodents, and override these in the derived classes to perform different behaviors depending on the specific type of Rodents. In the main() method of a class named Problem4, create an array of Rodent, fill it with different specific types of Rodents, and call your base-class methods to see what happens.

Objects are invisible machines that programmers use as tools. When you design an object, you design a machine for programmers. I feel thinking of objects as machines is helpful, because it encourages you to focus not only on functionality when you design objects, but also on usability.

One of the main disadvantages of the object approach, in my opinion, is that HTML is a lot easier to write than Java. The release of Mosaic, the first browser to support graphics in Webpages, unleashed an explosion in Webpage creation. I wouldn't expect that the release of a Cyberspace client, such as a browser plug-in that understands objects and places, would unleash a similar explosion in the creation of object-based services. I believe one significant hindrance to the growth of a Web of objects is simply that writing an object-based service is harder than writing a Webpage-based service.

Another difference between the source files of C++ and the source files of Java is that Java source is written in Unicode, a 16-bit international character set standard. If you create an ASCII source file, the Java compiler will treat the ASCII characters as if they were the equivalent Unicode characters. This will be discussed at greater length in Chapter 3.

Another relationship similar to composition is aggregation. Like composition, the aggregation relationship entails a front-end object holding references in instance variables to back-end objects. The difference is intent. In a composition relationship, the front-end objects enlist the help of the back-end objects to fulfill the front-end's semantic contract. In an aggregation relationship, front-end objects merely serve as containers for back-end objects. Front-end objects in an aggregation relationship don't invoke methods on back-ends, they just hold them.

Modeling the relationships between types is a fundamental part of the process of object-oriented design. This chapter shows you how to model relationships using composition and inheritance. It describes many facets of inheritance in Java, including abstract classes and final classes. [bv:need better intro]

In a class named Dictionary (in a file named Dictionary.java), create a class (static) variable named WORD_COUNT of type long. Make WORD_COUNT public and final. Initialize WORD_COUNT in a static initializer to the value 1234567. (A static initializer is just an "= " after the declaration of the static variable and before the semicolon. Create a static initialization block inside Dictionary that prints the value of WORD_COUNT out to the standard output with this string message: "Dictionary: WORD_COUNT == ".

Objects and Java is a tutorial of Java programming (currently being written) that eventually will serve as the text for my five-day Objects and Java Seminar.

Another basic difference between the object and document approach is the nature of the contract between the client and server. For network-mobile documents, the protocol (including the data models of any documents) forms the contract between the client and server. For network mobile objects, the object's interface forms the contract. One important advantage of objects is that it is easier to evolve the object's contract over time compared to the document's or the protocol's contract.

What's the difference really? In the subsequent two articles in this series, I'll delve into the advantages and disadvantages of objects versus documents. At this point, however, I'd like to try and identify the crux of the difference between the two approaches.

Java allows you to separate the interface and implementation of objects by providing you with access levels to attach to the instance variables and methods of a class. The access level of an instance variable or method determines what other classes of object, if any, can access that instance variable or method.

In the Cyberspace demo, I launched each Jini service and service UI in its own JVM. The Java application that I ran to start the JVM for a Jini service and service UI was named ObjectLauncher. ObjectLauncher was fired up by CyberspaceConsole. Here's the code for ObjectLauncher:

Given that you don't know when objects will be garbage collected, but you do know that finalizable objects will be finalized as they are garbage collected, you can make the following grand deduction:

The creation of if-else constructs like the one shown above are possible in Java because of the instanceof operator, which allows you to check whether an object is an instance of a certain class. Here the instanceof operator is being abused, and the code should be reorganized to use polymorphism. The instanceof operator, and the situations in which it should be used, will be discussed later in this chapter.

In the PackagesAccess/examples/ex1/com/artima/somelib directory of the example source code, edit SplitNameReturnVal.java. Make one small change to this file: change the access level on the class (SplitNameReturnVal) from public to package access.

The significance of the object, therefore, is that they are for people, not for computers. The reason objects exist is to help human programmers do their jobs. This is important to keep in mind when designing APIs, because if objects are for people, then object interfaces are for people too. (After all, API means Application Programmer Interface) When you design an API, you are designing for the benefit of human programmers.

Create a Java application named Counter that prints out the numbers between 1 and 100, inclusive. (i.e.: 1, 2, 3, ..., 99, 100)

One of the most basic object-oriented ideas is encapsulation -- associating data with code that manipulates the data. The data, stored in instance variables, represents the object's state. The code, stored in instance methods, represents the object's behavior. Because of encapsulation, therefore, you can think of objects as either bundles of data, bundles of behavior, or both. To reap the greatest benefit from encapsulation, however, you should think of objects primarily as bundles of behavior, not bundles of data. You should think of objects less as carriers of information, embodied in the data, and more as providers of services, represented by the behavior.

Create a Java application named Problem4 that has a private static float variable named coefficient. Place the coefficient variable first in the class. Second in the class, place a main() method that prints out the value of coefficient. Third in the class, place a static initialization block that sets coefficient to 2.0.

The event generator idiom allows one or more listener objects to be notified of state changes or events provided by an event generator. The number and type of listeners may be unknown at compile-time, and can vary throughout the course of execution. The loose coupling of listeners and event generators make the code easier to change or reuse in changing situations.

The fourth way to think about packages is as a tool that can help you separate interface from implementation. You can grant special access privileges between types within the same package, and you can declare entire types to be accessible only to other types within the same package. The full details of how to do this will be given later in this chapter as part of a discussion of Java's access levels.

Write an application named Prettifier.java that reads lines of text from the standard input. For each line read in, prepend the line with the line number followed by a single space, and print this to the standard output.

Up to this point, the examples used in this book have done no explicit initialization of instance variables. This is perfectly legal in Java, and results in predictable default initial values, which are based only upon the type of the variable. Table 4-1 shows the default initial values for each of the variable types. (These are the default initial values for both instance and class variables. Initialization of class variables will be discussed in depth in Chapter 6.)

In the last column, I focused on what I call object responsibility. Object responsibility refers to the design concept that requires all objects to provide (or at least know how to find) any services that it may need to function properly. This concept is very important when it comes to moving objects across a network. One of these responsibilities involves the way that an object constructs itself. Proper construction puts the object in a safe-state and is efficient with computer memory. In this article, you will explore the art and science of constructing objects.

A goal of every object-oriented design is to put the object into what is called a safe-state. By this we mean that the object is in a state that will not cause the system to be unstable. There are several mechanisms that are provided to assist in the construction of safe objects. In this article we explore some of the topics.

In this month's article, we continued our discussion about encapsulation and data hiding. Controlling access to all attributes is one of the most important concepts of object-oriented design. By using methods to control access to attributes we can provide a much higher level of security for your class as well as providing many programming advantages.

An economical way to address performance is by creating lightweight objects - in other words, objects that only initialize what they need when needed. An object should be a full-featured way for the user to utilize a specific kind of information; however, providing a full-featured solution doesn't mean that you have to completely prepare all of the features. You can wait until the feature of the object is needed and then initialize it.

Notice that there is only one method for each class: draw( ). Here is the important point regarding polymorphism and an object being responsible for itself: The concrete classes themselves have responsibility for the drawing function. The Shape class does not provide the code for drawing; the Circle, Rectangle, and Star classes do this for themselves. Here is some code to prove it:

This and the next few articles summarize patterns that are related to creating objects. The issues that they address involve dynamically deciding which class to instantiate or to which objects an object will delegate a responsibility. These patterns tell us how to structure and encapsulate these decisions. This article discusses a pattern called Object Pool, which comes from Volume 1 of Patterns in Java.

In the previous column, you covered several advanced techniques about connecting to a database using Java Database Connectivity (JDBC). Storing data to a database is just one of many ways to save data—a concept called data persistence. In this article, you will explore another aspect of object persistence/serialization, specifically how do you move an object across a client-server connection? You may want to store an object on a machine that is connected to your application via a network connection. You will create a very simple client/server application and transfer an object from the client to the server and back.

In Figure 4, the name on each of the objects represents the Draw method for the Circle, Star, and Square objects, respectively. When we design this Shape system it would be very helpful to standardize how we use the various shapes. Thus, we could decide that if we want to draw a shape, no matter what shape, we will invoke a method called draw. If we adhere to this decision, whenever we want to draw a shape, only the Draw method needs to be called, regardless of what the shape is. Here lies the fundamental concept of polymorphism it is the individual object's responsibility, be it a Circle, Star, or Square, to draw itself.

Creating wrappers might seem like overkill, but there are many advantages to writing them. To illustrate, there are many middleware products on the market today. Consider the problem of mapping objects to a relational database. There are OO databases on the market today that are perfect for OO applications. However, there is one itty-bitty problem: Most companies have years of data in legacy relational database systems. How can a company embrace OO technologies and stay on the bleeding edge when its data is in a relational database?

By creating these packages, you provide the users with very specific guidelines so that they can utilize your programming interfaces. In fact, unless you are very clear as to what these interfaces are, there will be no way for anyone to effectively employ the classes that you meticulously create. Thus, it is vitally important to put a significant amount of thought into how to design these interfaces?which are defined by what are called object signatures.

The Java primitives that you just covered are not objects. By definition, objects have attributes and behaviors, which the primitive data types don't have. Other than these primitives, everything else in Java is an object. Whereas a character represents a single Unicode value, you can treat a string as an object that contains a collection of characters.

Listing 14 invokes the setAction method on the JButton object to register the other Action object on that JButton. Thus, two different Action objects are registered on the two JButton objects on the toolbar.

In the previous column, we covered the basic Java technology required to construct a simple client/server example. The example illustrated how an object is constructed on one machine and then marshaled across a network to another machine. The process involves serializing the object so that it can be transferred across a wire and then reconstructed on the other side. In this article, we will further explore the process of moving an object across a client-server connection. Specifically, we will investigate what happens when the unexpected occurs. We will first review the client/server application that we began in the last column, and then we will throw in some wrinkles.

Until the release of Java 2 Standard Edition (J2SE) Version 1.4, Java objects could only be serialized to a proprietary, binary format. Now, Java objects can be serialized as XML documents, a feature of the new long-term persistence API for JavaBeans. This article illustrates how to use this new feature.

Once there are effective standards for interoperability and security, developers will be faced by many new opportunities and challenges in the relation of network-enabled, service-based computing. See the next article Object lessons: the future of OO design.

Today, data persistence for object-oriented systems is an incredibly cumbersome task to deal with when building many kinds of applications. The developer must map objects to database tables, XML files or use some other non-OO way to represent data, destroying encapsulation completely. One solution to this problem is object prevalence.

Large applications require using persistent HttpSessions. However, there is a cost. An HttpSession must be read by the servlet whenever it is used and rewritten whenever it is updated. This involves serializing the data and reading it from and writing it to a database. In most applications, each servlet requires only a fraction of the total session data. However, by storing the data in the HttpSession as one large object graph, an application forces WebSphere® Application Server to process the entire HttpSession object each time.

At this point, you're probably wondering why I'm even talking about memory management, aliases, and object ownership. After all, garbage collection is one of the core features of the Java language, and memory management is a chore of the past! Just let the garbage collector handle it; that's its job. Those who have been freed from the chore of memory management don't want to go back, and those who never had to deal with it can't even imagine how horrible life must have been as a programmer in the bad old days -- like 1996.

w__w__w.___ja___v_a2s.c___o_m___ | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.