Welcome to the Core Java Technologies Tech Tips, April 8, 2003. Here you'll get tips on using core Java technologies and APIs, such as those in Java 2 Platform, Standard Edition (J2SE). This issue covers:
These tips were developed using Java 2 SDK, Standard Edition, v 1.4. This issue of the Core Java Technologies Tech Tips is written by Glen McCluskey. DESTROYING OBJECTS
In Java programming, you create class objects and arrays using
the Let's start by presenting a comparative example that shows how another object-oriented language (C++) handles object destruction:
Class A has a destructor The output of the program looks like this:
call A::A 7a32c8
call A::A 12ff50
call A::~A 12ff50
call A::~A 7a32c8
The output shows the memory addresses of objects at construction and destruction time. The Java language handles things a little differently. In the first place, there are no stack-based objects, only references to objects. In other words, objects are allocated dynamically, and references (pointers) to those objects may be stored on the stack. Another really big difference is that there is no delete operator corresponding to the new operator that is used to allocate objects. Unreferenced objects ("garbage") are automatically reclaimed as needed, through a process known as garbage collection. For example, in this code:
void f() {
String str = new String();
}
the string object becomes garbage as soon as the f method completes execution. There is no way for the program containing f to reference the string, and so the memory used for the string object can be reclaimed. The actual process of garbage collection is scheduled in a way to minimize garbage collector overhead. It will probably take place at a later time (or not at all). When garbage collection happens, the Java virtual machine* determines which objects in the application are live, that is, which objects are reachable from running code. Objects that are not reachable are subject to reclamation, and their memory is reused. Because there is no delete operator, and no notion of stack-based objects going out of scope, it is only at garbage collection time that a call to a destructor is meaningful. This model has several implications. One is that you don't usually need to worry about space management issues. There is no delete operator available, and it's usually a bad idea to explicitly invoke garbage collection. Sometimes it's useful to deliberately nullify object references, to help out the garbage collector. For example, if you have a stack of object references, and you pop an element from the stack, it's important to set the just-vacated stack slot reference to null. Here's some sample code:
Popping an element from the stack means that the element is no longer on the stack, but the object reference will linger unless nullified or overwritten by a subsequent stack push. The collection classes take care of this operation for you.
Another point concerns management of system resources. When
garbage collection takes place, unused object and array space is
reclaimed. But what happens if an object makes reference to
other system resources, such as file descriptors? How are such
resources reclaimed? One way of handling this situation is to
define an explicit For more information about garbage collection, see section 12.1, Garbage Collection, section 12.2, A Simple Model, section 12.3, Finalization, and section 12.4, Interacting With the Garbage Collector, in "The Java Programming Language Third Edition" by Arnold, Gosling, and Holmes. PREPROCESSING AND THE JAVA LANGUAGEThe widely-used programming languages C and C++ make heavy use of what is called a preprocessor. The preprocessor makes an initial scan over the source code, and certain preprocessor directives are treated in a special way. For example, the directive:
#define X 37
results in the token The preprocessor is used to define constants, to include the contents of other source files (header files), to specify conditional compilation, and so on. Preprocessing is a useful mechanism, but it does have some problems associated with it. The Java language has no preprocessor, and because of this, it takes a different approach in these areas.
Let's start by looking at the preprocessor
#include <stdio.h>
Typically you use a directive like this to gain access to
constants and function declarations found in a header file such
as
import java.util.*;
import java.io.FileInputStream;
and there is also an implicit declaration:
import java.lang.*;
supplied for you at the top of every Java source file. Information such as constants, typically found in header files, is folded into Java source code. Import declarations do not use textual inclusion, but simply make the types in the specified package available. This approach tends to be much cleaner than actually importing huge masses of source code from a large number of header files. Another way that a C/C++ preprocessor is used is to define global constants and macros, for example:
#define X 100
#define perc(a,b) ((a) * 100.0 / (b))
The Java equivalent of these definitions might look like this:
This Java language approach illustrated in the
various C++ compilers will produce a warning message. However, this usage is probably an outright error, typically triggered by defining the same constant with different values across multiple header files. Note in this example that static methods have guaranteed function semantics. For example, method arguments are evaluated only once. Macros fall short in this regard.
One issue with this example is whether the Another area to look at is modifying the operation of a program by the use of compiler or run time directives. For example, if a C program is compiled like this:
$ cc -DABC file.c
and
#ifdef ABC
...
#endif
the behavior of the program is modified based on the presence of
This approach is also useful with Java programs, although there
is less need for it. One classic use of The following code illustrates what is sometimes called "conditional compilation":
Here you have a "global" boolean variable
int x = 0;
while (false)
x = 3;
is illegal ("
int x = 0;
if (false)
x = 3;
is legal.
Note that a compiler can throw away the block of code inside of
"
$ javap -c -classpath . PPDemo2
the result is:
Notice that there's no trace of the You can also use the Java launcher and libraries to specify the value of a system property. You can then use this value to modify the logic of your application. Here's an example:
If you compile this code, and then say:
$ java -Dproperty1=123 PPDemo3
the effect will be to set the value of the system property for use within the program, that is:
property1 is 123
Assertions are another area where you might want to alter the behavior of a program from outside. In C/C++, an assertion is specified by saying:
assert(x >= 100);
The Java language uses the assert keyword to specify assertions. Here's an example:
You need to compile this code with:
$ javac -source 1.4 PPDemo4.java
and then run it by saying:
$ java -ea PPDemo4
You should see the following result:
*** assertion failed ***
Normally you wouldn't catch an
If you don't specify For more information about Java language approaches to preprocessing, see section 1.4, Named Constants, section 13.2, Type Imports, and section 18.1.2, System Properties, in "The Java Programming Language Third Edition" by Arnold, Gosling, and Holmes. Also see section 14.20, "Unreachable Statements" in "The Java Language Specification Second Edition" by Gosling, Joy, Steele, and Bracha. And see item 21 "Replace enum constructs with classes" in "Effective Java Programming Language Guide" by Joshua Bloch. IMPORTANT: Please read our Terms of Use, Privacy, and Licensing policies: http://www.sun.com/share/text/termsofuse.html http://www.sun.com/privacy/ http://developer.java.sun.com/berkeley_license.html Comments? Send your feedback on the Core Java Technologies Tech Tips to: jdc-webmaster@sun.com Subscribe to other Java developer Tech Tips: - Enterprise Java Technologies Tech Tips. Get tips on using enterprise Java technologies and APIs, such as those in the Java 2 Platform, Enterprise Edition (J2EE). - Wireless Developer Tech Tips. Get tips on using wireless Java technologies and APIs, such as those in the Java 2 Platform, Micro Edition (J2ME). To subscribe to these and other JDC publications: - Go to the JDC Newsletters and Publications page, choose the newsletters you want to subscribe to and click "Update". - To unsubscribe, go to the subscriptions page, uncheck the appropriate checkbox, and click "Update". ARCHIVES: You'll find the Core Java Technologies Tech Tips archives at: http://java.sun.com/jdc/TechTips/ Copyright 2003 Sun Microsystems, Inc. All rights reserved. 4150 Network Circle, Santa Clara, CA 95054 USA. This document is protected by copyright. For more information, see: http://java.sun.com/jdc/copyright.html Trademark Information: http://www.sun.com/suntrademarks/ Java, J2EE, J2SE, J2ME, and all Java-based marks are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States and other countries. * As used in this document, the terms "Java virtual machine" or "JVM" mean a virtual machine for the Java platform. | |||||||||||||||||||||
Oracle is reviewing the Sun product roadmap and will provide guidance to customers in accordance with Oracle's standard product communication policies. Any resulting features and timing of release of such features as determined by Oracle's review of roadmaps, are at the sole discretion of Oracle. All product roadmap information, whether communicated by Sun Microsystems or by Oracle, does not represent a commitment to deliver any material, code, or functionality, and should not be relied upon in making purchasing decisions. It is intended for information purposes only, and may not be incorporated into any contract.
|
| ||||||||||||