Getting Started With Java
Getting Started With Java
Borland ®
™
VERSION 5 JBuilder
Borland Software Corporation
100 Enterprise Way, Scotts Valley, CA 95066-3249
www.borland.com
Refer to the file DEPLOY.TXT located in the redist directory of your JBuilder product for a complete list of files that
you can distribute in accordance with the JBuilder License Statement and Limited Warranty.
Borland Software Corporation may have patents and/or pending patent applications covering subject matter in this
document. The furnishing of this document does not give you any license to these patents.
COPYRIGHT © 1997, 2001 Borland Software Corporation. All rights reserved. All Borland brand and product names
are trademarks or registered trademarks of Borland Software Corporation in the United States and other countries.
Other product names are trademarks or registered trademarks of their respective holders.
For third-party conditions and disclaimers, see the Release Notes on your JBuilder product CD.
Printed in the U.S.A.
JBE0050WW21000gsjava 2E1R0401
0102030405-9 8 7 6 5 4 3 2 1
PDF
Contents
Chapter 1 Chapter 4
Introduction 1-1 Java language control 4-1
Documentation conventions . . . . . . . . . . . 1-3 Terms . . . . . . . . . . . . . . . . . . . . . . . . . 4-1
Contacting Borland developer support . . . . . 1-4 String handling . . . . . . . . . . . . . . . . . 4-1
Online resources . . . . . . . . . . . . . . . . 1-5 Type casting and conversion . . . . . . . . . . 4-2
World Wide Web . . . . . . . . . . . . . . 1-5 Return types and statements . . . . . . . . . . 4-3
Borland newsgroups . . . . . . . . . . . . 1-5 Flow control statements . . . . . . . . . . . . 4-3
Usenet newsgroups. . . . . . . . . . . . . 1-5 Applying concepts . . . . . . . . . . . . . . . . . 4-4
Reporting bugs . . . . . . . . . . . . . . . 1-6 Escape sequences . . . . . . . . . . . . . . . . 4-4
String handling. . . . . . . . . . . . . . . . 4-4
Chapter 2 Determining access . . . . . . . . . . . . . . . 4-6
Java language elements 2-1 Handling methods . . . . . . . . . . . . . . . 4-7
Terms . . . . . . . . . . . . . . . . . . . . . . . . 2-1 Using type conversions . . . . . . . . . . . . . 4-8
Identifier. . . . . . . . . . . . . . . . . . . . . 2-1 Implicit casting . . . . . . . . . . . . . . . . 4-8
Data type . . . . . . . . . . . . . . . . . . . . 2-2 Explicit conversion . . . . . . . . . . . . . 4-8
Primitive data types . . . . . . . . . . . . 2-2 Flow control . . . . . . . . . . . . . . . . . . . 4-9
Composite data types . . . . . . . . . . . 2-3 Loops . . . . . . . . . . . . . . . . . . . . . 4-9
Strings . . . . . . . . . . . . . . . . . . . . . . 2-3 Loop control statements. . . . . . . . . . 4-11
Arrays . . . . . . . . . . . . . . . . . . . . . . 2-4 Conditional statements . . . . . . . . . . . . 4-12
Variable . . . . . . . . . . . . . . . . . . . . . 2-4 Handling exceptions . . . . . . . . . . . . . 4-13
Literal . . . . . . . . . . . . . . . . . . . . . . 2-4
Applying concepts . . . . . . . . . . . . . . . . . 2-5 Chapter 5
Declaring variables. . . . . . . . . . . . . . . 2-5
Methods . . . . . . . . . . . . . . . . . . . . . 2-5 The Java class libraries 5-1
Java 2 Platform editions . . . . . . . . . . . . . . 5-1
Chapter 3 Standard Edition. . . . . . . . . . . . . . . . . 5-2
Java language structure 3-1 Enterprise Edition . . . . . . . . . . . . . . . . 5-2
Terms . . . . . . . . . . . . . . . . . . . . . . . . 3-1 Micro Edition . . . . . . . . . . . . . . . . . . 5-2
Keywords . . . . . . . . . . . . . . . . . . . . 3-1 Java 2 Standard Edition packages . . . . . . . . . 5-3
Operators . . . . . . . . . . . . . . . . . . . . 3-2 The Language package: java.lang . . . . . . . 5-4
Comments. . . . . . . . . . . . . . . . . . . . 3-3 The Utility package: java.util. . . . . . . . . . 5-4
Statements. . . . . . . . . . . . . . . . . . . . 3-5 The I/O package: java.io . . . . . . . . . . . . 5-4
Code blocks . . . . . . . . . . . . . . . . . . . 3-5 The Text package: java.text . . . . . . . . . . . 5-4
Understanding scope . . . . . . . . . . . . . 3-5 The Math package: java.math . . . . . . . . . 5-5
Applying concepts . . . . . . . . . . . . . . . . . 3-6 The AWT package: java.awt . . . . . . . . . . 5-5
Using operators. . . . . . . . . . . . . . . . . 3-6 The Swing package: javax.swing . . . . . . . 5-5
Arithmetic operators . . . . . . . . . . . . 3-7 The Javax packages: javax . . . . . . . . . . . 5-6
Logical operators . . . . . . . . . . . . . . 3-8 The Applet package: java.applet. . . . . . . . 5-6
Assignment operators . . . . . . . . . . . 3-9 The Beans package: java.beans. . . . . . . . . 5-7
Comparison operators . . . . . . . . . . . 3-10 The Reflection package: java.lang.reflect . . . 5-7
Bitwise operators . . . . . . . . . . . . . . 3-10
The SQL package: java.sql . . . . . . . . . . . 5-7
?:—The ternary operator . . . . . . . . . . 3-12
The RMI package: java.rmi . . . . . . . . . . . 5-8
Using methods . . . . . . . . . . . . . . . . . 3-12
The Networking package: java.net . . . . . . 5-8
Using arrays. . . . . . . . . . . . . . . . . . . 3-13
The Security package: java.security . . . . . . 5-8
Using constructors . . . . . . . . . . . . . . . 3-13
Member access . . . . . . . . . . . . . . . . . 3-14
Arrays . . . . . . . . . . . . . . . . . . . . 3-15
i
Chapter 6 Chapter 9
Object-oriented programming An introduction to the Java Virtual
in Java 6-1 Machine 9-1
Classes . . . . . . . . . . . . . . . . . . . . . . . 6-2 Java VM security . . . . . . . . . . . . . . . . . . 9-3
Declaring and instantiating classes. . . . . . 6-2 The security model . . . . . . . . . . . . . . . 9-3
Data members . . . . . . . . . . . . . . . . . 6-3 The Java verifier . . . . . . . . . . . . . . . 9-3
Class methods . . . . . . . . . . . . . . . . . 6-3 The Security Manager and the
Constructors and finalizers . . . . . . . . . . 6-4 java.security Package . . . . . . . . . . . 9-4
Case study: A simple OOP example . . . . . 6-4 The class loader . . . . . . . . . . . . . . . 9-6
Class inheritance . . . . . . . . . . . . . . . . 6-9 What about Just-In-Time compilers? . . . . . 9-6
Calling the parent’s constructor . . . . . . 6-11
Access modifiers . . . . . . . . . . . . . . . . 6-11 Chapter 10
Access from within class’s package . . . . 6-12
Access outside of a package . . . . . . . . 6-12
Working with the Java Native
Accessor methods . . . . . . . . . . . . . . . 6-13 Interface (JNI) 10-1
Abstract classes . . . . . . . . . . . . . . . . . 6-16 How JNI works . . . . . . . . . . . . . . . . . . 10-2
Polymorphism . . . . . . . . . . . . . . . . . . . 6-17 Using the native keyword . . . . . . . . . . . . 10-2
Using interfaces. . . . . . . . . . . . . . . . . 6-17 Using the javah tool. . . . . . . . . . . . . . . . 10-3
Adding two new buttons . . . . . . . . . . . 6-21
Running your application . . . . . . . . . . . 6-23 Chapter 11
Java packages. . . . . . . . . . . . . . . . . . . . 6-23 Java language quick reference 11-1
The import statement . . . . . . . . . . . . . 6-23
Java 2 platform editions . . . . . . . . . . . . . 11-1
Declaring packages. . . . . . . . . . . . . . . 6-24
Java class libraries. . . . . . . . . . . . . . . . . 11-2
Chapter 7 Keywords . . . . . . . . . . . . . . . . . . . . . 11-3
Data and return types and terms . . . . . . 11-3
Threading techniques 7-1 Packages, classes, members, and
The lifecycle of a thread . . . . . . . . . . . . . . 7-2 interfaces . . . . . . . . . . . . . . . . . . . 11-3
Customizing the run() method . . . . . . . . 7-2 Access modifiers. . . . . . . . . . . . . . . . 11-4
Subclassing the Thread class . . . . . . . 7-2 Loops and loop controls . . . . . . . . . . . 11-4
Implementing the Runnable interface . . 7-3 Exception handling . . . . . . . . . . . . . . 11-5
Defining a thread . . . . . . . . . . . . . . . . 7-5 Reserved . . . . . . . . . . . . . . . . . . . . 11-5
Starting a thread . . . . . . . . . . . . . . . . 7-6 Converting and casting data types . . . . . . . 11-5
Making a thread not runnable . . . . . . . . 7-6 Primitive to primitive . . . . . . . . . . . . . 11-6
Stopping a thread. . . . . . . . . . . . . . . . 7-7 Primitive to String . . . . . . . . . . . . . . . 11-7
Thread priority . . . . . . . . . . . . . . . . . . . 7-7 Primitive to reference . . . . . . . . . . . . . 11-8
Time slicing . . . . . . . . . . . . . . . . . . . 7-7 String to primitive . . . . . . . . . . . . . . .11-10
Synchronizing threads. . . . . . . . . . . . . . . 7-8 Reference to primitive . . . . . . . . . . . .11-12
Thread groups . . . . . . . . . . . . . . . . . . . 7-8 Reference to reference. . . . . . . . . . . . .11-13
Escape sequences . . . . . . . . . . . . . . . . .11-18
Chapter 8 Operators . . . . . . . . . . . . . . . . . . . . .11-18
Serialization 8-1 Basic operators. . . . . . . . . . . . . . . . .11-18
Why serialize? . . . . . . . . . . . . . . . . . . . 8-1 Arithmetic operators . . . . . . . . . . . . .11-19
Java serialization . . . . . . . . . . . . . . . . . . 8-2 Logical operators . . . . . . . . . . . . . . .11-20
Using the Serializable interface . . . . . . . . 8-2 Assignment operators. . . . . . . . . . . . .11-20
Using output streams . . . . . . . . . . . . . . . 8-4 Comparison operators . . . . . . . . . . . .11-21
ObjectOutputStream methods . . . . . . . . 8-5 Bitwise operators . . . . . . . . . . . . . . .11-21
Using input streams . . . . . . . . . . . . . . . . 8-6 Ternary operator. . . . . . . . . . . . . . . .11-22
ObjectInputStream methods . . . . . . . . . 8-8
Writing and reading object streams . . . . . . . 8-8 Index I-1
ii
Chapter
1
Introduction
Chapter1
Introduction 1-1
Introduction
Each section is divided into two main parts: “Terms” and “Applying
concepts.” “Terms” builds your vocabulary, introducing new concepts
that add to concepts you already understand. “Applying concepts”
demonstrates the actual use of concepts that have been presented up to
that point, providing a repeated, more complex exposure. Some
concepts are revisited several times, at increasing levels of complexity.
This iterative design improves understanding and retention.
• Chapter 5, “The Java class libraries”
This chapter presents an overview of the Java 2 class libraries and the
Java 2 Platform editions.
• Chapter 6, “Object-oriented programming in Java”
This chapter introduces the object-oriented features of Java. You will
create Java classes, instantiate objects, and access member variables in a
short tutorial. You will learn to use inheritance to create new classes,
use interfaces to add new capabilities to your classes, use
polymorphism to make related classes respond in different ways to the
same message, and use packages to group related classes together.
• Chapter 7, “Threading techniques”
A thread is a single sequential flow of control within a program. One of
the powerful aspects of the Java language is you can easily program
multiple threads of execution to run concurrently within the same
program. This chapter explains how to create multithreaded programs,
and provides links to other resources with more in-depth information.
• Chapter 8, “Serialization”
Serialization saves and restores a Java object’s state. This chapter
describes how to serialize objects using Java. It describes the
Serializable interface, how to write an object to disk, and how to read
the object back into memory again.
• Chapter 9, “An introduction to the Java Virtual Machine”
The JVM is the native software that allows a Java program to run on a
particular machine. This chapter explains the JVM’s general structure
and purpose. It discusses the major roles of the JVM, particularly in
Java security. It goes into more detail about three specific security
features: the Java verifier, the Security Manager, and the Class Loader.
• Chapter 10, “Working with the Java Native Interface (JNI)”
This chapter explains how to invoke native methods in Java
applications using the Java Native Method Interface (JNI). It begins by
explaining how the JNI works, then discusses the native keyword and
how any Java method can become a native method. Finally, it examines
the JDK’s javah tool, which is used to generate C header files for Java
classes.
Documentation conventions
The Borland documentation for JBuilder uses the typefaces and symbols
described in the table below to indicate special text.
Typeface and symbol conventions:
Typeface Meaning
Monospace type Monospaced type represents the following:
• text as it appears onscreen
• anything you must type, such as "Enter Hello World in the Title
field of the Application wizard."
• file names
• path names
• directory and folder names
• commands, such as SET PATH, CLASSPATH
• Java code
• Java data types, such as boolean, int, and long.
• Java identifiers, such as names of variables, classes, interfaces,
components, properties, methods, and events
• package names
• argument names
• field names
• Java keywords, such as void and static
Bold Bold is used for java tools, bmj (Borland Make for Java), bcj
(Borland Compiler for Java), and compiler options. For example:
javac, bmj, -classpath.
Italics Italicized words are used for new terms being defined, for book
titles, and occasionally for emphasis.
Keycaps This typeface indicates a key on your keyboard. For example,
“Press Esc to exit a menu.”
[] Square brackets in text or syntax listings enclose optional items.
Do not type the brackets.
<> Angle brackets in text or syntax listings indicate a variable string;
type in a string appropriate for your code. Do not type the angle
brackets. Angle brackets are also used for HTML tags.
... In code examples, an ellipsis indicates code that is missing from
the example. On a button, an ellipsis indicates that the button
links to a selection dialog.
Introduction 1-3
Contacting Borland developer support
Item Meaning
Paths All paths in the documentation are indicated with a forward
slash (/).
For the Windows platform, use a backslash (\).
Home directory The location of the home directory varies by platform.
• For UNIX and Linux, the home directory can vary. For
example, it could be /user/[username] or /home/[username]
• For Windows 95/98, the home directory is C:\Windows
• For Windows NT, the home directory is C:\Winnt\Profiles\
[username]
• For Windows 2000, the home directory is C:\Documents and
Settings\[username]
.jbuilder5 directory The .jbuilder5 directory, where JBuilder settings are stored, is
located in the home directory.
jbproject directory The jbproject directory, which contains project, class, and
source files, is located in the home directory. JBuilder saves
files to this default path.
Screen shots Screen shots reflect JBuilder’s Metal Look & Feel on various
platforms.
Online resources
You can get information from any of these online sources:
Borland newsgroups
You can register JBuilder and participate in many threaded discussion
groups devoted to JBuilder.
You can find user-supported newsgroups for JBuilder and other Borland
products at http://www.borland.com/newsgroups/
Usenet newsgroups
The following Usenet groups are devoted to Java and related
programming issues:
• news:comp.lang.java.advocacy
• news:comp.lang.java.announce
• news:comp.lang.java.beans
• news:comp.lang.java.databases
• news:comp.lang.java.gui
Introduction 1-5
Contacting Borland developer support
• news:comp.lang.java.help
• news:comp.lang.java.machine
• news:comp.lang.java.programmer
• news:comp.lang.java.security
• news:comp.lang.java.softwaretools
Note These newsgroups are maintained by users and are not official Borland
sites.
Reporting bugs
If you find what you think may be a bug in the software, please report it in
the JBuilder Developer Support page at
http://www.Borland.com/devsupport/jbuilder/. From this site, you can
also submit a feature request or view a list of bugs that have already been
reported.
When you report a bug, please include all the steps needed to reproduce
the bug, including any special environmental settings you used and other
programs you were using with JBuilder. Please be specific about the
expected behavior versus what actually happened.
If you have comments (compliments, suggestions, or issues) with the
JBuilder documentation, you may email [email protected]. This is for
documentation issues only. Please note that you must address support
issues to developer support.
JBuilder is made by developers for developers. We really value your
input, because it helps us to improve our product.
Terms
The following terms and concepts are discussed in this chapter:
• Identifier
• Data type
• Strings
• Arrays
• Variable
• Literal
Identifier
The identifier is the name you choose to call an element (such as a variable
or a method). Java will accept any valid identifier, but for reasons of
usability, it’s best to use a plain-language term that’s modified to meet the
following requirements:
• It should start with a letter. Strictly speaking, it can begin with a
Unicode currency symbol or an underscore (_), but some of these
symbols may be used in imported files or internal processing. They are
best avoided.
Data type
Data types classify the kind of information that certain Java programming
elements can contain. Data types fall into two main categories:
• Primitive or basic
• Composite or reference
Naturally, different kinds of data types can hold different kinds and
amounts of information. You can convert the data type of a variable to a
different type, within limits: you cannot cast to or from the boolean type,
and you cannot cast an object to an object of an unrelated class.
Java will prevent you from risking your data. This means it will easily let
you convert a variable or object to a larger type, but will try to prevent you
from converting it to a smaller type. When you change a data type with a
larger capacity to one with a smaller capacity, you must use a type of
statement called a type cast.
Not all special characters can be represented in this way. Java provides its
own set of escape sequences, many of which can be found in the “Escape
sequences” table on page 11-18.
In Java, the size of primitive data types is absolute, rather than
platform-dependent. This improves portability.
Different numeric data types take different kinds and sizes of numbers.
Their names and capacities are listed below:
Strings
The String data type is actually the String class. The String class stores any
sequence of alphanumeric characters, spaces, and normal punctuation
(termed strings), enclosed in double quotes. Strings can contain any of the
Unicode escape sequences and require \" to put double quotes inside of a
string, but, generally, the String class itself tells the program how to
interpret the characters correctly.
Arrays
An array is a data structure containing a group of values of the same data
type. For instance, an array can accept a group of String values, a group of
int values, or a group of boolean values. As long as all of the values are of
the same data type, they can go into the same array.
Arrays are characterized by a pair of square brackets. When you declare
an array in Java, you can put the brackets either after the identifier or after
the data type:
int studentID[];
char[] grades;
Note that the array size is not specified. Declaring an array does not
allocate memory for that array. In most other languages the array’s size
must be included in its declaration, but in Java you don’t specify its size
until you use it. Then the appropriate memory is allocated.
Variable
A variable is a value that a programmer names and defines. Variables
need an identifier and a value.
Literal
A literal is the actual representation of a number, a character, a state, or a
string. A literal represents the value of an identifier.
Alphanumeric literals include strings in double quotes, single char
characters in single quotes, and boolean true/false values.
Integer literals may be stored as decimals, octals, or hexadecimals, but
think about your syntax: any integer with a leading 0 (as in a date) will be
interpreted as an octal. Floating point literals can only be expressed as
decimals. They will be treated as double unless you specify the type.
For a more detailed explanation of literals and their capacities, see The Java
Handbook by Patrick Naughton.
Applying concepts
The following sections demonstrate how to apply the terms and concepts
introduced earlier in this chapter.
Declaring variables
The act of declaring a variable sets aside memory for the variable you
declare. Declaring a variable requires only two things: a data type and an
identifier, in that order. The data type tells the program how much
memory to allocate. The identifier labels the allocated memory.
Declare the variable only once. Once you have declared the variable
appropriately, just refer to its identifier in order to access that block of
memory.
Variable declarations look like this:
boolean isOn; The data type boolean can be set to true or false.
The identifier isOn is the name that the
programmer has given to the memory allocated
for this variable. The name isOn has meaning for
the human reader as something that would
logically accept true/false values.
int studentsEnrolled; The data type int tells you that you will be
dealing with a whole number of less than ten
digits. The identifier studentsEnrolled suggests
what the number will signify. Since students are
whole people, the appropriate data type calls for
whole numbers.
float creditCardSales; The data type float is appropriate because money
is generally represented to the second decimal
place. You know that money is involved because
the programmer has usefully named this variable
creditCardSales.
Methods
Methods in Java are equivalent to functions or subroutines in other
languages. The method defines an action to be performed on an object.
Methods consist of a name and a pair of parentheses:
getData()
Here, getData is the name and the parentheses tell the program that it is a
method.
If the method needs particular information in order to get its job done,
what it needs goes inside the parentheses. What’s inside the parentheses is
called the argument, or arg for short. In a method declaration, the arg must
include a data type and an identifier:
drawString(String remark)
Here, drawString is the name of the method, and String remark is the data
type and variable name for the string that the method must draw.
You must tell the program what type of data the method will return, or if
it will return anything at all. This is called the return type. You can make a
method return data of any primitive type. If the method doesn’t need to
return anything (as in most action-performing methods), the return type
must be void.
Return type, name, and parentheses with any needed args give a very
basic method declaration:
String drawString(String remark);
Your method is probably more complex than that. Once you have typed
and named it and told it what args it will need (if any), you must define it
completely. You do this below the method name, nesting the body of the
definition in a pair of curly braces. This gives a more complex method
declaration:
String drawString(String remark) { //Declares the method
String remark = "My, what big teeth you have!" //Defines what's in the method.
} //Closes the method body.
Once you have defined the method, you only need to refer to it by its
name and pass it any args it needs to do its job right then:
drawString(remark);.
Terms
The following terms and concepts are discussed in this chapter:
• Keywords
• Operators
• Comments
• Statements
• Code blocks
• Scope
Keywords
Keywords are reserved Java terms that modify other syntax elements.
Keywords can define an object’s accessibility, a method’s flow, or a
variable’s data type. Keywords can never be used as identifiers.
Many of Java’s keywords are borrowed from C/C++. Also, as in C/C++,
keywords are always written in lowercase. Generally speaking, Java’s
keywords can be categorized according to their functions (examples are in
parentheses):
• Data and return types and terms (int, void, return)
• Package, class, member, and interface (package, class, static)
• Access modifiers (public, private, protected)
Operators
Operators allow you to access, manipulate, relate, or refer to Java
language elements, from variables to classes. Operators have properties of
precedence and associativity. When several operators act on the same
element (or operand), the operators’ precedence determines which
operator will act first. When more than one operator has the same
precedence, the rules of associativity apply. These rules are generally
mathematical; for instance, operators will usually be used from left to
right, and operator expressions inside parentheses will be evaluated
before operator expressions outside parentheses.
Operators generally fall into six categories: assignment, arithmetic, logical,
comparison, bitwise, and ternary.
Assignment means storing the value to the right of the = inside the variable
to the left of it. You can either assign a value to a variable when you declare
it or after you have declared it. The machine doesn’t care; you decide
which way makes sense in your program and your practice:
double bankBalance; //Declaration
bankBalance = 100.35; //Assigment
1. It’s important to distinguish between operation and punctuation. Parentheses are used
around args as punctuation. They are used around a data type in an operation that
changes a variable’s data type to the one inside the parentheses.
2. A unary operator takes a single operand, a binary operator takes two operands, and a
ternary operator takes three operands.
Comments
Commenting code is excellent programming practice. Good comments
can help you scan your code more quickly, keep track of what you’ve
done as you build a complex program, and remind you of things you
want to add or tune. You can use comments to hide parts of code that you
want to save for special situations or keep out of the way while you work
on something that might conflict. Comments can help you remember
what you were doing when you return to one project after working on
another, or when you come back from vacation. In a team development
environment or whenever code is passed between programmers,
comments can help others understand the purpose and associations of
everything you comment on, without having to parse out every bit of it to
be sure they understand.
Java uses three kinds of comments: single-line comments, multi-line
comments, and Javadoc comments.
Statements
A statement is a single command. One command can cover many lines of
code, but the compiler reads the whole thing as one command. Individual
(usually single-line) statements end in a semicolon (;), and group
(multi-line) statements end in a closing curly brace (}). Multi-line
statements are generally called code blocks.
By default, Java runs statements in the order in which they’re written, but
Java allows forward references to terms that haven’t been defined yet.
Code blocks
A code block is everything between the curly braces, and includes the
expression that introduces the curly brace part:
class GettingRounder {
...
}
Understanding scope
Scope rules determine where in a program a variable is recognized.
Variables fall into two main scope categorizes:
• Global variables: Variables that are recognized across an entire class.
• Local variables: Variables that are recognized only in the code block
where they were declared.
Scope rules are tightly related to code blocks. The one general scope rule
is: a variable declared in a code block is visible only in that block and any
blocks nested inside it. The following code illustrates this:
class Scoping {
int x = 0;
void method1() {
int y;
y = x; // This works. method1 can access y.
}
void method2() {
int z = 1;
z = y; // This does not work:
// y is defined outside method2's scope.
}
}
This code declares a class called scoping, which has two methods: method1()
and method2(). The class itself is considered the main code block, and the
two methods are its nested blocks.
Applying concepts
The following sections demonstrate how to apply the terms and concepts
introduced earlier in this chapter.
Using operators
Review There are six basic kinds of operators (arithmetic, logical, assignment,
comparison, bitwise, and ternary), and operators affect one, two, or three
operands, making them unary, binary, or ternary operators. They have
properties of precedence and associativity, which determine the order
they’re processed in.
Operators are assigned numbers that establish their precedence. The
higher the number, the higher the order of precedence (that is, the more
likely it is to be evaluated sooner than others). An operator of precedence
1 (the lowest) will be evaluated last, and an operator with a precedence of
15 (the highest) will be evaluated first.
Operators with the same precedence are normally evaluated from left to
right.
Precedence is evaluated before associativity. For instance, the expression
a + b - c * d will not be evaluated from left to right; multiplication has
precedence over addition, so c * d will be evaluated first. Addition and
subtraction have the same order of precedence, so associativity applies: a
and b will be added first, then that sum will be subtracted from the
product of c * d.
It’s good practice to use parentheses around mathematical expressions
you want evaluated first, regardless of their precedence, for instance:
(a + b) - (c * d). The program will evaluate this operation the same way,
but for the human reader, this format is clearer.
Arithmetic operators
Java provides a full set of operators for mathematical calculations. Java,
unlike some languages, can perform mathematical functions on both
integer and floating-point values. You will probably find these operators
familiar.
Here are the arithmetic operators:
Logical operators
Logical (or Boolean) operators allow the programmer to group boolean
expressions to determine certain conditions. These operators perform the
standard Boolean operations AND, OR, NOT, and XOR.
The following table lists the logical operators:
determines the value of the whole expression, they don’t evaluate the
second operand. For example:
if ( !isHighPressure && (temperature1 > temperature2)) {
...
} //Statement 1: conditional
Assignment operators
You know that the basic assignment operator (=) lets you assign a value to
a variable. With Java’s set of assignment operators, you can perform an
operation on either operand and assign the new value to a variable in one
step.
The following table lists assignment operators:
The first operator is familiar by now. The rest of the assignment operators
perform an operation first, and then store the result of the operation in the
operand on the left side of the expression. Here are some examples:
int y = 2;
y *= 2; //same as (y = y * 2)
Comparison operators
Comparison operators allow you to compare one value to another.
The following table lists the comparison operators:
The equality operator can be used to compare two object variables of the
same type. In this case, the result of the comparison is true only if both
variables refer to the same object. Here is a demonstration:
m1 = new Mammal();
m2 = new Mammal();
boolean b1 = m1 == m2; //b1 is false
m1 = m2;
boolean b2 = m1 == m2; //b2 is true
The result of the first equality test is false because m1 and m2 refer to
different objects (even though they are of the same type). The second
comparison is true because both variables now represent the same object.
Note Most of the time, however, the equals() method in the Object class is used
instead of the comparison operator. The comparing class must be
subclassed from Object before objects of the comparing class can be
compared using equals().
Bitwise operators
Bitwise operators are of two types: shift operators and Boolean operators.
The shift operators are used to shift the binary digits of an integer to the
right or the left. Consider the following example (the short integer type is
used instead of int for conciseness):
short i = 13; //i is 0000000000001101
i = i << 2; //i is 0000000000110100
In the second line, the bitwise left shift operator shifted all the bits of i two
positions to the left.
Note The shifting operation is different in Java than in C/C++ in how it is used
with signed integers. A signed integer is one whose left-most bit is used to
indicate the integer’s positive or negative sign: the bit is 1 if the integer is
negative, 0 if positive. In Java, integers are always signed, whereas in
C/C++ they are signed only by default. In most implementations of
C/C++, a bitwise shift operation does not preserve the integer’s sign; the
sign bit would be shifted out. In Java, however, the shift operators
preserve the sign bit (unless you use the >>> to perform an unsigned shift).
This means that the sign bit is duplicated, then shifted. For example, right
shifting 10010011 by 1 is 11001001.
The following table lists Java’s bitwise operators:
Using methods
You know that methods are what get things done. Methods cannot
contain other methods, but they can contain variables and class references.
Here is a brief example to review. This method helps a music store with its
inventory:
//Declare the method: return type, name, args:
public int getTotalCDs(int numRockCDs, int numJazzCDs, in numPopCDs) {
//Declare the variable totalCDs. The other three variables are declared elsewhere:
int totalCDs = numRockCDs + numJazzCDs + numPopCDs;
//Make it do something useful. In this case, print this line on the screen:
System.out.println("Total CDs in stock = " + totalCDs);
}
In Java, you can define more than one method with the same name, as
long as the different methods require different arguments. For instance,
both public int getTotalCDs(int numRockCDs, int numJazzCDs, in numPopCDs)
and public int getTotalCDs(int salesRetailCD, int salesWholesaleCD) are
legal in the same class. Java will recognize the different patterns of
arguments (the method signatures) and apply the correct method when you
make a call. Assigning the same name to different methods is called
method overloading.
To access a method from other parts of a program, you must first create an
instance of the class the method resides in, and then use that object to call
the method:
//Create an instance totalCD of the class Inventory:
Inventory totalCD = new Inventory();
//Access the getTotalCDs() method inside of Inventory, storing the value in total:
int total = totalCD.getTotalCDs(myNumRockCDs, myNumJazzCDs, myNumPopCDs);
Using arrays
Note that the size of an array is not part of its declaration. The memory an
array requires is not actually allocated until you initialize the array.
To initialize the array (and allocate the needed memory), you must use the
new operator as follows:
int studentID[] = new int[20]; // Creates array of 20 int elements.
char[] grades = new char[20]; // Creates array of 20 char elements.
float[][] coordinates = new float[10][5]; // 2-dimensional, 10x5 array of float
// elements.
Note In creating two-dimensional arrays, the first array number defines
number of columns and the second array number defines number of rows.
Java counts positions starting with 0. This means the elements of a
20-element array will be numbered from 0 to 19: the first element will be 0,
the second will be 1, and so on. Be careful how you count when you’re
working with arrays.
When an array is created, the value of all its elements is null or 0; values
are assigned later.
Note The use of the new operator in Java is similar to that of the malloc command
in C and the new operator in C++.
To initialize an array, specify the values of the array elements inside a set
of curly braces. For multi-dimensional arrays, use nested curly braces. For
example:
char[] grades = {'A', 'B', 'C', 'D', 'F');
float[][] coordinates = {{0.0, 0.1}, {0.2, 0.3}};
The first statement creates a char array called grades. It initializes the
array’s elements with the values 'A' through 'F'. Notice that we did not
have to use the new operator to create this array; by initializing the array,
enough memory is automatically allocated for the array to hold all the
initialized values. Therefore, the first statement creates a char array of 5
elements.
The second statement creates a two-dimensional float array called
coordinates, whose size is 2 by 2. Basically, coordinates is an array
consisting of two array elements: the array’s first row is initialized to 0.0
and 0.1, and the second row to 0.2 and 0.3.
Using constructors
A class is a full piece of code, enclosed in a pair of curly braces, that defines
a logically coherent set of variables, attributes, and actions. A package is a
logically associated set of classes.
Member access
The access operator (.) is used to access members inside of an instantiated
object. The basic syntax is:
<instanceName>.<memberName>
Precise syntax of the member name depends on the kind of member.
These can include variables (<memberName>), methods (<memberName>()), or
subclasses (<MemberName>).
You can use this operation inside of other syntax elements wherever you
need to access a member. For example:
setColor(Color.pink);
This method needs a color to do its job. The programmer used an access
operation as an arg to access the variable pink within the class Color.
Arrays
Array elements are accessed by subscripting, or indexing, the array
variable. To index an array variable, follow the array variable’s name with
the element’s number (index) surrounded by square brackets. Arrays are
always indexed starting from 0. (Coding as if they were numbered from 1 is a
common mistake.)
In the case of multi-dimensional arrays, you must use an index for each
dimension to access an element. The first index is the row and the second
index is the column.
For example:
firstElement = grades[0]; //firstElement = 'A'
fifthElement = grades[4]; //fifthElement = 'F'
row2Col1 = coordinates[1][0]; //row2Col1 = 0.2
The following snippet of code demonstrates one use of arrays. It creates an
array of 5 int elements called intArray, then uses a for loop to store the
integers 0 through 4 in the elements of the array:
int[] intArray = new int [5];
int index;
for (index = 0; index < 5; index++) intArray [index] = index;
This code increments the index variable from 0 to 4, and at every pass, it
stores its value in the element of intArray indexed by the variable index.
Terms
The following terms and concepts are discussed in this chapter:
• String handling
• Type casting and conversion
• Return types and statements
• Flow control statements
String handling
The String class provides methods that allow you to get substrings or to
index characters within a string. However, the value of a declared String
can’t be changed. If you need to change the String value associated with
that variable, you must point the variable to a new value:
String text1 = new String("Good evening."); // Declares text1 and assigns a value.
text1 = "Hi, honey, I'm home!" // Assigns a new value to text1.
Indexing allows you to point to a particular character in a string. Java
counts each position in a string starting from 0, so that the first position is
0, the second position is 1, and so on. This gives the eighth position in a
string an index of 7.
The StringBuffer class provides a workaround. It also offers several other
ways to manipulate a string’s contents. The StringBuffer class stores your
string in a buffer (a special area of memory) whose size you can explicitly
control; this allows you to change the string as much as necessary before
you have to declare a String and make the string permanent.
Generally, the String class is for string storage and the StringBuffer class is
for string manipulation.
To cast a data type, put the type you want to cast to in parentheses,
immediately before the variable you want to cast: (int)x. This is what it
looks like in context, where x is the variable being cast, float is the original
data type, int is the target data type, and y is the variable storing the new
value:
float x = 1.00; //declaring x as a float
int y = (int)x; //casting x to an int named y
This assumes that the value of x would fit inside of int. Note that x’s
decimal values are lost in the conversion. Java rounds decimals down to
the nearest whole number.
Applying concepts
The following sections demonstrate how to apply the terms and concepts
introduced earlier in this chapter.
Escape sequences
A special type of character literal is called an escape sequence. Like C/C++,
Java uses escape sequences to represent special control characters and
characters that cannot be printed. An escape sequence is represented by a
backslash (\) followed by a character code. The following table
summarizes these escape sequences:
String handling
The string of characters you specify in a String is a literal; the program will
use exactly what you specify, without changing it in any way. However,
the String class provides the means to chain strings together (called string
concatenation), see and use what’s inside of strings (compare strings,
StringBuffer
If you want more control over your strings, use the StringBuffer class. This
class is part of the java.lang package.
StringBuffer stores your strings in a buffer so that you don’t have to
declare a permanent String until you need it. Some of the advantages to
this are that you don’t have to redeclare a String if its content changes. You
can reserve a size for the buffer larger than what is already in there.
StringBuffer provides methods in addition to those in String that allow
you to modify the contents of strings in new ways. For instance,
StringBuffer’s setCharAt() method changes the character at the index
specified in the first parameter, to the new value specified in the second
parameter:
StringBuffer word = new StringBuffer ("yellow");
word.setCharAt (0, 'b'); //word is now "bellow"
Determining access
By default, classes are available to all of the members inside them, and the
members within the class are available to each other. However, this access
can be widely modified.
Access modifiers determine how visible a class’s or member’s information is
to other members and classes. Access modifiers include:
• public: A public member is visible to members outside the public
member’s scope, as long as the parent class is visible. A public class is
visible to all other classes in all other packages.
• private: A private member’s access is limited to the member’s own
class.
• protected: A protected member can be accessed by other members of its
class and by members of classes in the same package (as long as the
member’s parent class is accessible), but not from other packages. A
protected class is available to other classes in the same package, but not
to other packages.
• If no access modifier is declared, the member is available to all classes
inside the parent package, but not outside the package.
Let’s look at this in context:
class Waistline {
private boolean invitationGiven = false; // This is private.
private int weight = 170 // So is this.
//Objects in the same package can see if this object is too big:
protected boolean isTooBig() {
//It can accept food if its weight is less than 185:
return (weight > 185) ? true : false;
}
}
Notice that isAcceptingFood() and invitationGiven are private. Only
members inside this class know if this object is capable of accepting food
or if it has an invitation.
isTooBig() is protected. Only classes inside this package can see if this
object’s weight exceeds its limit or not.
The only methods that are exposed to the outside are acceptInvitation()
and eat(). Any class can perceive these methods.
Handling methods
The main() method deserves special attention. It is the point of entry into a
program (except an applet). It’s written like this:
public static void main(String[] args) {
...
}
There are specific variations allowed inside the parentheses, but the
general form is consistent.
The keyword static is important. A static method is always associated
with its entire class, rather than with any particular instance of that class.
(The keyword static can also be applied to classes. All of the members of a
static class are associated with the class’s entire parent class.) static
methods are also called class methods.
Since the main() method is the starting-point within the program, it must
be static in order to remain independent of the many objects the program
may generate from its parent class.
static’s class-wide association affects how you call a static method and
how you call other methods from within a static method. static members
can be called from other types of members by simply using the name of
the method, and static members can call each other the same way. You
don’t need to create an instance of the class in order to access a static
method within it.
Implicit casting
There are times when a cast is performed implicitly by the compiler. The
following is an example:
if (3 > 'a') {
...
}
In this case, the value of 'a' is converted to an integer value (the ASCII
value of the letter a) before it is compared with the number 3.
Explicit conversion
Syntax for a widening cast is simple:
<nameOfOldValue> = (<new type>) <nameOfNewValue>
Java doesn’t want you to make a narrowing conversion, so you must be
more explicit when doing so:
floatValue = (float)doubValue; // To float "floatValue"
// from double "doubValue".
Flow control
Review There are three types of loop statements: iteration statements (for, while,
and do-while) create loops, selection statements (switch and all the if
statements) tell the program under what circumstances the program will
use statements, and jump statements (break, continue, and return) shift
control out to another part of the program.
Loops
Each statement in a program is executed once. However, it is sometimes
necessary to execute statements several times until a condition is met. Java
provides three ways to loop statements: while, do and for loops.
• The while loop
The while loop is used to create a block of code that will execute as long
as a particular condition is met. This is the general syntax of the while
loop:
while ( <boolean condition statement> ) {
<code to execute as long as that condition is true>
}
The loop first checks the condition. If the condition’s value is true, it
executes the entire block. It then reevaluates the condition, and repeats
this process until the condition becomes false. At that point, the loop
stops executing. For instance, to print “Looping” 10 times:
int x = 0; //Initiates x at 0.
while (x < 10){ //Boolean condition statement.
System.out.println("Looping"); //Prints "Looping" once.
x++; //Increments x for the next iteration.
}
When the loop first starts executing, it checks whether the value of x is
less than 10. Since it is, the body of the loop is executed. In this case, the
word “Looping” is printed on the screen, and then the value of x is
incremented. This loop continues until the value of x equals 10, when
the loop stops executing.
Unless you intend to write an infinite loop, make sure there is some
point in the loop where the condition’s value becomes false and the
loop terminates. You can also terminate a loop by using the return,
continue, or break statements.
We can tweak the for loop to make the loop execute half as many times:
for (int x=1,y=20, z=0; x<=10 && y>10; x++, y--) {
z+= x+y;
}
Let’s break this loop up into its four main sections:
1 The initialization expression: int x =1, y=20, z=0
2 The Boolean condition: x<=10 && y>10
3 The iteration expression: x++, y--
4 The main body of executable code: z+= x + y
Conditional statements
Conditional statements are used to provide your code with decision-
making capabilities. There are two conditional structures in Java: the if-
else statement, and the switch statement.
• The if-else statement
The syntax of an if-else statement is as follows:
if (<condition1>) {
... //code block 1
}
else if (<condition2>) {
... //code block 2
}
else {
... //code block 3
}
The if-else statement is typically made up of multiple blocks. Only one
of the blocks will execute when the if-else statement executes, based
on which of the conditions is true.
The else-if and else blocks are optional. Also, the if-else statement is
not restricted to three blocks: it can contain as many else-if blocks as
needed.
The following examples demonstrate the use of the if-else statement:
if ( x % 2 == 0)
System.out.println("x is even");
else
System.out.println("x is odd");
if (x == y)
System.out.println("x equals y");
else if (x < y)
System.out.println("x is less than y");
else
System.out.println("x is greater than y");
• The switch statement
The switch statement is similar to the if-else statement. Here is the
general syntax of the switch statement:
switch (<expression>){
case <value1>: <codeBlock1>;
break;
case <value2>: <codeBlock2>;
break;
default : <codeBlock3>;
}
Handling exceptions
Exception handling provides a structured means of catching run-time
errors in your program and making them return meaningful information
about themselves. You can also set the exception handler to perform
certain actions before allowing the program to terminate. Exception
handling uses the keywords try, catch, and finally. A method can declare
an exception by using the throws and throw keywords.
block will always catch the indicated type of exception and any of its
subclasses.
Code in the finally block is guaranteed to be executed, even if the try
block code does not complete for some reason. For instance, the code in
the try block might not complete if it throws an exception, but the code in
the finally block will still execute. This makes the finally block a good
place to put clean-up code.
If you know that a method you’re writing is going to be called by other
code, you might leave it up to the calling code to handle the exception that
your method might throw. In that case, you would simply declare that the
method can throw an exception. Code that might throw an exception can
use the throws keyword to declare an exception. This can be an alternative
to catching the exception, since if a method declares that it throws an
exception, it does not have to handle that exception.
Here is an example of using throws:
public void myMethod() throws SomeException {
... // Code here might throw SomeException, or one of its subclasses.
// SomeException is assumed to be a subclass of Exception.
}
You can also use the throw keyword to indicate that something has gone
wrong. For instance, you might use this to throw an exception of your
own when a user has entered invalid information and you want to show
them an error message. To do this, you would use a statement like:
throw new SomeException("invalid input");
Standard Edition
The Java 2 Platform, Standard Edition (J2SE) provides developers with a
feature-rich, stable, secure, cross-platform development environment.
This Java edition supports such core features as database connectivity,
user interface design, input/output, and network programming and
includes the fundamental packages of the Java language.
See also Java 2 Platform Standard Edition Overview
(http://java.sun.com/j2se/1.3/)
“Introducing the Java™ Platform”
(http://developer.java.sun.com/developer/onlineTraining/
new2java/programming/intro/)
“Java 2 Standard Edition packages” on page 5-3
Enterprise Edition
The Java 2, Enterprise Edition (J2EE) provides the developer with tools to
build and deploy multitier enterprise applications. J2EE includes the J2SE
packages as well as additional packages which support Enterprise
JavaBeans development, Java servlets, JavaServer Pages, XML, and
flexible transaction control.
See also Java 2 Platform Enterprise Edition Overview
(http://java.sun.com/j2ee/overview.html)
Java 2 Enterprise Edition technical articles
(http://developer.java.sun.com/developer/technicalArticles/J2EE/
index.html)
Micro Edition
The Java 2, Micro Edition (J2ME) is used in a variety of consumer
electronic products, such as pagers, smart cards, cell phones, hand-held
PDAs, and set-top boxes. While J2ME provides the same Java language
advantages of code portability across platforms, the ability to run
anywhere, and safe network delivery as J2SE and J2EE, it uses a smaller
set of packages. J2ME includes a subset of the J2SE packages with an
additional package specific to the Micro Edition, javax.microedition.io. In
addition, J2ME applications are upwardly scalable to work with J2SE and
J2EE.
See also Java 2 Platform Micro Edition Overview
(http://java.sun.com/j2me/)
Consumer & Embedded Products technical articles
(http://developer.java.sun.com/developer/technicalArticles/
ConsumerProducts/index.html)
Note Java packages vary by Java 2 Platform edition. The Java 2 Software
Development Kit (SDK) is available in several editions used for various
purposes: Standard Edition (J2SE), Enterprise Edition (J2EE), and Micro
Edition (J2ME).
See also “Java 2 Platform editions” on page 5-1
“Java 2 Platform, Standard Edition, API Specification” in the JDK API
specification
Sun’s tutorial, “Creating and using packages”
(http://www.java.sun.com/docs/books/tutorial/java/interpack/
packages.html)
“Packages” in “Creating and managing projects” in Building Applications
with JBuilder
The java.sql package includes classes, interfaces, and methods for making
database connections, sending SQL statements to a database, retrieving
and updating query results, mapping SQL values, providing information
about a database, throwing exceptions, and providing security.
See also java.sql package summary in the JDK API Documentation
Sun’s tutorial, “Trail: JDBC(TM) Database Access”
(http://web2.java.sun.com/docs/books/tutorial/jdbc/index.html)
JBuilder’s “SQL reference” in the JDataStore Developer’s Guide
Using these classes, developers can protect access to applets and Java
code, including applications, beans, and servlets, by creating permissions
and security policies. When code is loaded, it is assigned permissions
based on the security policy. Permissions specify which resources can be
accessed, such as read/write or connection access. The policy, which
controls which permissions are available, is usually initialized from an
external configurable policy file which defines the code’s security policy.
The use of permissions and policy allow for flexible, configurable, and
extensible access control to the code.
See also java.security package summary in the JDK API Documentation
“Security” in the JDK Guide to Features
An object that uses the clone() method simply makes a copy of itself.
When a copy is made, the new memory is allocated for the clone first, then
contents of the original object is copied into the clone object. In the
following example where the Document class implements the Cloneable
interface, a copy of the Document class containing a text and author property
is created using the clone() method. An object is not seen as cloneable
unless it implements the Cloneable interface.
Document document1 = new Document("docText.txt", "Joe Smith");
Document document2 = document1.clone();
The equals() method compares two objects of the same type for equality
by comparing the properties of both objects. It simply returns a boolean
value depending on the results of the object that calls it and the object that
is passed to it. For instance, if equals() is called by an object that passes it
an object that is identical, the equals() method returns a true value.
The toString() method returns a string representing the object. For this
method to return proper information about different types of objects, the
object’s class must override it.
See also java.lang.Object in the JDK API Documentation
The String class contains several important methods that are essential
when dealing with strings. These methods are used to edit, compare, and
analyze strings. Because strings are immutable and cannot be changed,
A very efficient feature associated with many of these methods is that they
are overloaded for more flexibility. The following demonstrates how the
String class and some of its methods can be used.
String s1 = new String("Hello World.");
char cArray[] = {'J', 'B', 'u', 'i', 'l', 'd', 'e', 'r'};
String s2 = new String(cArray); //s2 = "JBuilder"
length and content of the string buffer can be changed. Additionally, the
StringBuffer object can grow in length when necessary. Finally, after
modifying the StringBuffer, you can create a new string representing the
contents in the StringBuffer.
The StringBuffer class has several constructors shown in the following
table.
There are several important methods that separate the StringBuffer class
from the String class: capacity(), setLength(), setCharAt(), append(), insert()
and toString(). The append() and insert() methods are overloaded in order
to accept various data types.
The capacity() method, which returns the amount of memory allocated for
the StringBuffer, can return a larger value than the length() method.
Memory allocated for a StringBuffer can be set with the StringBuffer(int
length) constructor.
The following code demonstrates some of the methods associated with the
StringBuffer class.
StringBuffer s1 = new StringBuffer(10);
c = s1.capacity(); //c = 10
len = s1.length(); //len = 7
while (enum.hasMoreElements()) {
System.out.println(enum.nextElement());
}
There is one limitation on an Enumeration object; it can only be used once.
There is no method defined in the interface that allows the Enumeration
object to backtrack to previous elements. So, once it enumerates the entire
set of values, it is consumed.
See also java.util.Enumeration in the JDK API Documentation
The following table lists some of the more important methods of the Vector
class and the arguments they accept.
The following code demonstrates the use of the Vector class. A Vector
object called vector1 is created and enumerates its elements in three ways:
using Enumeration's nextElement() method, using Vector's elementAt()
method, and using Vector's toString() method. An AWT component,
textArea, is created to display the output. The text property is set using the
setText() method.
Vector vector1 = new Vector();
class FileReader {
public static void main(String args[]) {
byte buff[] = new byte[80];
try {
InputStream fileIn = new FileInputStream("Readme.txt");
int i = fileIn.read(buff);
String s = new String(buff);
System.out.println(s);
}
catch(FileNotFoundException e) {
}
catch(IOException e) {
}
}
}
In this example, a character array that stores the input data is created.
Then, a FileInputStream object is instantiated and the input file’s name is
passed to its constructor. Next, the FileInputStream read() method is used
to read a stream of characters and store them in the buff array. The first 80
bytes are read from the Readme.txt file and stored in the buff array.
Note The FileReader class could also be used in place of the FileInputStream()
method. The only changes needed would be a char array used in place of
the byte array, and the reader object would be instantiated as follows:
Reader fileIn = new FileReader("Readme.txt");
Finally, in order to see the result of the read call, a String object is created
using the buff array and then passed to the System.out.println() method.
As mentioned earlier, the System class defined in java.lang provides access
to system resources. System.out, a static member of System, represents the
standard output device. The println() method is called to send the output
to the standard output device. The System.out object is of type PrintStream,
which is discussed in “Output stream classes” on page 5-20.
The System.in object, another static member of the System class, is of type
InputStream and represents the standard input device.
See also java.io.FileInputStream in the JDK API Documentation
buffered data based on specified conditions, while the second flushes the
data when it encounters a new line character (if autoflush is set to true).
Several of the methods defined in the PrintStream class are shown in the
following table.
The print() and println() methods are overloaded to receive different data
types.
See also java.io.PrintStream in the JDK API Documentation
File classes
The FileInputStream and FileOutputStream classes in the java.io package
only provide basic functions for handling file input and output. The
java.io package provides the File class and RandomAccessFile class for more
advanced file support. The File class provides easy access to file attributes
and functions, while the RandomAccessFile class provides various methods
for reading and writing to and from a file.
The File class also implements many important methods which check for
the existence, readability, writeability, type, size, and modification time of
files and directories, as well as making new directories and renaming and
deleting files and directories.
This class has one constructor, StreamTokenizer(Reader r), and defines the
four following constants.
Constant Description
TT_EOF Indicates that the end of the file has been read.
TT_EOL Indicates that the end of the line has been read.
TT_NUMBER Indicates that a number token has been read.
TT_WORD Indicates that a word token has been read.
The StreamTokenizer class uses instance variables nval, sval, and ttype to
hold the number value, string value, and type of the token respectively.
The StreamTokenizer class implements several methods used to define the
lexical syntax of tokens.
Object-oriented programming
Chapter6
6
in Java
Object-oriented programming has been around since the introduction of
the language Simula ’67 in 1967. It really came to the forefront of
programming paradigms in the mid-1980s, however.
Unlike traditional structured programming, object-oriented programming
places the data and the operations that pertain to the data within a single
data structure. In structured programming, the data and the operations on
the data are separate and data structures are sent to procedures and
functions to be operated on. Object-oriented programming solves many of
the problems inherent in this design because the attributes and operations
are part of the same entity. This more closely models the real world, in
which all objects have both attributes and activities associated with them.
Java is a pure object-oriented language, meaning that the outermost level
of data structure in Java is the object. There are no stand-alone constants,
variables, or functions in Java. Everything is accessed through classes and
objects. This is one of the nicest features of Java. Other hybrid
object-oriented languages have aspects of structured languages in
addition to object extensions. For example, C++ and Object Pascal are
object-oriented languages, but you can still write structured programming
constructs, which dilutes the effectiveness of the object-oriented
extensions. You just can’t do that in Java!
This chapter assumes you have some knowledge about programming in
other object-oriented languages. If you don’t, you should refer to other
sources to find a more in-depth explanation of object-oriented
programming. This chapter attempts to highlight and summarize the
object-oriented features of Java.
Classes
Classes and objects are not the same thing. A class is a type definition,
whereas an object is a declaration of an instance of a class type. Once you
create a class, you can create as many objects based on that class as you
want. The same relationship exists between classes and objects as between
cherry pie recipes and cherry pies; you can make as many cherry pies as
you want from a single recipe.
The process of creating an object from a class is referred to as instantiating
an object or creating an instance of a class.
Data members
As stated above, a class in Java can contain both data members and
methods. A data member or member variable is a variable declared within
the class. A method is a function or routine that performs some task. Here
is a class that contains just data members:
public class DogClass {
String name, eyeColor;
int age;
boolean hasTail;
}
This example creates a class called DogClass that contains data members:
name, eyeColor, age, and a flag called hasTail. You can include any data type
as a member variable of a class. To access a data member, you must first
create an instance of the class, then access the data using the “.” operator.
Class methods
You can also include methods in classes. In fact, there are no standalone
functions or procedures in Java. All subroutines are defined as methods of
classes. Here is an example of DogClass with a speak() method added:
public class DogClass {
String name,eyeColor;
int age;
boolean hasTail;
Follow these steps listed in this section to create a simple UI for this
sample application.
1 Start creating the application and designing its UI:
1 Start a new project. Choose File|New Project to start the Project wizard.
2 Enter oop1 in the Project Name field and click Finish.
A new project opens.
3 Choose File|New and click the Application icon to start the
Application wizard.
4 Accept the default class name. The package name will be oop1.
5 Click Next and then Finish to create a Frame1.java and an
Application1.java file.
6 Click the Design tab in the content pane to display the UI designer
for Frame1.java.
7 Select contentPane in the structure pane. In the Inspector set the layout
property of contentPane to XYLayout (if you are a Foundation user, set
layout to null). XYLayout and null are seldom ideal for an application,
but until you learn about using layouts, you can use them to create a
quick-and-dirty UI.
public DogClass() {
name = "Snoopy";
eyeColor = "Brown";
age = 2;
hasTail = true;
}
}
You defined DogClass with some member variables. There is also a
constructor to instantiate DogClass objects.
Using the Class wizard, create a ManClass.java file by following the same
steps except specifying the Class Name as ManClass. Modify the resulting
code so that it looks like this:
package oop1;
public ManClass() {
name = "Steven";
eyeColor = "Blue";
age = 35;
isMarried = true;
}
}
The two classes are very similar. You’ll take advantage of this similarity in
an upcoming section.
Click the Frame1 tab at the top of content pane to return to the Frame1 class.
Click the Source tab at the bottom to return to open the editor. Declare two
instance variables as references to the objects. Here is the source listing of
the Frame1 variable declarations shown in bold; add the lines in bold to
your class:
public class Frame1 extends JFrame {
// Create a reference for the dog and man objects
DogClass dog;
ManClass man;
JPanel contentPane;
JPanel jPanel1 = new JPanel();
. . .
Click the Design tab at the bottom of content pane to return to the UI you
designed. Double-click the Create Dog button. JBuilder creates the
beginning of an event handler for that button and places your cursor
within the event handler code. Fill in the event handler code so that you
instantiate a dog object and fill in the dog text fields. Your code should
look like this:
void jButton1_actionPerformed(ActionEvent e) {
dog = new DogClass();
txtfldDogName.setText(dog.name);
txtfldDogEyeColor.setText(dog.eyeColor);
txtfldDogAge.setText(Integer.toString(dog.age));
chkboxDog.setSelected(true);
}
As the code shows, you are calling the constructor for the dog object and
then accessing its member variables.
Click the Design tab to return to the UI designer. Double-click the Create
Man button. JBuilder creates an event handler for the Create Man button.
Fill in the event handler so that it looks like this:
void jButton2_actionPerformed(ActionEvent e) {
man = new ManClass();
txtfldManName.setText(man.name);
txtfldManEyeColor.setText(man.eyeColor);
txtfldManAge.setText(Integer.toString(man.age));
chkboxMan.setSelected(true);
}
You can now compile and run your application. Choose Project|Make
Project “oop1.jpx” to compile it. If you have no errors, choose Run|Run
Project.
If all goes well, the form appears on your screen. When you click the
Create Dog button, a dog object is created and the dog values appear in the
dog fields. When you click the Create Man button, a man object is created
and the man values appear in the appropriate fields.
Class inheritance
The dog and man objects you created have many similarities. One of the
benefits of object-oriented programming is the ability to handle
similarities like this within a hierarchy. This ability is referred to as
inheritance. When a class inherits from another class, the child class
automatically inherits all the characteristics (member variables) and
behavior (methods) from the parent class. Inheritance is always additive;
there is no way to inherit from a class and get less than what the parent
class has.
Inheritance in Java is handled through the keyword extends. When one
class inherits from another class, the child class extends the parent class.
For example,
public class DogClass extends MammalClass {
. . .
}
The items that men and dogs have in common could be said to be
common to all mammals; therefore, you can create a MammalClass to handle
these similarities. You can then remove the declarations of the common
items from DogClass and ManClass, declare them in MammalClass instead, and
then subclass DogClass and ManClass from MammalClass.
Using the Class wizard, create a MammalClass. Fill in the resulting code so
that it looks like this:
package oop1;
public MammalClass() {
name = "The Name";
eyeColor = "Brown";
age = 0;
}
}
Notice that the MammalClass has common characteristics from both the
DogClass and the ManClass. Now, rewrite DogClass and ManClass to take
advantage of inheritance.
boolean hasTail;
public DogClass() {
// implied super()
name = "Snoopy";
age = 2;
hasTail = true;
}
}
Modify the code of ManClass so that it looks like this:
package oop1;
boolean isMarried;
public ManClass() {
name = "Steven";
eyeColor = "Blue";
age = 35;
isMarried = true;
}
}
Notice that DogClass doesn’t specifically assign an eyeColor value, but
ManClass does. DogClass doesn’t need to assign a value to eyeColor because
the dog Snoopy has brown eyes and DogClass inherits brown eyes from the
MammalClass, which declares an eyeColor variable and assigns it the value of
“Brown”. The man Steven, however, has blue eyes, so its necessary to
assign the value “Blue” to the eyeColor variable inherited from MammalClass.
Try compiling and running your project again. (Choosing Run|Run
Project will compile and then run your application.) You’ll see that the UI
of your program looks just as it did before, but now the dog and man objects
inherit all common member variables from MammalClass.
As soon as DogClass extends MammalClass, DogClass has all the member
variables and methods that the MammalClass has. In fact, even MammalClass is
inherited from another class. All classes in Java ultimately extend the
Object class; so if a class is declared that doesn’t extend another class, it
implicitly extends the Object class.
Classes in Java can inherit from only one class at a time (single inheritance).
Unlike Java, some languages (such as C++) allow a class to inherit from
several classes at once (multiple inheritance). A class can extend just one
class at a time. Although, there is no restriction on how many times you
can use inheritance to extend the hierarchy, you must do so one extension
at a time. Multiple inheritance is a nice feature, but it leads to very
complex object hierarchies. Java has a mechanism that provides many of
the same benefits without so much complexity, as you’ll see later.
The MammalClass has a constructor that sets very practical and convenient
default values. It would be nice if the subclasses could access this
constructor.
In fact, they can. You can do this in Java two different ways. If you don’t
call the parent’s constructor explicitly, Java automatically calls the
parent’s default constructor for you as the first line of the child
constructor. The only way to prevent this behavior is to call one of the
parent’s constructors yourself as the first line of the child class constructor.
Constructor calls are always chained like this, and you can’t defeat this
mechanism. This is a very nice feature of the Java language, because in
other object-oriented languages, failing to call the parent’s constructor is a
common bug. Java will always do this for you if you don’t. That is the
meaning of the comment in the first line of the DogClass constructor
(// implied super()). The MammalClass constructor is called at that point
automatically. This mechanism relies on the existence of a superclass
(parent class) constructor that takes no parameters. If the constructor
doesn’t exist and you don’t call one of the other constructors as the first
line of the child constructor, the class won’t compile.
Access modifiers
It’s important to understand when members (both variables and methods)
in the class are accessible. There are several options in Java to allow you to
closely tailor how accessible you want these members to be.
Usually you want to limit the scope of program elements, including class
members, as much as possible. The fewer places something is accessible,
the fewer places it can be accessed incorrectly.
There are four different access modifiers for class members in Java:
private, protected, public, and default (or the absence of any modifier). This
is slightly complicated by the fact that classes within the same package
have different access than classes outside the package. Therefore, here are
two tables that show both the accessibility and inheritability of classes and
member variables from within the same package and from outside the
package (packages are discussed in a later section).
This table shows how class members are accessed and inherited from with
respect to other members in the same package. For example, a member
that is declared to be private cannot be accessed by, or inherited from,
other members of the same package. On the other hand, members
declared using the other modifiers could be accessed by and inherited
from all other members of that package. All parts of the sample
application are part of the oop1 package, so you don’t have to worry about
accessing classes in another package.
For example, this table shows that a protected member could be inherited
from, but not accessed, by classes outside its package.
Note that in both access tables public members are available to anyone
who wants to access them, (notice that constructors are always public),
whereas private members are never accessible nor inheritable outside the
class. So, you should declare any member variable or method you want to
keep internal to the class private.
Accessor methods
Accessor methods (sometimes called getters and setters) are methods that
provide the outward public interface to the class while keeping the actual
data storage private to the class. This is a good idea because you can, at
any time in the future, change the internal representation of the data in the
class without touching the methods that actually set those internal values.
As long as you don’t change the public interface to the class, you don’t
break any code that relies on that class and its public methods.
Accessor methods in Java usually come in pairs: one to get the internal
value, and another to set the internal value. By convention, the Get
method uses the internal private variable name with “get” as a prefix. The
Set method does the same with “set”. A read-only property would only
have a Get method. Usually, Boolean Get methods use “is” or “has” as the
prefix instead of “get”. Accessor methods also make it easy to validate the
data that is assigned to a particular member variable.
Here is an example. In your DogClass, make all of the internal member
variables private and add accessor methods to access the internal values.
DogClass creates just one new member variable, tail.
package oop1;
public DogClass() {
setName("Snoopy");
setAge(2);
setTail(true);
}
The variable tail has been moved to the bottom of the class and now is
declared as private. The location of the definition is not important, but it’s
common in Java to place the private members of the class at the bottom of
the class definition (after all, you can’t get to them outside the class;
therefore, if you are reading the code, you are interested in the public
aspects first). DogClass now has public methods to retrieve and set the
value of tail. The getter is hasTail() and setter is setTail().
Follow the same patterns and revise ManClass so that it looks like this:
package oop1;
public ManClass() {
setName("Steven");
setAge(35);
setEyeColor("Blue");
setMarried(true);
}
// eyecolor
public String getEyeColor() {
return eyeColor;
}
// sound
public String getSound() {
return sound;
}
// age
public int getAge() {
return age;
}
public MammalClass() {
setName("The Name");
setEyeColor("Brown");
setAge(0);
}
void jButton2_actionPerformed(ActionEvent e) {
man = new ManClass();
txtfldManName.setText(man.getName());
txtfldManEyeColor.setText(man.getEyeColor());
txtfldManAge.setText(Integer.toString(man.getAge()));
chkboxMan.setSelected(true);
}
Abstract classes
It’s possible to declare a method in a class as abstract, meaning that there
will be no implementation for the method within this class, but all classes
that extend this class must provide an implementation.
For example, suppose you want all mammals to have the ability to report
their top running speed, but you want each mammal to report a different
speed. In the mammal class you should create an abstract method called
speed(). Add a speed() method to MammalClass just above the private member
variable declarations at the bottom of the source code:
abstract public void speed();
Once you have an abstract method in a class, the entire class must also be
declared as abstract. This indicates that a class that includes at least one
abstract method (and is therefore an abstract class) cannot be instantiated.
So add the abstract keyword to the beginning of the MammalClass
declaration so that it looks like this:
abstract public class MammalClass {
Polymorphism
Polymorphism is the ability for two separate yet related classes to receive
the same message but to act on it in their own way. In other words, two
different (but related) classes can have the same method name, but they
implement the method in different ways.
Therefore, you can have a class method that is also implemented in a child
class, and you can access the code from the parent’s class (similar to the
automatic constructor chaining discussed earlier). Just as in the
constructor example, you can use the keyword super to access any
methods or member variables of the superclass.
Here is a simple example. We have two classes, Parent and Child.
class Parent {
int aValue = 1;
int someMethod(){
return aValue;
}
}
class Child extends Parent {
int aValue; // this aValue is part of this class
int someMethod() { // this overrides Parent's method
aValue = super.aValue + 1; // access Parent's aValue with super
return super.someMethod() + aValue;
}
}
The someMethod() of Child overrides the someMethod() of Parent. A method of
a child class with the same name as a method in the parent class, but that
is implemented differently and therefore has different behavior is an
overridden method.
Can you see how the someMethod() of the Child class would return the value
of 3? The method accesses the aValue variable of Parent using the super
keyword, adds the value of 1 to it, and assigns the resulting value of 2 to
its own aValue variable. The last line of the method calls the someMethod() of
Parent, which simply returns Parent.aValue with a value of 1. To that, it
adds the value of Child.aValue, which was assigned the value of 2 in the
previous line. So 1 + 2 = 3.
Using interfaces
An interface is much like an abstract class but with one important
difference: an interface cannot include any code. The interface mechanism
in Java is meant to replace multiple inheritance.
An interface is a specialized class declaration that can declare constants
and method declarations, but not method implementations. You can
never put code in an interface.
import javax.swing.*;
// eyecolor
public String getEyeColor() {
return eyeColor;
}
// sound
public String getSound() {
return sound;
}
// age
public int getAge() {
return age;
}
public MammalClass() {
setName("The Name");
setEyeColor("Brown");
setAge(0);
}
public DogClass() {
setName("Snoopy");
setSound("Woof, Woof!");
setAge(2);
setTail(true);
}
public ManClass() {
setName("Steven");
setEyeColor("Blue");
setSound("Hello there! I'm " + this.getName() + ".");
setAge(35);
setMarried(true);
}
Click the Source tab to return to the Frame1.java code and add code shown
here in bold to the class definition:
// Create a reference for the objects
DogClass dog;
ManClass man;
void button2_actionPerformed(ActionEvent e) {
man = new ManClass();
txtfldManName.setText(man.getName());
txtfldManEyeColor.setText(man.getEyeColor());
txtfldManAge.setText(Integer.toString(man.getAge()));
chkboxMan.setSelected(true);
mammalList[1] = man;
soundList[1] = man;
}
Return to the UI designer and double-click the Speed button, and fill in
the event handler JBuilder starts for you so that the code looks like this:
void button3_actionPerformed(ActionEvent e) {
for (int i = 0; i <= 1; i++) {
mammalList[i].speed();
}
}
The code loops through the list of mammals held in the array (all two of
them!) and tells each object to display its speed. The first time through the
list, the dog displays its speed, the second time through the list, the man
displays its speed. This is polymorphism in action - two separate but
related objects receiving the same message and reacting to it in their own
way.
Java packages
To facilitate code reuse, Java allows you to group several class definitions
together in a logical grouping called a package. If, for instance, you create a
group of business rules that model the work processes of your
organization, you might want to place them together in a package. This
makes it easier to reuse code that you have previously created.
Declaring packages
Creating your own packages is almost as easy as using them. For instance,
if you want to create a package called mypackage, you would simply use a
package statement at the beginning of your file:
package mypackage;
} // end class
Now, any other program can access the classes declared in mypackage with
the statement:
import mypackage.*;
Remember, this file should be in a subdirectory called mypackage. This
allows your Java compiler to easily locate your package. JBuilder’s Project
wizard will automatically set the directory to match the project name.
Also, keep in mind that the base directory of any package you import
must be listed in the Source Path of the JBuilder IDE or the Source Path of
your project. This is good to remember if you decide to relocate a package
to a different base directory.
For more information about working with packages in JBuilder, see
“Packages” in Building Applications with JBuilder.
Threading techniques
Chapter7
7
Threads are a part of every Java program. A thread is a single sequential
flow of control within a program. It has a beginning, a sequence, and an
end. A thread cannot run on its own; it runs within a program. If your
program is a single sequence of execution, you don’t need to set up a
thread explicitly, the Java Virtual Machine (VM) will take care of this for
you.
One of the powerful aspects of the Java language is that you can easily
program multiple threads of execution to run concurrently within the
same program. For example, a web browser can download a file from one
site, and access another site at the same time. If the browser can’t do two
simultaneous tasks, you’d need to wait until the file had finished
downloading before you could browse to another site.
The Java VM always has multiple threads, called daemon threads, running.
For example, a continually running daemon thread performs garbage
collection tasks. Another daemon thread handles mouse and keyboard
events. It is possible for your program to lock up one of the Java VM
threads. If your program appears to be dead, with no events being sent to
your program, try using threads.
A few books that provide detailed information about working with
threads in Java are listed below.
• Java Threads, Second Edition by Scott Oaks and Henry Wong, et al.
• Taming Java Threads by Allen Holub
• Mastering Java Threads by DDC Publishing
You would also have to change the way the name of the thread is
obtained. Because you are not instantiating the class CountThread, you
cannot call the getName() method of CountThread's superclass, in this case,
java.lang.Object. This method is not available. Instead, you need to
specifically use the Thread.currentThread() method, which returns the
thread’s name in a format that is slightly different from the getName()
method.
The entire class, with changes highlighted in bold-faced type, would then
look like this:
public class CountThread implements Runnable {
private int start;
private int finish;
was assigned. (The priority and the group are assigned by the Java VM if
none are specified.)
See also “Thread priority” on page 7-7
“Thread groups” on page 7-8
Defining a thread
The Thread class provides seven constructors. These constructors combine
the following three parameters in various ways:
• A Runnable object whose run() method will execute inside the thread.
• A String object to identify the thread.
• A ThreadGroup object to assign the thread to. The ThreadGroup class
organizes groups of related threads.
Constructor Description
Thread() Allocates a new Thread object.
Thread(Runnable target) Allocates a new Thread object so that
it has target as its run object.
Thread(Runnable target, String name) Allocates a new Thread object so that
it has target as its run object and the
specified name as its name.
Thread(String name) Allocates a new Thread object so that
it has the specified name as its name.
Thread(ThreadGroup group, Runnable target) Allocates a new Thread object so that
it belongs to the thread group
referred to by group and has target as
its run object.
Thread(ThreadGroup group, Runnable target, Allocates a new Thread object so that
String name) it has target as its run object, the
specified name as its name, and
belongs to the thread group referred
to by group.
Thread(ThreadGroup group, String name) Allocates a new Thread object so that
it belongs to the thread group
referred to by group and has the
specified name as its name.
If you want to associate state with a thread, use a ThreadLocal object when
you create the thread. This class allows each thread to have its own
independently initialized copy of a private static variable, for example, a
user or transaction ID.
Starting a thread
To start a thread call the start() method. This method creates the system
resources necessary to run the thread, schedules the thread, and calls the
thread’s run() method.
After the start() method returns, the thread is running and is in a
runnable state. Because most computers have only a single CPU, the Java
VM must schedule threads. For more information see “Thread priority”
on page 7-7.
Stopping a thread
You can no longer stop a thread with the stop() method. This method has
been deprecated, as it is unsafe. Stopping a thread will cause it to unlock
all of the monitors it has locked. If an object previously protected by one of
these monitors is in an inconsistent state, other threads will see that object
as inconsistent. This can cause your program to be corrupted.
To stop a thread, terminate the run() method with a finite loop.
For more information, see the topic called “Why are Thread.stop,
Thread.suspend, Thread.resume and runtime.runFinalizersOnExit
Deprecated?” in the JDK documentation.
Thread priority
When a Java thread is created, it inherits its priority from the thread that
created it. You can set a thread’s priority using the setPriority() method.
Thread priorities are represented as integer values ranging from
MIN_PRIORITY to MAX_PRIORITY (constants in the Thread class). The thread with
the highest priority is executed.
When that thread stops, yields, or becomes not runnable, a lower priority
thread will be executed. If two threads of the same priority are waiting,
the Java scheduler will choose one of them to run in a round-robin
fashion. The thread will run until:
• A higher priority thread becomes runnable.
• The thread yields, by use of the yield() method, or its run() method
exits.
• Its time allotment has expired. This only applies to systems that
support time slicing.
This type of scheduling is based on a scheduling algorithm called fixed
priority scheduling. Threads are run based on their priority when compared
to other threads. The thread with the highest priority will always be
running.
Time slicing
Some operating systems use a scheduling mechanism knows as
time-slicing. Time-slicing divides the CPU into time slots. The system gives
the highest priority threads that are of equal priority time to run, until one
or more of them finishes, or until a higher priority thread is in a runnable
state. Because time-slicing is not supported on all operating systems, your
program should not depend on a time-slicing scheduling mechanism.
Synchronizing threads
One of the central problems of multithreaded computing is handling
situations where more than one thread has access to the same data
structure. For example, if one thread was trying to update the elements in
a list, while another thread was simultaneously trying to sort them, your
program could deadlock or produce incorrect results. To prevent this
problem, you need to use thread synchronization.
The simplest way to prevent two objects from accessing the same method
at the same time is to require a thread to obtain a lock. While a thread
holds the lock, another thread that needs a lock has to wait until the first
thread releases the lock. To keep a method thread-safe, use the synchronized
keyword when declaring methods that can be executed by only one
thread at a time. Note than you can also synchronize on an object.
For example, if you create a swap() method that swaps values using a local
variable and you create two different threads to execute the method, your
program could produce incorrect results. The first thread, due to the Java
scheduler, might only be able to execute the first half of the method. Then,
the second thread might be able to execute the entire method, but using
incorrect values (since the first thread did not complete the operation).
The first thread would then return to finish the method. In this case, it
would appear as if the swapping of values never took place. To prevent
this from happening, use the synchronized keyword in your method
declaration.
As a basic rule, any method that modifies an object’s property should be
declared synchronized.
Thread groups
Every Java thread is a member of a thread group. A thread group collects
multiple threads into a single object and manipulates all those threads at
once. Thread groups are implemented by the java.lang.ThreadGroup class.
The runtime system puts a thread into a thread group during thread
construction. The thread is either put into a default group or into a thread
group you specify when the thread is created. You cannot move a thread
into a new group once the thread has been created.
If you create a thread without specifying a group name in its constructor,
the runtime system places the new thread in the same group as the thread
that created it. Usually, unspecified threads are put into the main thread
group. However, if you create a thread in an applet, the new thread might
be put into a thread group other than main, depending on the browser or
viewer the applet is running in.
8
Serialization
Chapter8
Why serialize?
Traditionally, saving data to a disk or other storage device required that
you define a special data format, write a set of functions to write and read
that format, and create a mapping between the file format and the format
of your data. The functions to read and write data were either simple and
lacked extensibility, or they were complex and difficult to create and
maintain.
Java is completely based around objects and object-oriented programming
and provides a storage mechanism for objects in the form of serialization.
Using the Java way of doing things, you no longer have to worry about
details of file formats and input/output (I/O). Instead, you can
concentrate on solving your real-world tasks by designing and
implementing objects. If, for instance, you make a class persistent and
later add new fields to it, you don’t have to worry about modifying
routines that read and write the data for you. All fields in a serialized
object will automatically be written and restored.
Serialization 8-1
Java serialization
Java serialization
Serialization first appeared as a feature of JDK 1.1. Java’s support for
serialization consists of the Serializable interface, the ObjectOutputStream
class and the ObjectInputStream class, as well as a few supporting classes
and interfaces. We’ll examine all three of these items as we demonstrate
an application that can save user information to a disk and read it back.
Suppose, for instance, you wanted to save information about a particular
user as shown here.
Figure 8.1 Saving a user name and password
After the user types in his or her name and password into the appropriate
fields, the application should save information about this user to disk. Of
course, this is a very simple example, but you can easily imagine saving
data about user application preferences, the last document opened, and so
on.
Using JBuilder, you can design a user interface like the one shown above.
See “Designing a user interface” in Building Applications with JBuilder if
you need help with this task. Name the Name text field textFieldName, and
the password field passwordFieldName. Besides the two labels you can see,
add a third one near the bottom of the frame and name it labelOutput.
3 In the Options section, check just the Public and Generate Default
Constructor options, unchecking all others.
4 Choose OK.
The Class wizard creates the new class file for you and adds it to the
project. Modify the generated code so that it looks like this:
package serialize;
public UserInfo() {
}
Serialization 8-3
Using output streams
This is how the event handler for the Serialize button should look in its
entirety:
void jButton1_actionPerformed(ActionEvent e) {
UserInfo user = new UserInfo();
user.setUserName(textFieldName.getText());
user.setUserPassword(textFieldPassword.getText());
try {
FileOutputStream file = new FileOutputStream("c:\userInfo.ser");
ObjectOutputStream out = new ObjectOutputStream(file);
out.writeObject(user);
out.flush();
}
catch (java.io.IOException IOE) {
labelOutput.setText("IOException");
}
finally {
out.close();
}
}
Now compile your project and run it. Enter values in the Name and
Password fields and click the Serialize button. You can verify that the
object has been written by opening it in a text editor. (Don’t try to edit it,
or the file will probably be corrupted!) Notice that a serialized object
contains a mixture of ASCII text and binary data:
Figure 8.2 The serialized object
ObjectOutputStream methods
The ObjectOutputStream class contains several useful methods for writing
data to a stream. You aren’t restricted to writing objects. Calling
writeInt(), writeFloat(), writeDouble(), and so on, will write any of the
fundamental types to a stream. If you want to write more than one object
or fundamental type to the same stream, you can do so by repeatedly
calling these methods against the same ObjectOutputStream object. When
you do this, however, you must read the objects back in the same order.
Serialization 8-5
Using input streams
renamed the UserInfo class since the file was written, you’ll get a
ClassNotFoundException.
catch (ClassNotFoundException cnfe) {
labelOutput.setText("ClassNotFoundException");
}
}
Here is the Deserialize button event handler in its entirety:
void jButton2_actionPerformed(ActionEvent e) {
try {
FileInputStream file = new FileInputStream("c:\userInfo.ser");
ObjectInputStream input = new ObjectInputStream(file);
UserInfo user = (UserInfo)input.readObject();
input.close();
labelOutput.setText("Name is " + user.getUserName() +
", password is: " +
user.getUserPassword());
}
catch (java.io.IOException IOE) {
labelOutput.setText("IOException");
}
catch (ClassNotFoundException cnfe) {
labelOutput.setText("ClassNotFoundException");
}
}
Now when you compile and run your project, enter Name and Password
values and click the Serialize button to store the information on your disk.
Then click the Deserialize button to read the serialized UserInfo object back
again.
Figure 8.3 The object restored
Serialization 8-7
Writing and reading object streams
ObjectInputStream methods
ObjectInputStream also has methods such as readDouble(), readFloat(), and
so on, which are the counterparts to the writeDouble(), writeFloat(), and
such methods. You must call each method in sequence, the same way the
objects were written to the stream.
An introduction to the
Chapter9
9
Java Virtual Machine
This chapter provides an introduction to the Java Virtual Machine (JVM).
While it is important for you to be familiar with basic information
concerning the JVM, unless you get into very advanced Java
programming, the JVM is typically something you don’t need to worry
about. This chapter is for your information only.
Before exploring the Java Virtual Machine, we will explain some of the
terminology used in this chapter. First, the Java Virtual Machine (JVM) is
the environment in which Java programs execute. The Java Virtual
Machine specification essentially defines an abstract computer, and
specifies the instructions that this computer can execute. These
instructions are called bytecodes. Generally speaking, Java bytecodes are to
the JVM what an instruction set is to a CPU. A bytecode is a byte-long
instruction that the Java compiler generates, and the Java interpreter
executes. When the compiler compiles a .java file, it produces a series of
bytecodes and stores them in a .class file. The Java interpreter can then
execute the bytecodes stored in the .class file.
Other terminology used in this chapter involves Java applications and
applets. It is sometimes appropriate to distinguish between a Java
application and a Java applet. In some sections of this chapter, however,
that distinction is inappropriate. In such cases, we will use the word app to
refer to both Java applications and Java applets.
It is important here to clarify what Java really is. Java is more than just a
computer language; it is a computer environment. This is because Java is
composed of two separate main elements, each of which is an essential
part of Java: the design-time Java (the Java language itself) and the
runtime Java (the JVM). This interpretation of the word Java is a more
technical one.
Interestingly enough, the practical interpretation of the word Java is that it
stands for the runtime environment—not the language. When you say
something like “this machine can run Java,” what you really mean is that
the machine supports the Java Runtime Environment (JRE); more
precisely, it implements a Java Virtual Machine.
A distinction should be made between the Java Virtual Machine
Specification and an implementation of the Java Virtual Machine. The JVM
specification is a document (available from Sun’s website
http://java.sun.com/docs/books/vmspec/index.html) which defines
how to implement a JVM. When an implementation of the JVM correctly
follows this specification, it essentially ensures that Java apps can run on
this implementation of the JVM with the same results those same Java
apps produce when running on any other implementation of the JVM. The
JVM specification ensures that Java programs will be able to run on any
platform.
The JVM specification is platform independent, because it can be
implemented on any platform. Note that a specific implementation of the
JVM is platform dependent. This is because the JVM implementation is
the only portion of Java that directly interacts with the operating system
(OS) of your computer. Because each OS is different, any specific JVM
implementation must know how to interact with the specific OS for which
it is intended.
Having Java programs run under an implementation of the JVM
guarantees a predictable runtime environment, because all
implementations of the JVM conform to the JVM specification. Even
though there are different implementations of the JVM, they all must meet
certain requirements to guarantee portability. In other words, whatever
differs among the various implementations does not affect portability.
The JVM is responsible for performing the following functions:
• Allocating memory for created objects
• Performing garbage collection
• Handling register and stack operations
• Calling on the host system for certain functions, such as device access
• Monitoring the security of Java apps
Throughout the remaining chapter, we will focus on the last function:
security.
Java VM security
One of the JVM’s most important roles is monitoring the security of Java
apps. The JVM uses a specific mechanism to force certain security
restrictions on Java apps. This mechanism (or security model) has the
following roles:
• Determines to what extent the code being run is “trusted” and assigns
it the appropriate level of access
• Assures that bytecodes do not perform illegal operations
• Verifies that every bytecode is generated correctly
In the following sections, we will see how these security roles are taken
care of in Java.
The third stage involves validating the bytecodes. This is the most
significant and complex stage in the entire verification process. Validating
a bytecode means checking that its type is valid and that its arguments
have the appropriate number and type. The verifier also checks that
method calls are passed the correct type and number of arguments, and
that each external function returns the proper type.
The final stage is where runtime checks take place. At this stage,
externally referenced classes are loaded, and their methods are checked.
The method check involves checking that the method calls match the
signature of the methods in the external classes. The verifier also monitors
access attempts by the currently loaded class to make sure that the class
does not violate access restrictions. Another access check is done on
variables to ensure that private and protected variables are not accessed
illegally.
From this exhaustive verification process, we can see how important the
Java verifier is to the security model. It is also important to note that the
verification process must be done at the verifier level, and not at the
compiler’s, since any compiler can be programmed to generate Java
bytecodes. Clearly then, relying on the compiler to perform the
verification process is dangerous, since the compiler can be programmed
to bypass it. This point illustrates why the JVM is necessary.
If you need more information on the Java verifier, please see the Java
Virtual Machine Specification
(http://java.sun.com/docs/books/vmspec/index.html).
developers. When you do find you are concerned with more advanced
security topics, or just for more information on the java.security package,
please see the “Security Architecture” document in the JDK
documentation.
Option Description
-jni Creates a JNI header file
-verbose Displays progress information
-version Displays the version of javah
-o directoryName Outputs the .h file in specified directory
-classpath path Overrides the default class path
The contents of the .h file generated by javah include all the function
prototypes for the native methods in the class. The prototypes are
modified to allow the Java runtime system to find and invoke the native
Keywords
These tables cover the following types of keywords:
• Data and return types and terms
• Packages, classes, members, and interfaces
• Access modifiers
• Loops and loop controls
• Exception handling
• Reserved words
Keyword Use
interface Abstracts a class’s interface from its implementation (tells what to
do, not how to do it).
native The body of this method is provided by a link to a native library.
new Instantiates a class.
package Declares a package name for all classes defined in source files with
the same package declaration.
static Member is available to the whole class, not just one object.
super Inside a subclass, refers to the superclass.
synchronized Makes a code block thread-safe.
this Refers to the current object.
transient This variable’s value won’t persist when the object is stored.
volatile This variable’s value can change unexpectedly.
Access modifiers
Keyword Use
package Default access level; don’t use it explicitly.
Cannot be subclassed by another package.
private Access limited to member’s own class.
protected Access limited to member’s class’s package.
public Class: accessible from anywhere.
Subclass: accessible as long as its class is accessible.
Exception handling
Keyword Use
throw Transfers control of the method to the exception handler.
throws Lists the exceptions a method could throw.
try Opening exception-handling statement.
catch Captures the exception.
finally Runs its code before terminating the program.
Reserved
Keyword Use
assert Reserved for future use.
const Reserved for future use.
goto Reserved for future use.
Primitive to primitive
Java doesn’t support casting to or from boolean values. In order to work
around Java’s strict logical typing, you must assign an appropriate
equivalent value to the variable and then convert that. 0 and 1 are often
used to represent false and true values.
Syntax Comments
From other primitive type p Other primitive types include byte,
To boolean t: short, char, int, long, double, float.
t = p != 0;
From boolean t
To byte b:
b = (byte)(t ? 1 : 0);
From boolean t
To int, long, double, or float m:
m = t ? 1 : 0;
From boolean t
To short s:
s = (short) (t ? 1 : 0);
From boolean t
To byte b:
b = (byte) (t?1:0);
From boolean t You can omit the single quotes, but
To char c: they are recommended.
c = (char) (t?'1':'0');
From short, char, int, long, double, or float n
To byte b:
b = (byte)n;
From byte b
To short, int, long, double, or float n:
n = b;
From byte b
To char c:
c = (char)b;
Primitive to String
Primitive data types are mutable; reference types are immutable objects.
Casting to or from a reference type is risky.
Java doesn’t support casting to or from boolean values. In order to work
around Java’s strict logical typing, you must assign an appropriate
equivalent value to the variable and then convert that. 0 and 1 are often
used to represent false and true values.
Syntax Comments
From boolean t
To String gg:
gg = t ? "true" : "false";
From byte b The following may be substituted for toString, where
To String gg: appropriate:
gg = Integer.toString(b); toBinaryString
or toOctalString
toHexString
gg = String.valueOf(b);
Where you are using a base other than 10 or 2 (such
as 8):
gg = Integer.toString(b, 7);
From short or int n The following may be substituted for toString, where
To String gg: appropriate:
gg = Integer.toString(n); toBinaryString
or toOctalString
toHexString
gg = String.valueOf(n);
Where you are using a base other than 10 (such as 8):
gg = Integer.toString(n, 7);
From char c
To String gg:
gg = String.valueOf(c);
From long n The following may be substituted for toString, where
To String gg: appropriate:
g = Long.toString(n); toBinaryString
or toOctalString
toHexString
gg = String.valueOf(n);
Where you are using a base other than 10 or 2 (such
as 8):
gg = Integer.toString(n, 7);
Syntax Comments
From float f These casts protect more data.
To String gg: Double precision:
gg = Float.toString(f); java.text.DecimalFormat df2
or = new java.text.DecimalFormat("###,##0.00");
gg = df2.format(f);
gg = String.valueOf(f);
Scientific notation (protects exponents) (JDK 1.2.x
For decimal protection or
and up):
scientific notation, see next
column. java.text.DecimalFormat de
= new java.text.DecimalFormat("0.000000E00");
gg = de.format(f);
From double d These casts protect more data.
To String gg: Double precision:
gg = Double.toString(d); java.text.DecimalFormat df2
or = new java.text.DecimalFormat("###,##0.00");
gg = df2.format(d);
gg = String.valueOf(d);
Scientific notation (JDK 1.2.x and up):
For decimal protection or
scientific notation, see next java.text.DecimalFormat de
column. = new java.text.DecimalFormat("0.000000E00");
gg = de.format(d);
Primitive to reference
Java provides classes that correspond to primitive data types and provide
methods that facilitate conversions.
Note that primitive data types are mutable; reference types are immutable
objects. Casting to or from a reference type is risky.
Java doesn’t support casting to or from boolean values. In order to work
around Java’s strict logical typing, you must assign an appropriate
equivalent value to the variable and then convert that. 0 and 1 are often
used to represent false and true values.
Syntax Comments
From boolean t
To Boolean tt:
tt = new Boolean(t);
From Primitive type p (other than boolean) For char c, put single quotes
To Boolean tt around the zero:
tt = new Boolean(p != 0); tt = new Boolean(c != '0');
For char, see next column.
From boolean t
To Character cc:
cc = new Character(t ? '1' : '0');
Syntax Comments
From byte b
To Character cc:
cc = new Character((char) b);
From char c
To Character cc:
cc = new Character(c);
From short, int, long, float, or double n
To Character cc:
cc = new Character((char)n);
From boolean t
To Integer ii:
ii = new Integer(t ? 1 : 0);
From byte b
To Integer ii:
ii = new Integer(b);
Fromshort, char, or int n
To Integer ii:
ii = new Integer(n);
From long, float, or double f
To Integer ii:
ii = new Integer((int) f);
From boolean t
To Long nn:
nn = new Long(t ? 1 : 0);
From byte b
To Long nn:
nn = new Long(b);
From short, char, int, or long s
To Long nn:
nn = new Long(s);
From float, double f
To Long nn:
nn = new Long((long)f);
From boolean t
To Float ff:
ff = new Float(t ? 1 : 0);
From byte b
To Float ff:
ff = new Float(b);
From short, char, int, long, float, or double n
To Float ff:
ff = new Float(n);
Syntax Comments
From boolean t
To Double dd:
dd = new Double(t ? 1 : 0);
From byte b
To Double dd:
dd = new Double(b);
From short, char, int, long, float, or double n
To Double dd:
dd = new Double(n);
String to primitive
Note that primitive data types are mutable; reference types are immutable
objects. Casting to or from a reference type is risky.
Java doesn’t support casting to or from boolean values. In order to work
around Java’s strict logical typing, you must assign an appropriate
equivalent value to the variable and then convert that. The numbers 0 and
1, the strings “true” and “false”, or equally intuitive values are used here
to represent true and false values.
Syntax Comments
From String gg Caution: t will only be true when the value of gg is “true”
To boolean t: (case insensitive); if the string is “1”, “yes”, or any other
affirmative, this conversion will return a false value.
t = new Boolean(gg.trim()).booleanValue();
From String gg Note: If the value of gg is null, trim() will throw a
To byte b: NullPointerException. If you don’t use trim(), make sure
there’s no trailing white space.
try {
b = (byte)Integer.parseInt(gg.trim()); For bases other than 10, such as 8:
} try {
catch (NumberFormatException e) { b = (byte)Integer.parseInt(gg.trim(), 7);
... }
} catch (NumberFormatException e) {
...
}
From String gg Note: If the value of gg is null, trim() will throw a
To short s: NullPointerException. If you don’t use trim(), make sure
there’s no trailing white space.
try {
s = (short)Integer.parseInt(gg.trim()); For bases other than 10, such as 8:
} try {
catch (NumberFormatException e) { s = (short)Integer.parseInt(gg.trim(), 7);
... }
} catch (NumberFormatException e) {
...
}
Syntax Comments
From String gg Note: If the value of gg is null, trim() will throw a
To char c: NullPointerException. If you don’t use trim(), make sure
there’s no trailing white space.
try {
c = (char)Integer.parseInt(gg.trim()); For bases other than 10, such as 8:
} try {
catch (NumberFormatException e) { c = (char)Integer.parseInt(gg.trim(), 7);
... }
} catch (NumberFormatException e) {
...
}
From String gg Note: If the value of gg is null, trim() will throw a
To int i: NullPointerException. If you don’t use trim(), make sure
there’s no trailing white space.
try {
i = Integer.parseInt(gg.trim()); For bases other than 10, such as 8:
} try {
catch (NumberFormatException e) { i = Integer.parseInt(gg.trim(), 7);
... }
} catch (NumberFormatException e) {
...
}
From String gg Note: If the value of gg is null, trim() will throw a
To long n: NullPointerException. If you don’t use trim(), make sure
there’s no trailing white space.
try {
n = Long.parseLong(gg.trim());
}
catch (NumberFormatException e) {
...
}
From String gg Note: If the value of gg is null, trim() will throw a
To float f: NullPointerException. If you don’t use trim(), make sure
there’s no trailing white space.
try {
f = Float.valueOf(gg.trim()).floatValue; For JDK 1.2.x or better:
} try {
catch (NumberFormatException e) { f = Float.parseFloat(gg.trim());
... }
} catch (NumberFormatException e) {
...
}
From String gg Note: If the value of gg is null, trim() will throw a
To double d: NullPointerException. If you don’t use trim(), make sure
there’s no trailing white space.
try {
d = Double.valueOf(gg.trim()).doubleValue; For JDK 1.2.x or better:
} try {
catch (NumberFormatException e) { d = Double.parseDouble(gg.trim());
... }
} catch (NumberFormatException e) {
...
}
Reference to primitive
Java provides classes that correspond to the primitive data types. This
table shows how to convert a variable from one of these classes to a
primitive data type for a single operation.
To convert from a reference type to a primitive, you must first get the
value of the reference as a primitive, then cast the primitive.
Primitive data types are mutable; reference types are immutable objects.
Converting to or from a reference type is risky.
Java doesn’t support casting to or from boolean values. In order to work
around Java’s strict logical typing, you must assign an appropriate
equivalent value to the variable and then convert that. 0 and 1 are often
used to represent false and true values.
Syntax Comments
From Boolean tt
To boolean t:
t = tt.booleanValue();
From Boolean tt
To byte b:
b = (byte)(tt.booleanValue() ? 1 : 0);
From Boolean tt
To short s:
s = (short)(tt.booleanValue() ? 1 : 0);
From Boolean tt You may omit the single quotes,
To char c: but they are recommended.
c = (char)(tt.booleanValue() ? '1' : '0');
From Boolean tt
To int, long, float, or double n:
n = tt.booleanValue() ? 1 : 0);
From Character cc
To boolean t:
t = cc.charValue() != 0;
From Character cc
To byte b:
b = (byte)cc.charValue();
From Character cc
To short s:
s = (short)cc.charValue();
From Character cc
To char, int, long, float, or double n:
n = cc.charValue();
Syntax Comments
From Integer ii
To boolean t:
t = ii.intValue() != 0;
From Integer ii
To byte b:
b = ii.byteValue();
From Integer, Long, Float, or Double nn
To short s:
s = nn.shortValue();
From Integer, Long, Float, or Double nn
To char c:
c = (char)nn.intValue();
From Integer, Long, Float, or Double nn
To int i:
i = nn.intValue();
From Integer ii
To long n:
n = ii.longValue();
From Long, Float, or Double dd
To long n:
n = dd.longValue();
From Integer, Long, Float, or Double nn
To float f:
f = nn.floatValue();
From Integer, Long, Float, or Double nn
To double d:
d = nn.doubleValue();
Reference to reference
Java provides classes that correspond to the primitive data types. This
table shows how to convert a variable from one of these classes to another
for a single operation.
Note For legal class to class conversions apart from what’s shown here,
widening conversions are implicit. Narrowing casts use this syntax:
castFromObjectName = (CastToObjectClass)castToObjectName;
You must cast between classes that are in the same inheritance hierarchy.
If you cast an object to an incompatible class, it will throw a
ClassCastException.
Reference types are immutable objects. Converting between reference
types is risky.
Syntax Comments
From String gg Note: If the value of gg is null, trim() will throw a
To Boolean tt: NullPointerException. If you don’t use trim(), make sure
there’s no trailing white space.
tt = new Boolean(gg.trim());
Alternative:
tt = Boolean.valueOf(gg.trim());
From String gg
To Character cc:
cc = new Character(g.charAt(<index>);
From String gg Note: If the value of gg is null, trim() will throw a
To Integer ii: NullPointerException. If you don’t use trim(), make sure
there’s no trailing white space.
try {
ii = new Integer(gg.trim()); Alternative:
} try {
catch (NumberFormatException e) { ii = Integer.valueOf(gg.trim());
... }
} catch (NumberFormatException e) {
...
}
From String gg Note: If the value of gg is null, trim() will throw a
To Long nn: NullPointerException. If you don’t use trim(), make sure
there’s no trailing white space.
try {
nn = new Long(gg.trim()); Alternative:
} try {
catch (NumberFormatException e) { nn = Long.valueOf(gg.trim());
... }
} catch (NumberFormatException e) {
...
}
From String gg Note: If the value of gg is null, trim() will throw a
To Float ff: NullPointerException. If you don’t use trim(), make sure
there’s no trailing white space.
try {
ff = new Float(gg.trim()); Alternative:
} try {
catch (NumberFormatException e) { ff = Float.valueOf(gg.trim());
... }
} catch
...
}
From String gg Note: If the value of gg is null, trim() will throw a
To Double dd: NullPointerException. If you don’t use trim(), make sure
there’s no trailing white space.
try {
dd = new Double(gg.trim()); Alternative:
} try {
catch dd = Double.valueOf(gg.trim());
... }
} catch (NumberFormatException e) {
...
}
Syntax Comments
From Boolean tt
To Character cc:
cc = new
Character(tt.booleanValue() ?'1':'0');
From Boolean tt
To Integer ii:
ii = new Integer(tt.booleanValue() ? 1 : 0);
From Boolean tt
To Long nn:
nn = new Long(tt.booleanValue() ? 1 : 0);
From Boolean tt
To Float ff:
ff = new Float(tt.booleanValue() ? 1 : 0);
From Boolean tt
To Double dd:
dd = new Double(tt.booleanValue() ? 1 : 0);
From Character cc
To Boolean tt:
tt = new Boolean(cc.charValue() != '0');
From Character cc
To Integer ii:
ii = new Integer(cc.charValue());
From Character cc
To Long nn:
nn = new Long(cc.charValue());
From any class rr
To String gg:
gg = rr.toString();
From Float ff These variations protect more data.
To String gg: Double precision:
gg = ff.toString(); java.text.DecimalFormat df2
= new java.text.DecimalFormat("###,##0.00");
gg = df2.format(ff.floatValue());
Scientific notation (JDK 1.2.x on up):
java.text.DecimalFormat de
= new
java.text.DecimalFormat("0.000000E00");
gg = de.format(ff.floatValue());
Syntax Comments
From Double dd These variations protect more data.
To String gg: Double precision:
gg = dd.toString(); java.text.DecimalFormat df2
= new java.text.DecimalFormat("###,##0.00");
gg = df2.format(dd.doubleValue());
Scientific notation (JDK 1.2.x on up):
java.text.DecimalFormat de
= new
java.text.DecimalFormat("0.0000000000E00");
gg = de.format(dd.doubleValue());
From Integer ii
To Boolean tt:
tt = new Boolean(ii.intValue() != 0);
From Integer ii
To Character cc:
cc = new Character((char)ii.intValue());
From Integer ii
To Long nn:
nn = new Long(ii.intValue());
From Integer ii
To Float ff:
ff = new Float(ii.intValue());
From Integer ii
To Double dd:
dd = new Double(ii.intValue());
From Long nn
To Boolean tt:
tt = new Boolean(nn.longValue() != 0);
From Long nn Note: Some Unicode values may be rendered as
To Character cc: nonprintable characters. Consult www.unicode.org/
cc = new Character((char)nn.intValue());
From Long nn
To Integer ii:
ii = new Integer(nn.intValue());
From Long nn
To Float ff:
ff = new Float(nn.longValue());
Syntax Comments
From Long nn
To Double dd:
dd = new Double(nn.longValue());
From Float ff
To Boolean tt:
tt = new Boolean(ff.floatValue() != 0);
From Float ff Note: some Unicode values may be rendered as
To Character cc: nonprintable characters. Consult www.unicode.org/
cc = new Character((char)ff.intValue());
From Float ff
To Integer ii:
ii = new Integer(ff.intValue());
From Float ff
To Long nn:
nn = new Long(ff.longValue());
From Float ff
To Double dd:
dd = new Double(ff.floatValue());
From Double dd
To Boolean tt:
tt = new Boolean(dd.doubleValue() != 0);
From Double dd Note: some Unicode values may be rendered as
To Character cc: nonprintable characters. Consult www.unicode.org/
cc = new Character((char)dd.intValue());
From Double dd
To Integer ii:
ii = new Integer(dd.intValue());
From Double dd
To Long nn:
nn = new Long(dd.longValue());
From Double dd
To Float ff:
ff = new Float(dd.floatValue());
Escape sequences
An octal character is represented by a sequence of three octal digits, and a
Unicode character is represented by a sequence of four hexadecimal
digits. Octal characters are preceded by the standard escape mark, \, and
Unicode characters are preceded by \u. For example, the decimal number
57 is represented by the octal code \071 and the Unicode sequence \u0039.
Unicode sequences can represent numbers, letters, symbols, or
nonprinting characters such as line breaks or tabs. For more information
on Unicode, see http://www.unicode.org/
Operators
This section lists the following:
• Basic operators
• Arithmetic operators
• Logical operators
• Assignment operators
• Comparison operators
• Bitwise operators
• Ternary operator
Basic operators
Operator Operand Behavior
. object member Accesses a member of the object.
(<type>) data type Casts a variable to a different data type. 1
+ String Joins up strings (concatenator).
number Adds.
1. It’s important to distinguish between an operator and a delimiter. Parentheses are used
around args (for instance) as delimiters that mark the args in the statement. They are used
around a data type as operators that change a variable’s data type to the one inside the
parentheses.
2. A unary operator affects a single operand, a binary operator affects two operands, and a
ternary operator affects three operands.
Arithmetic operators
Operator Prec. Assoc. Definition
++/–– 1 Right Auto-increment/decrement: Adds one
to, or subtracts one from, its single
operand. If the value of i is 4, ++i is 5. A
pre-increment (++i) increments the value
by one and assigns the new value to the
variable. A post-increment (i++)
increments the value but leaves the
variable with the original value.
+/– 2 Right Unary plus/minus: sets or changes the
positive/negative value of a single
number.
* 4 Left Multiplication.
/ 4 Left Division.
% 4 Left Modulus: Divides the first operand by
the second operand and returns the
remainder (not the result).
+/– 5 Left Addition/subtraction
Logical operators
Operator Prec. Assoc. Definition
! 2 Right Boolean NOT (unary)
Changes true to false or false to true. Because
of its low precedence, you may need to use
parentheses around this statement.
& 9 Left Evaluation AND (binary)
Yields true only if both operands are true.
Always evaluates both operands.
^ 10 Left Evaluation XOR (binary)
Yields true if only one operand is true.
Evaluates both operands.
| 11 Left Evaluation OR (binary)
Yields true if one or both of the operands is
true. Evaluates both operands.
&& 12 Left Conditional AND (binary)
Yields true only if both operands are true.
Called “conditional” because it only evaluates
the second operand if the first operand is true.
|| 13 Left Conditional OR (binary)
Yields true if either one or both operands is
true; returns false if both are false. Doesn’t
evaluate second operand if first operand is
true.
Assignment operators
Operator Prec. Assoc. Definition
= 15 Right Assign the value on the right to the variable
on the left.
+= 15 Right Add the value on the right to the value of the
variable on the left; assign the new value to
the original variable.
–= 15 Right Subtract the value on the right from the value
of the variable on the left; assign the new
value to the original variable.
*= 15 Right Multiply the value on the right with the value
of the variable on the left; assign the new
value to the original variable.
/= 15 Right Divide the value on the right from the value
of the variable on the left; assign the new
value to the original variable.
Comparison operators
Operator Prec. Assoc. Definition
< 7 Left Less than
> 7 Left Greater than
<= 7 Left Less than or equal to
>= 7 Left Greater than or equal to
== 8 Left Equal to
!= 8 Left Not equal to
Bitwise operators
Note A signed integer is one whose left-most bit is used to indicate the integer’s
positive or negative sign: the bit is 1 if the integer is negative, 0 if positive.
In Java, integers are always signed, whereas in C/C++ they are signed
only by default. In Java, the shift operators preserve the sign bit, so that
the sign bit is duplicated, then shifted. For example, right shifting
10010011 by 1 is 11001001.
Ternary operator
The ternary operator ?: performs a very simple if-then-else operation
inside of a single statement. If the first term is true, it evaluates the second;
if the second term is false, it uses the third. This is the syntax:
<expression 1> ? <expression 2> : <expression 3>;
For example:
int x = 3, y = 4, max;
max = (x > y) ? x : y;
This operation assigns to max the value of whichever is greater, x or y.
Index I-1
code primitive 2-2, 5-10
comments 3-3 reading 8-8
reusing 6-23 Strings 2-3
code blocks writing to streams 8-5
defined 3-5 DataOutputStream class
static 10-3 overview 5-22
comments 3-3 declaring a variable 2-5
comparison operators declaring classes 6-2
defined 3-2 declaring packages 6-24
table of 3-10, 11-21 default keyword 6-11, 11-4
compilers defining classes 6-2
just-in-time (JIT) 9-6 deserialization
composite data types 2-3 defined 8-1
arrays 2-4 example 8-6
Strings 2-3 deserializing objects 8-1
conditional statements 4-12 developer support 1-4
if-else 4-12 developing applications 6-4
switch 4-12 do keyword 11-4
constructors 6-4 do loops
calling parent 6-11 using 4-10
multiple 6-11 documentation conventions 1-3
superclasses 6-11 platform conventions 1-4
syntax 3-14 dot operator 6-2
using 3-13 double keyword 11-3
contacting Borland 1-4
newsgroups 1-5 E
World Wide Web 1-5
continue keyword 11-4 else keyword 11-4
continue statements 4-11 Enterprise Edition
control characters 4-4 Enumeration interface
See also escape sequences overview 5-15
control statements 4-11 escape sequences 4-4
conversions table of 11-18
primitive to primitive 11-6 exception handling 4-13
primitive to String 11-7 See also exceptions
primitives to reference types 11-8 defined 4-3
reference to primitive 11-12 keywords, table of 11-5
reference to reference 11-13 exceptions
String to primitive 11-10 catch blocks 4-14
tables of 11-5 finally blocks 4-15
creating a thread 7-5 statements 4-14
creating an object 3-13 throw keyword 4-15
throws keyword 4-15
D try blocks 4-14
extends keyword 6-9, 11-3
daemon threads 7-1 external packages
data and return types importing 6-23
table of 11-3 Externalizable interface 8-8
data members 6-3
accessing 6-11 F
data types
arrays 2-4 File class
composite 2-3 overview 5-24
converting and casting 4-2 file classes 5-23, 5-24
defined 2-2 RandomAccessFile class 5-24
numeric, table of 2-3 file input/output 5-23
Index I-3
java.lang package
overview 5-4
L
java.lang.reflect package language package
overview 5-7 Math class, overview 5-11
java.math package Object class, overview 5-9
overview 5-5 overview 5-4
java.net package String class, overview 5-11
overview 5-8 StringBuffer class, overview 5-12
java.rmi package System class 5-14
overview 5-8 type wrapper classes 5-10
java.security package libraries
overview 5-8 accessing native 10-2
java.sql package Java class 5-1
overview 5-7 static code blocks 10-3
java.text package literals
overview 5-4 defined 2-4
java.util package logical operators
overview 5-4 defined 3-2
javah 10-3 table of 3-8, 11-20
options 10-3 long keyword 11-3
javax packages loop controls
overview 5-6 break statements 4-11
javax.swing package continue statements 4-11
overview 5-5 loop statements
JIT compilers (just-in-time) 9-6 defined 4-3
JNI (Java Native Interface) 10-1, 10-2 loops
JRE (Java Runtime Environment) conditional statements 4-12
relation to JVM 9-2 controlling execution 4-11
just-in-time compilers (JIT) 9-6 keywords, table of 11-4
JVM (Java Virtual Machine) terminating 4-9
advantages 9-2 loops, using 4-9
and JNI 10-2 do 4-10
class loader 9-6 for 4-10
defined 9-1 if-else 4-12
instructions 9-1 switch 4-12
introduction 9-1 while 4-9
main roles 9-2
memory management 9-2 M
portability 9-2
relation to JRE 9-2 Math class
security 9-2 overview 5-11
specification vs. implementation 9-2 math functions 5-11
verifier 9-3 math operators
table of 3-7
using 3-7
K math package
keywords overview 5-5
access modifiers 4-6, 11-4 member access 3-14
data and return types 11-3 member variables 6-3
defined 3-1 memory allocation
exception handling 11-5 getting StringBuffer 5-13
loops 11-4 memory management
packages, classes, members, interfaces 11-3 role of JVM 9-2
reserved 11-5 method calls 6-3, 10-2
tables of 11-3 methods 2-5
accessing 10-2
Index I-5
R source code
reusing 6-23
RandomAccessFile class SQL package
overview 5-24 overview 5-7
reading data types 8-8 Standard Edition 11-2
reading object streams 8-8 starting a thread 7-6
readObject() 8-6, 8-8 statements
reference data types defined 3-5
converting to other reference 11-13 static code blocks 10-3
converting to primitive 11-12 static keyword 4-6, 11-3
referencing objects 6-2, 8-8 stopping a thread 7-7
reflections package storing objects to disk 8-1
overview 5-7 stream resources
reserved keywords freeing 8-6
table of 11-5 streams 8-4, 8-6
resources input streams 5-17
freeing stream 8-6 output streams 5-20
restoring objects 8-1 partitioning as tokens 5-25
return keyword 11-3 read/writes 8-8
return statements 4-3 StreamTokenizer class
return types 4-3 overview 5-25
RMI package strictfp keyword 11-3
overview 5-8 String class
run() 7-2 overview 5-11
Runnable interface String data type
implementing 7-3 converting to primitive 11-10
runtime environment, Java 9-2 defined 2-3
See also JRE StringBuffer class
overview 5-12
S strings 4-1
constructing 5-11
saving objects 8-1 handling 4-1, 4-4
scope manipulating 4-1
defined 3-5 subroutines 2-5
security See also methods
applet vs. application 9-5 super keyword 6-11, 11-3
class loader 9-6 superclasses 6-10
in the JVM 9-2 Swing package
serialization and 8-8 overview 5-5
security manager 9-4 switch keyword 11-4
security package 9-4 switch statements 4-12
overview 5-8 synchronized keyword 11-3
security policy 9-4 synchronizing threads 7-8
SecurityManager class 9-4 System class 5-14
Serializable interface 8-2
serialization
defined 8-1
T
reasons for 8-1 technical support 1-4
security and 8-8 ternary operator 3-12, 11-22
serializing objects 8-1 defined 3-3
setSecurityManager() 9-5 test conditions, aborting 4-11
setter methods 6-13 text package
setting thread priority 7-7 overview 5-4
short keyword 11-3 this keyword 11-3
single inheritance 6-10 Thread class
subclassing 7-2
U
UnsatisfiedLineError exceptions 10-3
Usenet newsgroups 1-5
utility classes
overview 5-4
utility package
Enumeration interface, overview 5-15
overview 5-4
Vector class, overview 5-16
Index I-7