Comments

advertisement
Comments
Computer programs are read by both computes and humans. You write Java instructions to
tell the computer what to do. You must also write comments to explain to humans what the
program does. Of course, Java can't understand them because they are written in English, or
Spanish, or Thai, or ... .
Java ignores all comments. There is, however, a program called javadoc which reads certain
kinds of comments and produces HTML documentation (see below).
Spaces and blank lines
One of the most effective ways to make a program readable is to put spaces in at key points. There
are several styles for doing this. Even more important is to put blank lines in your program. These
should separate sections of code. There should be a blank line between each "paragraph" of code.
By paragraph, I mean a group of statements that belong together logically; there is no Java concept
of paragraph.
Java comments
// comments -- one line
After the two // characters, Java ignores everything to the end of the line. This is the most
common type of comment.
//--- local variables --int nquest;
// number of questions.
int score;
// count of number correct minus number
wrong.
/* ... */ comments -- multiple lines
After the /* characters, Java will ignore everything until it finds a */. This kind of
comment can cross many lines, and is commonly used to "comment out" sections of code -making Java code into a comment while debugging a program. For example,
/* Use comments to describe variables or sections of the
program.
They are very helpful to everyone who reads your programs:
your teacher, your boss, but especially yourself!
*/
javadoc comments
Comments that start with /** are used by the javadoc program to produce HTML
documentation for the program. The Java documentation from Sun Microsystems is
produced using javadoc. It is essential to use this kind of comment for large programs.
Best Practices

Don't write comments to document obvious statements. Assume the reader knows Java.

Every comment has the potential to create an inconsistency between what the comment
says, and what the code does. One cause of "software rot" is that code is changed over
time, but comments are not updated. To avoid this, keep comments next to the code that is
documented so that they may be more easily synchonized.
Interesting comments

Write Sweet-Smelling Comments by Mike Clark.

Otaku, Cedric's weblog
Identifier Names
Getting the names of things right is extremely important. It makes a huge difference in readability.
Many IDEs support refactoring, and specifically renaming. I will sometimes rename classes several
times before I hit on exactly the obvious name. It's worth the effort.
Legal Characters
Every name is made from the following characters, starting with a letter:

Letters: a-z, A-Z, and other alphabetic characters from other languages.

Digits: 0-9

Special: _ (underscore)
No names can be the same as a Java keyword (eg, import, if, ...).
Examples
apple
This is a legal name. Lowercase implies it's a variable or method.
Apple
This is a different legal name. Uppercase implies it's a class or interface.
APPLE
Yet a different legal name. All uppercase implies it's a constant.
topleft
Legal, but multiple words should be camelcase.
top_left Better, but camelcase is preferred to _ in Java.
topLeft
Good Java style
top left ILLEGAL - no blanks in a name
import
ILLEGAL - same as the Java keyword
Using Uppercase, Lowercase, and "Camelcase" Letters
The conventions for the use of upper- and lowercase is not enforced by compilers, but it is so widely
observed, that it should have been. Camelcase is the practice of capitalizing the first letter of
successive words in multi-word identifiers. Camelcase is much preferred in the Java community over
the use of underscores to separate words, or even worse, no distinction made at word boundaries.
Class and interface names - Start with uppercase
Class and interface names start with an uppercase letter, and continue in lowercase. For
multiple words, use camelcase. Eg, Direction, LogicalLayout, DebugGapSpacer.
Variable and method names - Lowercase
Lowercase is used for variable and method names. If a name has multiple words, use
camelcase. Eg, top, width, topLeft, roomWidth, incomeAfterTaxes.
Constants - All uppercase, use _ to separate words
The names of constants (typically declared static final) should be in all uppercase. For
example, BorderLayout.NORTH. When constant names are made from multiple words,
use an underscore to separate words, eg, JFrame.EXIT_ON_CLOSE
Readable names are more important than most comments
Java doesn't care if your names are readable, but it's really important to make your names readable
to humans.
I once worked on a project where we had to distribute the source code so that it could be compiled
on another machine, but we didn't want to reveal our algorithms. We deleted all comments and
indentation, and wrote a small program to change all variable names to combinations of "I", "1",
"O", and "0", figuring that it would be too much effort for them to decode it. For example, the semireadable
LogicalGapInfo topBorder =
m_logicalLayout.getGapInfo(LogicalLayout.AXIS_V, 0);
Could be translated into
I001O I00I0 = O1001.OI001(O1OOI.IO010, 0);
Packages and Import
Package = directory. Java classes can be grouped together in packages. A package name is the
same as the directory (folder) name which contains the .java files. You declare packages when you
define your Java program, and you name the packages you want to use from other libraries in an
import statement.
Package declaration
The first statement, other than comments, in a Java source file, must be the package declaration.
Following the optional package declaration, you can have import statements, which allow you to
specify classes from other packages that can be referenced without qualifying them with their
package.
Default package. Altho all Java classes are in a directory, it's possible to omit the package
declaration. For small programs it's common to omit it, in which case Java creates what it calls a
default package. Sun recommends that you do not use default packages.
Package declaration syntax
The statement order is as follows. Comments can go anywhere.
1.
Package statment (optional).
2.
Imports (optional).
3.
Class or interface definitions.
// This source file must be Drawing.java in the illustration
directory.
package illustration;
import java.awt.*;
public class Drawing {
. . .
}
Imports: three options
The JOptionPane class is in the swing package, which is located in the javax package. The wildcard
character (*) is used to specify that all classes with that package are available to your program.
This is the most common programming style.
import javax.swing.*;
used.
// Make all classes visible altho only one is
class ImportTest {
public static void main(String[] args) {
JOptionPane.showMessageDialog(null, "Hi");
System.exit(0);
}
}
Classes can be specified explicitly on import instead of using the wildcard character.
import javax.swing.JOptionPane;
// Make a single class visible.
class ImportTest {
public static void main(String[] args) {
JOptionPane.showMessageDialog(null, "Hi");
System.exit(0);
}
}
Alternately we can the fully qualified class name without an import.
class ImportTest {
public static void main(String[] args) {
javax.swing.JOptionPane.showMessageDialog(null, "Hi");
System.exit(0);
}
}
Common imports
There are 166 packages containing 3279 classes and interfaces in Java 5. However, only a few
packages are used in most programming. GUI programs typically use at least the first three imports.
import java.awt.*;
Common GUI elements.
import java.awt.event.*; The most common GUI event listeners.
import javax.swing.*;
More common GUI elements. Note "javax".
import java.util.*;
Data structures (Collections), time, Scanner, etc classes.
import java.io.*;
Input-output classes.
import java.text.*;
Some formatting classes.
import java.util.regex.*; Regular expression classes.
import FAQ
1.
Q: Does importing all classes in a package make my object file (.class or .jar)
larger?
A: No, import only tells the compiler where to look for symbols.
2.
Q: Is it less efficient to import all classes than only the classes I need?
A: No. The search for names is very efficient so there is no effective difference.
3.
Q: Doesn't it provide better documentation to import each class explicitly?
A: This shows good intentions, but ...
4.
o
It's hard to remember to remove classes when they are no longer used, so the
import list is surprisingly often wrong. It can seriously slow down reading because
unusual or unexpected class imports make me look for that class, only to discover
that it must have been used in an earlier version.
o
Explicit class imports permit accidentally defining classes with names that conflict
with the standard library names. This is very bad. Using "*" to import all classes
prevents this dangerous naming accident.
o
It's annoying to always update this list, altho if you use NetBeans, fixing the list is
only a click away (see below).
Q: I've imported java.awt.*, why do I also need java.awt.event.*?
A: The wildcard "*" only makes the classes in this package visible, not any of the
subpackages.
5.
Q: Why don't I need an import to use String, System, etc?
A: All classes in the java.lang package are visible without an import.
6.
Q: Is the order of the imports important?
A: No. Group them for readability.
NetBeans creates packages by default

The project name is used as the default package name, but you can change it.

A directory / folder is created with this project name. This directory name is the name of
your package.

A package declaration is automatically inserted into each new source file it creates.

When you build a main project, the double-clickable .jar file uses this
project/package/directory name.
NetBeans will create your imports
If you forgot to write import statements, or don't remember which package a class is in, no
problem. Just right click on the source file and choose Fix Imports. It will add all necessary import
statements.
Static imports in Java 5
Java 5 added an import static option that allows static variables (typically constants) to be
referenced without qualifying them with a class name. For example, after
import static java.awt.Color;
It would then be possible to write
Color background = RED;
instead of
Color background = Color.RED;
Adding this "feature" wasn't the best idea because it leads to name pollution and confusion about
which class constants come from. Even Sun (see References below) basically advises not to use it!
The Many Meanings of final
The final modifier can be applied to four Java constructs:
1. variables: a final variable can be set once and only once.
2. fields: a final field can also be set only once, by the constructor of the class which
defines it.
3. methods: a final method cannot be overridden nor hidden.
4. classes: a final class cannot be extended.
Notice how using final is an entirely negative act. The final keyword works by
subtracting, limiting default language mechanisms: the ability to override a method, to set
a variable or a field. The motivations behind using final fall into three broad categories:
correctness, robustness, and finally performance.
Final Variables
A final variable can be set only once, allowing you to declare local constants. Such a
variable can be left un-assigned at the point of declaration, creating blank finals. But all
final variables must be assigned exactly once. Final variables come in handy in mostly
two situations: to prevent accidental changes to method parameters, and with variables
accessed by anonymous classes.
Final Parameters
The following sample declares final parameters:
public void doSomething(final int i, final int j)
{
// ...
}
final
is used here to ensure the two indexes i and j won't accidentally be reset by the
method. It's a handy way to protect against an insidious bug that erroneously changes the
value of your parameters. Generally speaking, short methods are a better way to protect
from this class of errors, but final parameters can be a useful addition to your coding style.
Note that final parameters are not considered part of the method signature, and are
ignored by the compiler when resolving method calls. Parameters can be declared final
(or not) with no influence on how the method is overriden.
Anonymous Local Classes
The second situation involving final variables is actually mandated by language
semantics. In that situation, the Java compiler won't let you use a variable unless it is
declared final. This situation arises with closures, also known as anonymous local classes.
Local classes can only reference local variables and parameters that are declared final.
public void doSomething(int i, int j)
{
final int n = i + j; // must be declared final
Comparator comp = new Comparator()
{
public int compare(Object left, Object right)
{
return n; // return copy of a local variable
}
};
}
The reason for this restriction becomes apparent if we shed some light on how local
classes are implemented. An anonymous local class can use local variables because the
compiler automatically gives the class a private instance field to hold a copy of each local
variable the class uses. The compiler also adds hidden parameters to each constructor to
initialize these automatically created private fields. Thus, a local class does not actually
access local variables, but merely its own private copies of them. The only way this can
work correctly is if the local variables are declared final, so that they are guaranteed not
to change. With this guarantee in place, the local class is assured that its internal copies of
the variables accurately reflect the actual local variables.
Final Fields
A final field can be assigned once and only once, and must be initialized by every
constructor of the class that declares it. It is also possible to assign the field directly, in
the same statement where it is defined. This simply reflects the fact that such shortcut
assignments are compiled into a synthetic constructor. E.g. both the following code
samples are correct and strictly equivalent; the first is preferred for being shorter.
public class MyClass
{
private final int i = 2;
}
public class MyClass
{
private final int i;
public MyClass()
{
i = 2;
}
}
Declare Constants
Coupled with static, final is used to flag constants. This usage is well-known to all
Java programmers, so I won't expand much on it. It is useful to know that the value of a
field declared constant in that manner will be computed statically if possible, at compiletime.
private static final int ERROR_CODE = 1 + 3 * 4 / 2;
public static final String ERROR_MESSAGE = "An error occurred with
code=" + ERROR_CODE;
The compiler will compute the value for ERROR_CODE, concatenate the string equivalent
of the result, and assign the resulting String to ERROR_MESSAGE.
Aggregation vs. Acquaintance
In the words of Gamma et al.'s Design Patterns:
Aggregation implies that one object owns or is responsible for another object. Generally
we speak of an object having or being part of another object. Aggregation implies that an
aggregate object and its owner have identical lifetimes.
Acquaintance implies that an object merely knows of another object. Sometimes
acquaintance is called "association" or the "using" relationship. Acquainted objects may
request operations of each other, but they aren't responsible for each other. Acquaintance
is a weaker relationship than aggregation and suggests much looser coupling between
objects.
It's easy to confuse aggregation and acquaintance, because they are often implemented in
the same way. Ultimately, acquaintance and aggregation are determined more by intent
than by explicit language mechanisms. Aggregation relationships tend to be fewer and
more permanent than acquaintance. Acquaintance, in contrast, are made and remade more
frequently, sometimes existing only for the duration of an operation. Acquaintances are
more dynamic as well, making them more difficult to discern in the source code.
As it turns out, the Java language does offer an explicit mechanism to differentiate
aggregation relationships from mere acquaitances: the object of this article, the keyword
final. Use it to flag and make explicit aggregations. But why should this be important to
you? The short answer is: to improve code quality.
Enforce Atomicity of Object Creation
Once a field is determined to be an aggregation of another object, and it is declared final,
an interesting property emerges. The aggregating object is guaranteed to be created in full,
or it won't be created at all; either all final fields are initialized successfully, or an
exception terminates the constructor.
Say an object Car aggregates another object Engine, and therefore is defined as
absolutely requiring an Engine instance to function. Declaring the reference to the Engine
as final ensures any Car instance is correctly initialized in full – or the constructor was
terminated abruptly by a thrown exception. The Car class doesn't even compile without
the Engine reference being initialized.
public class Car
{
private final Engine engine;
// always has an engine
public Car()
{
engine = new Engine();
}
}
Simply by tagging a field with final, we have just created a very strong condition on all
Car instances: namely, they must have an Engine to exist. This simple property can
dramatically raise the quality of your code, by enforcing correct aggregation relationships
between objects. The object thus defined, and all its aggregated dependents, always exists
in a stable state.
Declare Invariants
Design by Contract is an effective programming methodology for designing robust
software components: by declaring (and verifying) conditions specific to a given
component, its behavior can be asserted correct, even at runtime. final is a great tool to
enforce field invariance: since final fields can only be set once, any attempt to reset their
value (accidental or not) is detected by the compiler. This idiom is also of great help
during refactoring: it catches refactoring mistakes by acting as a safeguard against the reinitialization of a field.
A caveat applies here: if a final variable holds a reference to an object, the object may be
modified, in spite of it being final. This is because final only applies to the reference
holding the object, not the object itself. The final variable will always refer to the same
object, but the object itself may change through its methods.
This applies also to arrays and collections, because they are both objects. If a final
variable holds a reference to an array, then the components of the array may be changed
by operations on the array, although the variable will always refer to the same array. The
same restriction applies to collections as well. E.g. a list may be declared final and thus
always exist as far as the aggregating object is concerned, its content is undetermined,
and can be changed at will. Elements can be added/removed from the collection, even
though it is declared final.
For Performance
The revised memory model proposed by JSR 133 includes special provisions for final
fields, provisions that are absent from the existing specification. Newer VMs already
implement this specification, and treat final fields accordingly. Because final fields are
assigned exactly once, aggressive optimizations in a multithreaded context become
possible. Specifically, a field doesn't need to be ever reloaded, since its value is
guaranteed never to change.
Conclusion on Final Fields
Extensive use of final fields leads to a new and interesting programming idiom. By
statically enforcing field initialization at construction time, objects can be designed to be
correct, fully initialized, once their construction is complete. Doing so is a simple yet
powerful way to increase both the correctness and robustness of a given object: since it
cannot fail to be correctly initialized, subsequent methods are free to deal with their own
processing, and use whatever fields they need to do said processing, without concern for
the correct initialization sequence of the object.
This idiom strongly relates to eager initialization: all fields are initialized as soon as
possible, at construction, and never changed once the initialization phase is over. In my
experience, developers shun eager initialization because it is perceived as more expensive
than lazy initialization. "I don't need this field until later, so let's not bother with it now,"
their thinking goes. Unfortunately, this line of thinking leads to more complex code that
simply initializing all fields right away. Every usage of the field has to check whether the
field has been initialized, and initialize it if it hasn't. It's akin to premature optimization,
which, as we all know, is the root of all evil.
Compare the two following examples. While it may look like a trivial transformation, in a
real class with potentially dozens of fields, eager initialization will clear up a lot of code
by removing extraneous tests. By declaring all fields final, initialization is gathered in
one place (the constructor), yielding simpler, more maintainable, code.
public class LazyCar
{
private Engine engine; // lazily initialized
public void drive()
{
if (engine == null)
{
engine = new Engine();
}
// ...
}
}
public class BetterCar
{
private final Engine engine = new Engine(); // using final
public void drive()
{
// the engine is always present
// ...
}
}
Final Methods
A final method is implemented exactly once, in the declaring class. Such a method cannot
be overridden: subclasses cannot substitute a new definition for the method. Note that
either modifier private or static also implies final, which is therefore redundant,
when applied to methods. Private and static methods are always implicitely final, since
they cannot be overridden.
Enforce Invariant Code
The Template Method pattern declares an abstract method solely for the purpose of
overriding it in a subclass. This allows the base class to delegate parts of an algorithm to
subclasses. Final methods cannot be overridden, therefore they create an almost exact
anti-"template method" pattern. But in fact, they are best used in conjunction with
template methods. By specifying explicitely which parts of the algorithm can vary (using
abstract methods) and which cannot (using final methods), the class's author conveys a
precise picture of the work expected by subclasses. Final methods are used with template
methods to declare the invariant parts of an algorithm.
public abstract class AbstractBase
{
public final void performOperation()
{
prepareForOperation();
doPerformOperation();
}
// cannot be overridden
protected abstract void doPerformOperation();
// must override
}
Be aware that final methods impose a very strict restriction on subclass implementors. In
a framework context, think long and hard before declaring methods final, as it will
severely limit the extensibility of the framework, and the possibilities of adapting the
framework to situations unforeseen by the original developers.
For Security
In Java all methods are by default overridable. While this gives maximum flexibility to us
programmers, this liberal attitude can sometimes lead to conflicting situations. Let's look
at the Object class for example. It declares methods that certainly must be overridable:
Object.equals and Object.toString are two well-known examples. But Object also
includes methods such as Object.wait and Object.notify – system-level methods
which implement core language capabilities. It simply cannot be allowed for
Object.wait to be substituted by a different implementation. It would alter the
semantics of the language itself.
Final methods come to the rescue again in this case: Object.wait is declared final, and
therefore it cannot be changed, accidentally or not. This reasoning also applies to entire
JDK classes, as discussed below.
For Performance?
Since a final method is only implemented in the declaring class, there is no need to
dynamically dispatch a call to a final method, and static invocation can be used instead.
The compiler can emit a direct call to the method, bypassing entirely the usual virtual
method invocation procedure. Because of this, final methods are also candidates for
inlining by a Just-In-Time compiler or a similar optimization tool. (Remember,
private/static methods are already final, therefore always considered for this optimization.)
Static invocation is faster than dynamic method lookup, leading to the widespread use of
final methods as an optimization technique. But this "optimization" is next to useless in
recent virtual machines: they are able to detect if a non-final method is overridden, and if
not, use static invocation. Therefore, final should be used first and foremost for sofware
engineering reasons, as discussed in the rest of this article.
Final Classes
A final class cannot be subclassed, or extended, in any way. Final classes can be regarded
as a generalization of final methods: a final class has all its method declared final. On the
other hand, fields of a final class do not have any special property.
Enforce Composition over Inheritance
Since final classes cannot be extended, the only way to reuse them is by composing them
with other objects. And encouraging that practice in your own code might prove very
healthy; inheritance, while a powerful technique that should not be dismissed, has it own
share of issues. It introduces a very tight coupling between classes, sometimes leading to
the infamous Fragile Base Class problem. It is also more complex, forcing users to
bounce up and down a class hierarchy in order to understand what a given class does.
And finally, it can break encapsulation by allowing less restrictive access to methods.
Thus final classes are used to enforce composition. This is particularly important with
core classes, classes that define the base functionality of a framework. We look at this
case next.
For Security
One of the very best feature of the Java environment is its ability to dynamically load
classes. Necessarily, this flexibility comes at a price, including a more complex security
model. If classes can be loaded dynamically, at any time, the virtual machine must be
able to enforce security policies on the running code. Final classes are used in this context
to prevent malicious code from altering the semantics of classes essential to the
framework.
The best known example of a final class is certainly java.lang.String. This class is so
vital to the operation of the Java compiler and interpreter that it must be guaranteed that
whenever code uses a string, it gets exactly a java.lang.String and not an instance of
some other class. Because java.lang.String is final, it cannot be subclassed, none of
its methods can be overriden, and therefore any String instance is guaranteed to always
behave the way it is intended.
Immutable Objects
I would like to conclude this article with a section about immutable objects and what a
useful pattern they form.
An immutable object is an object which state is guaranteed to stay identical over its entire
lifetime. While it is perfectly possible to implement immutability without final, its use
makes that purpose explicit, to the human (the software developer) and the machine (the
compiler).
Immutable objects carry some very desirable characteristics:



they are simple to understand and easy to use
they are inherently thread-safe: they require no synchronization
they make great building blocks for other objects
Clearly final is going to help us define immutable objects. First in labelling our object
as immutable, which makes it simple to use and understand by other programmers.
Second in guaranteeing that the object's state never changes, which enable the thread-safe
property: thread concurrency issues are relevant when one thread can change data while
another thread is reading the same data. Because an immutable object never changes its
data, synchronizing access to it is not needed.
Create an immutable class by meeting all of the following conditions:
1. Declare all fields private final.
2. Set all fields in the constructor.
3. Don't provide any methods that modify the state of the object; provide only getter
methods (no setters).
4. Declare the class final, so that no methods may be overridden.
5. Ensure exclusive access to any mutable components, e.g. by returning copies.
Conclusion
I hope you have enjoyed this scrutiny of a sometimes forgotten feature of the Java
language. My references section lists additional resources useful to the reader eager to
keep on learning about final and its uses.
if Statement - Overview
Purpose
The purpose of the if statement is to make decisions, and execute different parts of your program
depending on a boolean true/false value. About 99% of the flow decisions are made with if. [The
other 1% of the decisions use the switch statement.]
General Forms
The if statement has this form, where condition is true or false.
... // Do these statements before.
if (condition) {
... // Do this clause if the condition is true.
}
... // Do these statements after.
or
... // Do these statements before.
if (condition) {
... // Do this clause if the condition is true
} else {
... // Do this clause if the condition is false
}
... // Do these statements after.
Example - EvaluateScore.java
This displays one of two messages, depending on an input value.
1
2
// Description: Evaluate a test score. Illustrates if statement.
// File : if/EvalScore.java
// Author: Fred Swartz - 2007-04-09 - Placed in public domain.
import javax.swing.*;
public class EvalScore {
3
4
public static void main(String[] args) {//... Input a score.
String scoreStr = JOptionPane.showInputDialog(null, "Enter
your score?");
int score = Integer.parseInt(scoreStr);
5
//... Create a message.
String comment;
// Message to the user.
if (score >= 60) {
comment = "Not so bad";
} else {
comment = "This is terrible";
}
6
7
8
//... Output the message.
JOptionPane.showMessageDialog(null, comment);
9
}
}
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Flowchart representation of if statement
The flow of execution in a program is sometimes represented by a flowchart. Flowcharts are
sometimes a good way to outline the flow in a method, especially if it gets complex. They may be
useful in user documentation, but most flowcharting is done in quick sketches, which are thrown
away once the program is written.
Decisions (if statements) are written in diamonds, and computational processes are written in
boxes. There are several styles, and here is one of the most common.
Alternate ways to write the above if statement
There are lots of ways to write the above if statement. Here are some.
1.
Reverse the condition. Which to put first? There are two practices: Either put the normal
case first, or the case that makes the boolean condition easiest to read.
2.
3.
4.
5.
6.
String comment;
// Message to the user.
if (score < 60) {
comment = "This is terrible";
} else {
comment = "Not so bad";
}
7.
Initialize the variable to a default value, and only change it if necessary. This is often used
when the condition is only rarely true.
8.
9.
10.
String comment = "Not so bad;
// Message to the user.
if (score < 60) {
comment = "This is terrible";
}
11. BAD: Two ifs. This is almost always a bad way to write an if-else. It's confusing to read,
border values can slip through, and both conditions must be evaluated (inefficiency).
12.
13.
14.
15.
16.
17.
18.
// BAD BAD BAD BAD BAD BAD BAD BAD BAD
String comment;
// Message to the user.
if (score < 60) {
comment = "This is terrible";
}
if (score >= 60) {
comment = "Not so bad";
}
Brace style
Always write braces. It is good programming style to always write the curly braces, {}, altho
they are not needed if the clause contains only a single statement. There are two reasons this is
good.

Reliability. When code is modified, the indentation is such a strong indicator of structure
that the programmer may not notice that the addition of a statement at the "correct"
indentation level really isn't included in the scope of the if statement. This is a suprisingly
common error.

Readability. It is faster to read code with the braces because the reader doesn't have to
keep in mind whether they are dealing with an un-braced single statement or a braced
block.
History. Braces have been used in most language that have descended from Algol, including C, C++,
Java, C# etc because language designers want to make it easy for programmers in earlier
languages to make the transition. Braces are an annoying and error prone, and numerous
languages, eg, Visual Basic and Python, have tried to choose better notation.
'else' Not Required
'else' is not required
It is not necessary to have the else part of an if statement. Maybe only 50% of the time there is
an else part.
Form
The if statement without an else has this form:
if (condition) {
do this if the condition is true
}
Example
Here is a paintComponent() method with an if statement without an else clause.
public void paintComponent(Graphics g) {
super.paintComponent(g);
// draw background etc.
if (marks < 50) {
g.setColor(Color.red);
}
g.drawString("Score = " + marks, 10, 50);
}
When the paintComponent() method begins, the Graphics context g uses Color.black by default.
Therefore there is no need to set the color to black.
Braces are your friend
Braces { } not required for one statement (but are always good)
If the true or false clause of an if statement has only one statement, you do not need to use
braces (also called "curly brackets"). This braceless style is dangerous, and most style guides
recommend always using them.
Braceless form
The if statement doesn't need braces if there is only one statement in a part. Here both the true
and false parts have only one statement:
// Legal, but dangerous.
if (condition)
Exactly one statement to execute if condition is true
else
Exactly one statement to execute if condition is false
Examples showing what can go wrong
A sample written with braces.
//... Good style - Indented with braces.
String comment = "Not so bad.";
if (marks < 60) {
comment = "This is terrible.";
}
System.out.println(comment);
Without braces it's still correct, but not as safe.
//... Less good style - Indented but without braces.
String comment = "Not so bad.";
if (marks < 60)
comment = "This is terrible.";
System.out.println(comment);
What can go wrong?
Q1: What does this "legal" version print?
//... What does this print?
String comment = "Not so bad.";
if (marks < 60);
comment = "This is terrible.";
System.out.println(comment);
A: it always prints "This is terrible" because of that semicolo after the if clause. The semicolon
indicates an empty statement, which satisfies the compiler, but is surely not what you intended.
Putting a beginning brace after the if condition prevents programmers from also adding a semicolon
and creating this kind of error.
Q2: What's wrong with this?
So your program is working OK without the braces and you decide to add a grade. The compiler is
very happy with this, but you won't be. Why?
//... What does this print?
String comment = "Not so bad.";
String grade
= "A";
if (marks < 60)
comment = "This is terrible.";
grade
= "F";
System.out.println("Your grade is " +grade);
System.out.println(comment);
A: Although the comment will be appropriate to the score, the grade will always be "F". Although
the second grade assignment is indented, it isn't inside the if because the unbraced clause only
includes one statement! This appearance of being included is a major source of programming errors.
Other Java constructions use braces
There are many kinds of Java statements that use braces to group things. You've already seen class
and method (eg, main) declarations, which enclose their contents in braces. In addition to ifs, you'll
learn about loops (for, while, and do), try...catch, and switch statements which use braces to
enclose other statements.
'if' Statement - Indentation
Indent to make programs readable
There are several meathods to make programs readable. How can you easily make the reader see
which statements are inside the true part and false part of an if statement.
The best way to show this is to indent the statements that are inside. To do this you move the
statements to the right by a few spaces. People commonly use two, three, or four spaces. Choose
one number (eg, I use 2 or 3), and use it for all programs.
Java doesn't care about your indentation -- it is for humans (including yourself!).
Example 1 - No indentation - BAD BAD BAD
Here is the paintComponent() method from a previous page without indentation. This is small,
so it's easy to see which statements are in the true and false parts. If the if statement is much
larger, it will be unreadable without indentation.
public void paintComponent(Graphics g) {
super.paintComponent(g);
if (marks < 50)
g.setColor(Color.red);
else
g.setColor(Color.black);
g.drawString("Score = " + marks, 10, 50);
}
Example 2 - No indentation and no line breaks
Even a very short method is almost unreadable when you take out the line breaks and
spaces. Here is the same method:
public void paintComponent(Graphics g) {super.paintComponent(g);if
(marks<50) g.setColor(Color.red);else
g.setColor(Color.black);g.drawString("Score = " + marks,10,50);}
Statement - if inside if
'if'
if inside if
You can put an if statement inside another if statement.
Nearest 'else'
If you use braces, there is no problem with deciding which else goes with which if For example,
if (age < 24) {
if (height > 200) {
c = Color.RED;
}
} else {
c = Color.BLUE;
}
Because the true and false parts are both single statements, you might be tempted to omit braces
and write:
if (age < 24)
if (height > 200)
c = Color.RED;
else
// DANGER: which 'if' goes with this 'else'
c = Color.BLUE;
But this is WRONG, because 'else' always goes with the nearest 'if' when there are no braces. This
code is the same as:
if (age < 24) {
if (height > 200)
c = Color.RED;
else
c = Color.BLUE;
}
Advice: Always use braces on if statements
These kinds of errors are very hard to find. This is another good reason to always use braces.
Watch out for semicolons on your if statements
Why does the following code always say it thinks the user is lying?
String ageStr = JOptionPane.showInputDialog(null, "How old are you?");
int age = Integer.parseInt(ageStr);
if (age > 120 || age < 0);
System.out.println("I think you're lying about your age!");
It's the semicolon! if you put a semicolon directly after the condition in an if statement, Java
thinks it's finished with the body of the statement. The indentation of the next line, which is so
important to human readers, is ignored by Java.
This is another error that's harder to make if you always follow the condition by an opening brace.
'if' Statement - 'else if' style
Series of tests
It is common to make a series of tests on a value, where the else part contains only another if
statement. If you use indentation for the else part, it isn't easy to see that these are really a series
of tests which are similar. It is better to write them at the same indentation level by writing the if
on the same line as the else.
Example -- series of tests - cascading ifs
This code is correctly indented, but ugly and hard to read. It also can go very far to the right if there
are many tests.
if (score < 35) {
g.setColor(Color.MAGENTA);
} else {
if (score < 50) {
g.setColor(Color.RED);
} else {
if (score < 60) {
g.setColor(Color.ORANGE);
} else
{
if (score < 80) {
g.setColor(Color.YELLOW);
} else {
g.setColor(Color.GREEN);
}
}
}
}
Example -- using 'else if' style for formatting
Here is the same example, using a style of writing the if immediately after the else. This is a
common exception to the indenting rules, because it results in more readable programs. Note that it
makes use of the rule that a single statement in one of the Java clauses doesn't need braces.
if (score < 35) {
g.setColor(Color.MAGENTA);
} else if (score < 50) {
g.setColor(Color.RED);
} else if (score < 60) {
g.setColor(Color.ORANGE);
} else if (score < 80) {
g.setColor(Color.YELLOW);
} else {
g.setColor(Color.GREEN);
}
Other languages
Some programming languages recognize this common construction with a special elseif keyword.
Although it is hardly necessary, this kind of small touch can make a language a little nicer to use.
The Java language designers are very conservative about adding keywords to the language, so
don't expect it.
switch Statement - Overview
Purpose of switch: select one of many possible statements to execute
The if statement allows you to select one of two sections of code to execute based on a boolean
value (only two possible values). The switch statement allows you to choose from many
statements based on an integer (including char) or enum value.
Syntax example
Syntax
switch (expr) {
case c1:
statements // do these if expr == c1
break;
case c2:
statements // do these if expr == c2
break;
case c2:
case c3:
case c4:
//
Cases can simply fall thru.
statements // do these if expr ==
any of c's
break;
. . .
default:
statements // do these if expr != any above
}
Switch keywords
switch
The switch keyword is followed by a parenthesized integer expression, which is followed
by the cases, all enclosed in braces.. The switch statement executes the case corresponding
to the value of the expression. Normally the code in a case clause ends with a break
statement, which exits the switch statement and continues with the statement following the
switch. If there is no corresponding case value, the default clause is executed. If no case
matched and there is no default clause, execution continues after the end of the switch
statement.
case
The case keyword is followed by an integer constant and a colon. This begins the
statements that are executed when the switch expression has that case value.
default
If no case value matches the switch expression value, execution continues at the default
clause. This is the equivalent of the "else" for the switch statement. It is written after the
last case be convention, and typically isn't followed by break because execution just
continues out the bottom of switch if this is the last clause.
break
The break statement causes execution to exit to the statement after the end of the switch.
If there is no break, execution flows thru into the next case. Flowing directly into the next
case is almost always an error.
Example - Random comment
String comment;
// The generated insult.
int which = (int)(Math.random() * 3);
//
Result is 0, 1, or 2.
switch (which) {
case 0:
comment = "You look so much better than usual.";
break;
case 1:
comment = "Your work is up to its usual standards.";
break;
case 2: comment = "You're quite competent for so little
experience.";
break;
default: comment = "Oops -- something is wrong with this code.";
}
Equivalent if statement
A switch statement can often be rewritten as an if statement in a straightforward manner. For
example, the preceding switch statement could be written as follows. When one of a number of
blocks of code is selected based on a single value, the switch statement is generally easier to read.
The choice of if or switch should be based on which is more readable.
String comment;
// The generated insult.
int which = (int)(Math.random() * 3);
//
Result is 0, 1, or 2.
if (which == 0) {
comment = "You look so much better than usual.";
} else if (which == 1) {
comment = "Your work is up to its usual standards.";
} else if (which == 2) {
comment = "You're quite competent for so little experience.";
} else {
comment = "Oops -- something is wrong with this code.";
}
Defensive programming
Always include a default clause in your switch statement as a general policy of defensive
programming - assume there will be bugs in your code and make sure they are caught.
Where to use switch?
The ability of switch to choose between many sections of code seems to make it more powerful
than if. However, selecting sections of code depending on specific integer values turns out not to be
very common. If you are handling specific coded values (eg, the number of the button that was
clicked in a JOptionPane), or processing characters (whose codes are treated like numbers), you
may find it useful.
Efficiency? Some compilers can produce more efficient code for certain switch statements than
for equivalent if statements. I haven't bothered to test the Java compiler because, if there is a
speed difference, it would be extremely small and the choice between switch and if should be
based on readability.
Comments on switch
Java's switch statement, which was taken directly from C++ to increase its attractiveness to C++
programmers, is not well loved.

No ranges. It doesn't allow ranges, eg case 90-100:. Many other languages do.

Integers only. It requires integers and doesn't allow useful types like String. Many other
languages do.

Error-prone. It is error-prone and a common source of bugs - forgetting break or
default silently ignores errors. Some languages have eliminated these dangerous
situations.
switch Example - Random Insults
The following class could be
useful for generating
random insults in response
to erroneous user input.
Source code formatting.
Some of the cases are
formatted on a single line.
This is a common style
when they do similar short
actions. It makes the switch
statements much easier to
read.
Separate model (logic) from user interface. This program is separated into two classes: one
contains the logic (or "model" as it's more often called) for generating an insult as a string. It knows
nothing about the user interface, and could equally well be used in a dialog program (as in the test
program below), console I/O, a GUI program, or a web-based application.
Random Insult Model
This is the logic of the program, and does no I/O so it would be equally suitable as the logic behind
a console program, GUI program, or web server program.
1
2
3
4
5
6
7
8
9
10
11
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
File
: flow-switch/insult/InsultGenerator1.java
Purpose: Generates random insults.
Author : Fred Swartz 2006 Aug 23 Placed in public domain
Comments: This switch statements were written in the
most conservative style -- a default clause
and no returns in them.
The structure of the random generation is
entirely in executable code,
A much better way to write this is as a
data-Driven program, where this information is
represented by data structures, with a
simple program to process the data.
The data-driven style allows the data to be
read in from user-editable files for example,
so the program need not be recompiled for changes.
12
13
14
15
16
17
18
19
20
21
public class InsultGenerator1 {
//============================================ badInputInsult
public static String badInputInsult() {
String insult;
switch (rand(2)) {
case 0: insult = "What kind of "
+ infoAdjective() + " "
+ infoNoun()
+ " is this, you "
+ personAdjective() + " "
+ person()
+ "?";
break;
22
case 1: insult = "Never enter this kind of "
+ infoAdjective() + " "
+ infoNoun()
+ " again!!!!";
break;
23
24
25
26
default:insult = "Oops -- bad switch statement";
}
return insult;
27
28
29
30
}
//==================================================== person
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
private static String person() {
String name;
switch (rand(3)) {
case 0 : name = "idiot"
; break;
case 1 : name = "imbecile"; break;
case 2 : name = "moron"
; break;
default: name = "bad value from person???";
}
return name;
}
//=========================================== personAdjective
private static String personAdjective() {
String adj;
switch (rand(4)) {
case 0 : adj = "clueless"; break;
case 1 : adj = "witless" ; break;
case 2 : adj = "stupid" ; break;
case 3: adj = "hopeless"; break;
default: adj = "bad value from infoAdjective???";
}
return adj;
}
//============================================= infoAdjective
private static String infoAdjective() {
String adj;
switch (rand(5)) {
case 0: adj = "revolting" ; break;
case 1: adj = "insulting" ; break;
case 2: adj = "meaningless"; break;
case 3: adj = "useless"
; break;
case 4: adj = "idiotic"
; break;
default:adj = "bad value from infoAdjective???";
}
return adj;
}
//================================================== infoNoun
private static String infoNoun() {
String noun;
switch (rand(4)) {
case 0: noun = "nonsense"; break;
case 1: noun = "crap"
; break;
case 2: noun = "swill"
; break;
case 3: noun = "garbage" ; break;
default:noun = "bad value from infoNoun???";
}
return noun;
}
//===================================================== rand
// Utility method to generate random numbers in range 0..bound-
66 1.
// Starting the range at zero was simply to match the typical
// Java ranges (eg, switch, subscripts) that start at zero.
// Returns random int in range 0...bound-1
private static int rand(int bound) {
return (int) (Math.random() * bound);
}
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
}
101
102
103
104
105
Main program
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//
//
//
//
//
File
:
Purpose:
Author :
License:
Date
:
flow-switch/insult/TestTextGenerator1.java
Show some random insults.
Fred Swartz
public domain
2006 May 3
import javax.swing.*;
public class TestTextGenerator1 {
public static void main(String[] args) {
String display;
do {
display = InsultGenerator1.badInputInsult()
+ "\n\nWould you like another opinion?";
} while (JOptionPane.showConfirmDialog(null, display) ==
JOptionPane.YES_OPTION);
}
}
17
Data-driven programming
Replace methods with data structure? This version is written with executable Java code. It is
usually very desirable to replace executable code with some kind of data structure. There are
several reasons for this.

Data can be stored in user-editable files, which allows modifying the functioning of the
program without recompiling, or even having access to the source code.

Every line of code is a liability! Keeping code small is a very good goal. It looks like nothing
can go wrong here, but surely it will sometime when the program is updated.
Programming problems
1.
2.
3.
Problem (using arrays): Get rid of the methods, and replace them with arrays of strings.
You'll find it useful to define a method to choose a random element from an array of Strings.
To keep this problem simple don't read the data in from files. It might look like
private static String chooseRandom(String[] words)
Problem (using Map and File I/O): Another way to think about this problem is to have a
special syntax to denote something that should be replaced -- I'll use "angle brackets" to
surround terms that should be replaced by a something that is dynamically generated. For
example, the starting element could be the string "<insult>".
The program would then look up the definition of "insult" in something like
HashMap<String, ArrayList<String>> and randomly choose one of the strings
from the array list. For example, it might replace "<insult>" with "Never enter this kind of
<infoAdj> <infoNoun> again!!!!"
The program would then find each thing surrounded by angle brackets and replace it with a
randomly chosen values from its associated arrays. This process is repeated until all angle
bracketted symbols have been replaced.
Read data in from a file. One plausible format would be to have the the "meta-symbols"
start in column 1, and all possible definitions follow on lines that start with a blank. For
example,
<insult>
Never enter this kind of <infoAdj> <infoNoun> again!!!!
What kind of <infoAdj> <infoNoun> is this, you <personAdj>
<person>?
<infoAdj>
revolting
insulting
meaningless
useless
idiotic
. . .
Loops - Introduction
The purpose of loop statements is to repeat Java statements many times. There are several kinds of
loop statements in Java.
while statement - Test at beginning
The while statement is used to repeat a block of statements while some condition is true. The
condition must become false somewhere in the loop, otherwise it will never terminate.
//... While loop to build table of squares.
String result = "";
// StringBuilder would be more efficient.
int i = 1;
while (i <= 20) {
result = result + i + " squared is " + (i * i) + "\n";
i++;
}
JOptionPane.showMessageDialog(null, "Tables of squares\n" + result);
The following example has an assignment inside the condition. Note that "=" is assignment, not
comparison ("=="). This is a common coding idiom when reading input.
//... Add a series of numbers.
JOptionPane.showMessageDialog(null, "Enter ints.
Cancel to end");
String valStr;
int sum = 0;
while ((valStr = JOptionPane.showInputDialog(null, "Number?")) !=
null) {
sum += Integer.parseInt(valStr.trim());
}
JOptionPane.showMessageDialog(null, "Sum is " + sum);
for statement - Combines three parts
Many loops consist of three operations surrounding the body: (1) initialization of a variable, (2)
testing a condition, and (3) updating a value before the next iteration. The for loop groups these
three common parts together into one statement, making it more readable and less error-prone
than the equivalent while loop. For repeating code a known number of times, the for loop is the
right choice.
//... For loop to build table of squares.
String result = "";
// StringBuilder would be more efficient.
for (int i = 1; i <= 20; i++) {
result += i + " squared is " + (i * i) + "\n";
}
JOptionPane.showMessageDialog(null, "Tables of squares\n" + result);
do..while statement - Test at end
When you want to test at the end to see whether something should be repeated, the do..while
statement is the natural choice.
String ans;
do {
. . .
ans = JOptionPane.showInputDialog(null, "Do it again (Y/N)?");
} while (ans.equalsIgnoreCase("Y"));
"foreach" statement - Java 5 data structure iterator
Java 5 introduced what is sometimes called a "for each" statement that accesses each successive
element of an array, List, or Set without the bookkeeping associated with iterators or indexing.
//... Variable declarations.
JTextArea nameTextArea = new JTextArea(10, 20);
String[] names = {"Michael Maus", "Mini Maus"};
//... Display array of names in a JTextArea.
for (String s : names) {
nameTextArea.append(s);
nameTextArea.append("\n");
}
Similar to the 'if' statement
There are three general ideas that you will see in many parts of Java.

Braces {} to enclose multiple statements in the body.

Indentation to show the extent of the body clearly.

Boolean (true/false) conditions to control whether the body is executed.
Scope of loop indicated with braces {}
If the body of a loop has more than one statement, you must put the statements inside braces. If
there is only one statement, it is not necessary to use braces {}. However, many programmers
think it is a good idea to always use braces to indicate the scope of statements. Always using
braces allows the reader to relax and not worry about the special single statement case.
Indentation. All statements inside a loop should be indented one level (eg, 4 spaces), the same as
an if statement.
'while' Statement
Purpose - to repeat statements
The purpose of the while statement is to repeat a group of Java statements many times. It's
written just like an if statement, except that it uses the while keyword.
General Form
The while statement has this form:
while (condition) {
statements to repeat while the condition is true
}
Condition is true or false
The value of condition must be true or false (ie, a boolean value). It is often a comparison
(see example below).
Example: Loop continues while the condition is true
public void paintComponent(Graphics g) {
super.paintComponent(g);
int count = 0;
while (count < 50) {
g.drawLine(20, count*5, 80, count*5);
count = count + 1;
}
g.drawString("Loop is finished.
count="+count, 10, 300);
}
This repeats the drawLine() call 50 times. The first time the while condition is tested, it is true
because the value of count is 0, which is less than 50. After the statements in the body are done,
the while loop comes back to the top of the loop and makes the test again. Each time the value of
count is larger. Finally, count is 50, and the value of the condition will be false.
When the loop stops, the program continues with the statement after the end of the loop (the
drawLine() call). This will display the string "Loop is finished. count=50".
Example with flowchart
The following shows some code and the equivalent flowchart.
int n = 0;
int i = 1;
while (i < 4) {
n++;
i++;
}
. . .
Here is another example of code and an equivalent flowchart
int n = 0;
int i = 1;
while (i < 4) {
int j = 1;
while (j<=i) {
n += 1;
j++;
}
i = i + 1;
}
'for' Loop
Purpose
The for statement is similar to the while statement, but it is often easier to use if you are counting
or indexing because it combines three elements of many loops: initialization, testing, and
incrementing.
General Form
The for and equivalent while statements have these forms.
for (init-stmt; condition; nextstmt) {
init-stmt;
while (condition) {
body
body
next-stmt;
}
}
There are three clauses in the for statement.
1.
The init-stmt statement is done before the loop is started, usually to initialize an iteration
variable.
2.
The condition expression is tested before each time the loop is done. The loop isn't
executed if the boolean expression is false (the same as the while loop).
3.
The next-stmt statement is done after the body is executed. It typically increments an
iteration variable.
Example - Printing a table of squares
Here is a loop written as both a while loop and a for loop. First using while:
int number = 1;
while (number <= 12) {
System.out.println(number + " squared is " + (number * number));
number++;
}
And here is the same loop using for.
for (int number = 1; number <= 12; number++) {
System.out.println(number + " squared is " + (number * number));
}
Example - Counting doubled characters
This code will look at each character in a string, sentence, and count the number of times any
character occurs doubled.
String sentence = ...;
int doubleCount = 0;
// Number of doubled characters.
// Start at second char (index 1).
for (int pos = 1; pos < sentence.length(); pos++) (
// Compare each character to the previous character.
if (sentence.charAt(pos) == sentence.charAt(pos-1)) {
doubleCount++;
}
}
Summary
The for loop is shorter, and combining the intialization, test, and increment in one statement makes
it easier to read and verify that it's doing what you expect. The for loop is better when you are
counting something. If you are doing something an indefinite number of times, while loop may be
the better choice.
For-each Loop
Purpose
The basic for loop was extended in Java 5 to make iteration over arrays and other collections more
convenient. This newer for statement is called the enhanced for or for-each (because it is called this
in other programming languages). I've also heard it called the for-in loop.
Use it in preference to the standard for loop if applicable (see last section below) because it's much
more readable.
Series of values. The for-each loop is used to access each successive value in a collection of
values.
Arrays and Collections. It's commonly used to iterate over an array or a Collections class (eg,
ArrayList).
Iterable<E>. It can also iterate over anything that implements the Iterable<E> interface (must
define iterator() method). Many of the Collections classes (eg, ArrayList) implement
Iterable<E>, which makes the for-each loop very useful. You can also implement Iterable<E> for
your own data structures.
General Form
The for-each and equivalent for statements have these forms. The two basic equivalent forms are
given, depending one whether it is an array or an Iterable that is being traversed. In both cases an
extra variable is required, an index for the array and an iterator for the collection.
For-each loop
Equivalent for loop
for (type var : arr) {
body-of-loop
}
for (int i = 0; i < arr.length;
i++) {
type var = arr[i];
body-of-loop
}
for (type var : coll) {
body-of-loop
}
for (Iterator<type> iter =
coll.iterator(); iter.hasNext(); )
{
type var = iter.next();
body-of-loop
}
Example - Adding all elements of an array
Here is a loop written as both a for-each loop and a basic for loop.
double[] ar = {1.2, 3.0, 0.8};
int sum = 0;
for (double d : ar) {
// d gets successively each value in ar.
sum += d;
}
And here is the same loop using the basic for. It requires an extra iteration variable.
double[] ar = {1.2, 3.0, 0.8};
int sum = 0;
for (int i = 0; i < ar.length; i++) {
successively.
// i indexes each element
sum += ar[i];
}
Where the for-each is appropriate
Altho the enhanced for loop can make code much clearer, it can't be used in some common
situations.

Only access. Elements can not be assigned to, eg, not to increment each element in a
collection.

Only single structure. It's not possible to traverse two structures at once, eg, to compare
two arrays.

Only single element. Use only for single element access, eg, not to compare successive
elements.

Only forward. It's possible to iterate only forward by single steps.

At least Java 5. Don't use it if you need compatibility with versions before Java 5.
Example: String reverse
The following program reverses a string in a very straightforward, but rather inefficient way. When
you learn about StringBuilder (or the equivalent StringBuffer), you can do this more
efficiently. But the purpose of this is to see how looping over a string works.
Nested loops. There are two nested loops in the is program, the outer while loop reads more
input. The inner for loop gets every character from the input string starting at character 0.
1
2
3
//
//
//
//
//
//
//
//
File
: loops/reverse/Reverse.java
Purpose: Reverse a string using a loop.
Author : Fred Swartz
Date
: Oct 23 2005
Comments: Building a String one character at a time
is very inefficient because it requires
creating a new object for each concatenation.
StringBuilder is better, and it already
//
has a reverse() method!
4
import javax.swing.*;
5
public class Reverse {
public static void main(String[] args) {
6
7
8
9
String input;
// Used for the input string.
String reversed; // Reversed form or the input string.
while (true) {
input = JOptionPane.showInputDialog(null, "Enter a
string");
if (input == null) break;
10
11
reversed = "";
for (int i=0; i<input.length(); i++) {
reversed = input.substring(i, i+1) + reversed;
}
JOptionPane.showMessageDialog(null, "Reversed:\n" +
12 reversed);
}
}
13
}
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
While loop vs For loop
Counting. A for loop is preferred to a while loop when counting through a series of numbers -in this case all character positions in a string.
Equivalent. A for loop has the same condition as the equivalent while loop, but also
incorporates an initialization, which would be before the while statement, and the increment,
which would be at the end of the while body. You can write the loop either way, but putting the
initialization, condition, and increment in one statement increases the readability.
For loop
for (int i=0; i<input.length();
i++) {
reversed = input.substring(i,
i+1) + reversed;
}
While loop
int i = 0;
while (i<input.length()) {
reversed = input.substring(i,
i+1) + reversed;
i++;
}
A single character - String or char?
This program uses substring(...) to get a single character. It would be more efficient to use
charAt(...), which returns a single primitive char value.
for (int i=0; i<input.length(); i++) {
reversed = input.charAt(i) + reversed;
}
Assertions
Assertions are used to stop execution when "impossible" situations are
detected
Impossible conditions. Program debugging is filled with "impossible" problems ("But that
parameter can't possibly be null"). If you're lucky, the problem is detected immediately in some way
you can easily diagnose. If not, the error may propagate thru the program, finally crashing, but so
far from the original bug that diagnosis is difficult. Even worse, the bug may not produce visible
symptoms until after it has altered permanent data. Assert statements provide an easy means to
check for impossible conditions, with little or no runtime cost.
Programmer, not user problems. The purpose or asserts is to detect programming errors, and
they should not be used in the case of erroneous user input or actions.
Crash as quickly as possible. Discovering bugs as early as possible is good. Every program starts
with bugs, and the debugging process is faster and simpler when the bugs are detected early. It's
better to discover a problem at compile time than at run time, and it's better to discover a run-time
bug as early as possible. Often a run-time bug doesn't cause an immediate, visible, disaster.
Instead, the consequences of the bug distort the following execution, and the bad effects may not
become visible for a long time. The crippled program may corrupt files or have other bad
consequences. Tracing symptoms back to the original cause can be a long, tedious process. The
goal is to detect bugs as early as possible. Assertions provide a relatively painless way to stop many
bugs before they go too far.
Two forms of the assert statement.
Usual form
An assert statement has two parts separated by a colon. The boolean condition must be
true for execution to continue. If it is false, an AssertionError is thrown, which
terminates execution and display the message string. Some examples.
assert jobQueue.size() == 0 : "processB: queue should have been
empty.";
assert connector != null : "merge: Connector null for " + rel;
When asserts are enabled (more on that below), the assert statement checks the condition
(queue empty, connector is not null, etc) which must be true for the program to function
correctly.. If it's true, execution continues. If it's null, an exception containing the message
is thrown. This message is for the programmer, so it doesn't have to be user friendly. I
typically include the name of the method and sometimes other information that will help
make sense of the error.
Abbreviated form
The simplest form the assert statement specifies only a boolean expression that must be
true. This is OK when there's not much to say, or the likelihood of failing seems so remote
it isn't worth the extra typing.
assert n > 0;
How to figure out if assertions are turned on
Try this program to see if assertions are turned on.
1
2
/** flow-assertion/AssertTest.java - test assertions.
* @author Fred Swartz
* @version 1.01 2005-10-03
*
Compile: javac AssertTest.java
*
Run
: java -ea AssertTest
*/
3
4
5
6
class AssertTest {
//===========================================================
main
public static void main(String[] args) {
// The following assert statement will stop execution
//
with a message if assertions are turned on.
assert false : "Assertions are turned on.";
// The following statement will only be printed if
//
assertions are turned off because assertions
//
were not allowed at run time by the -ea parameter.
System.out.println("Assertions are not active.");
7
8
}
}
9
10
11
12
13
14
15
16
17
18
19
20
Test for consistency
One path to early bug detection is to test variables to see if they have expected values. If
something is wrong, the program can stop and indicate that an unexpected inconsistency was
discovered. Later, when the program is released, this checking may either be disabled to increase
speed, or left in if a "crash" is better than uncontrolled bug propagation (usually the case). If the
checking code is removed or disabled, it should be reinserted or activated during testing all future
updates. Writing checking code can be a major headache, so it isn't done in many cases. The
assert statement makes testing conditions relatively easy, and allows easy activation or
deactivation of some or all of the checking code.
Check for "impossible" conditions, not bad input
assert shouldn't be used for checking for bad input. Input should be checked by code that gives
the user a meaningful response and perhaps a chance to correct the input.
Assertions are used to check for things that can't possibly be wrong! This is what bugs are -- things
that shouldn't happen do happen because there is something wrong with the code. Assertions are
often used in the following cases.

Check situations which must be true, but aren't obviously so. For example, the result of a
complicated calculation must be in a certain range.

All switch statements should have default clauses. If this path is impossible, use an
assert that will always fail.

default:
assert false: "You shouldn't be here!"

Add an assert where control should never flow, eg, when looking up and returning an entry
that "must" be in an array, the code after the loop should never be executed. Put an
assert false: "some message" there.

There is less of a need to check conditions which produce immediate execution errors. For
example, there is no need to check if an array reference is null when the array is used
immediately after that, because a NullPointerException would stop execution. An assert
would allow a better error message, and you must decide if the extra code is worth the
better error diagnostic. In many cases the answer is "no".
Enabling assertions when running in NetBeans or TextPad
Assertion checking defaults to off at runtime, unfortunately. You should always turn them on.
See NetBeans 4.1 IDE for how to enable assertions. This also applies to the NetBeans 5 beta version.
See the TextPad Editor description for how to enable assertions.
Shouldn't runtime assertion checking default on?
1.
Some argue that a production program should not have the overhead of evaluating asserts.
Asserts are not slow, but there is some cost. If they are not turned on at at execution time,
the class loader actually strips out all the assertion code so they really don't take up any
time or memory. But this small amount of time is surely unnoticeable in all but the most
critical tasks.
2.
The user may be presented with an unfamiliar error message. This seems like an especially
bad argument. Does the user really prefer bad results to a strange error message?
Why don't the same people that want assertion checking to default off also want subscript checking
to default off?
Before Java 5
The assert statement was added to Java in version 1.4, but it didn't default on for the compiler
until version 5. You have to explicitly turn it on in Java 1.4 by specifying the "-source 1.4" option to
the compiler.
Exceptions
Exceptions | Exception Usage | Exceptions - More
Java throws an exception
When your program causes an error, Java throws an exception. Java then throws this exception
to a part of the program that will catch it. You shouldn't try to catch most exceptions, but you
should catch all exceptions that are caused by events which you have no control over - exceptions
caused by bad user input or I/O problems.
Processing an exception
When an exception is thrown, execution of that statement stops immediately and Java looks for
someone to catch the exception.
1.
It looks to see if the code that caused the exception is inside a try statement that can
handle the exception. If the try statement has a catch clause that can handle this type of
exception, then it goes to that code. After catch clause is executed, execution resumes after
the end of the entire try statement. It's not possible to return to the point at which the
exception was thrown.
2.
If there is no try statement around the code that threw the exception, Java goes up the
call stack and looks at the statement that called this method, and checks for a try
statement surrounding the call. If it finds an enclosing try statement that has a catch clause
for this kind of exception, the catch clause is executed and then execution continues after
that try statement. Java continues moving up the call stack until it finds an enclosing try
statement.
3.
If no enclosing try statement and catch clause is found, the exception is caught by the
initial Java system method that called main initially. It prints an error message and
terminates the program.
try...catch statement catches exceptions
Put a try...catch statement around any section of code that might generate a user generated
exception (eg, converting text field input to numbers). The simplest form is:
try {
. . . // Normal statements that might cause a problem
} catch (exception-name parameter-name) {
. . . // Statements to execute if exception-name occurred.
}
Example
If the user types an illegal value into a JTextField that expects an integer (eg, "123X45"),
attempting to convert with Integer.parseInt will throw a NumberFormatException.
txt = aTextField.getText();
try {
. . .
// other code
i = Integer.parseInt(txt);
. . .
// process the input
catch (NumberFormatException nfe) {
aTextField.setText("Enter an integer");
}
Exception Usage
Exceptions Exception Usage | Exceptions - More
Common Exceptions To Catch
The most common exceptions to catch are number conversion exceptions and I/O exceptions. Here
are some common exceptions to catch:
Exception
Cause
NumberFormatException
You tried to convert a number from an illegal String form.
InputMismatchException
IOException
A Scanner method, eg nextDouble() will throw this exception
when the next input text is not the right type, eg double.
Catch an IOException to get either of its subclasses below.
FileNotFoundException The specified file didn't exist.
EOFException
Tried to read past end of file.
MalformedURLException
This can be generated if you are using the java.net package.
Suggestions for catching exceptions
If you catch an exception, do something. Don't silence exceptions.
Some programs catch exceptions, then do nothing with them. This is almost always a
mistake, and the underlying error should be fixed.
There are a few cases where you might want to silently ignore an exception. For example,
changing the Look and Feel of the GUI may cause an exception. There's nothing to be done
about it, so you don't want to stop execution. For example, I sometimes use the Liquid look
and feel, and have this code.
try {
UIManager.setLookAndFeel(new
net.sourceforge.napkinlaf.NapkinLookAndFeel());
} catch (Exception e) {
// Silently ignore -- there's nothing to be done.
}
Another example where exceptions are typically ignored is in calls to sleep.
try {
Thread.sleep(DELAY);
} catch (InterruptedException ignoredException) {
// Silently ignore. This thread can never cause an
exception.
}
If you do silently ignore exceptions, enclose only one call in the try clause; do not use
larger blocks of code as suggested below. Rather than silently ignoring exceptions, consider
logging them to a file.
Put larger blocks of code in a try clause
Altho an exception is generated by a single statement, an entire block of code is usually
affected. It is often better to put the try around the block, not just single statements.
Don't catch exceptions that you can't really do anything with
If you can't do anything useful, don't catch an exception. Let someone higher up catch it.
Exception handling is usually slow
It is generally not a good idea to use exception handling mechanism instead of simple if
tests because throwing and catching exceptions is typically much slower.
Catch and rethrow exceptions to clean up
If your code has to clean up something (eg, close files, put a data structure into a
consistent state, ...), it can catch exceptions, do the cleanup, and then rethrow the
exception.
Printing the call stack
For debugging purposes you can print a trace of the current call stack.
e.printStackTrace();
Exceptions - More
Prev: Exception Usage Next: Throwing Exceptions
Kinds of Exceptions
There are many exceptions, but they can be put into two groups: checked exceptions and
unchecked exceptions. There is some controversy about which type you should use. A discussion of
some of the issues can be found at Java theory and practice: The exceptions debate.

Unchecked Exceptions -- These exceptions are usually something that should have been
prevented by more careful programming. For example, you should never get
NullPointerException or ArrayIndexOutOfBoundsException. If you do, there
is something wrong with your program, and you need to fix it. You usually don't catch
unchecked exceptions. Instead, fix your program so it can't produce one of these.
However, NumberFormatException is the one exception of this type that is usually
caught.

Checked Exceptions -- These are usually errors in the input data. The programmer has no
control over the input the user gives you, eg, file names, .... If the user gives you a bad
value, it may cause an exception when you use it. You need to check for bad input
using a try statement.
Use exceptions for exceptional conditions, NOT normal control flow
Probably most of your student programming has been "Happy Trails" style, where you didn't have to
worry much about handling errors. But error handling is really a big deal in most real programs, and
exceptions play a central role in dealing with errors.
All experienced programmers agree that using exceptions for normal processing flow is wrong.
Exceptions should only be used only for errors or unusual conditions, and the equivalent if tests
should be used for normal processing. There are good reasons for this.

Slow. Exceptions are very slow. When an exception occurs, the Java runtime system works
its way up the call stack (you might be surprised at how deep this can get), identifying each
source statement at which a call was made, and building a string that reports this. This
string is then used in creating the exception object that is thrown. This is not fast.

Readability. Experienced programmers expect exceptions to have something to do with
errors, so it is very uncomfortable to read code where it is used for normal flow. A
programmer has to stop and examine the code in the try clause to see what might have
caused the exception.
Here are examples where beginning programmers used exceptions, but should NOT have. These are
all done to either speed execution (which they do not) or simplify code (which they arguably do not).
Example: Test for end of array index range
Good
int[] a = new int[1000];
for (int i=0; i < a.length;
i++) {
a[i] = i;
}
BAD
int[] a = new int[1000];
try {
for (int i=0; ; i++) { // No
range check.
a[i] = i;
}
} catch
(ArrayIndexOutOfBoundsException e) {
}
You might wonder how inefficient this is
because the loop must compare the index
with the array size 1000 times, but only the
final test is important. Because Java always
checks the subscript range anyway, why not Exceptions are so slow that this won't be faster unless
make use of its check?
the array is extremely large (much, much larger than
1000).
Avoiding edges in looking for adjacent array cells.
Problem: You must invert the values in a cell in a rectangular grid and its non-diagonally adjacent
cells. The difficulty is in dealing with the edge cases, where you must avoid referencing non-existent
adjacent cells.
Two alternate definitions of a method are given, one uses exceptions and the other uses if to
handle the boundary violation cases. The exception solution is very inefficient and might be very
hard to interpret by the reader. The difficulty is increased because the writer chose to use the
Exception class instead of ArrayIndexOutOfBoundsException. The use of Exception suggests that it
is designed to catch other exceptions too. if the body of the try had been larger, it might have been
very difficult decide exactly which exception is being caught. Do you see which other exception
could be thrown by the code, at least in principle?
private boolean[][] cell = new boolean[SIZE][SIZE];
. . .
// BAD
public void flipA(int row, int
cell[col ][row ] =
try { cell[col+1][row ] =
{}
try { cell[col-1][row ] =
{}
try { cell[col ][row+1] =
{}
try { cell[col ][row-1] =
{}
}
col) {
!cell[col][row];
!cell[col+1][row
];} catch(Exception e)
!cell[col-1][row
];} catch(Exception e)
!cell[col
][row+1];} catch(Exception e)
!cell[col
][row-1];} catch(Exception e)
// Much better (faster and less worrisome to the normal reader)
public void flipB(int row, int col) {
cell[col ][row ] = !cell[col ][row ];
if (col < SIZE-1) cell[col+1][row ] = !cell[col+1][row ];
if (col > 0
) cell[col-1][row ] = !cell[col-1][row ];
if (row < SIZE-1) cell[col ][row+1] = !cell[col ][row+1];
if (row > 0
) cell[col ][row-1] = !cell[col ][row-1];
}
Another solution to avoid edge cases is to define extra rows and columns of boundary cells, and
translate the subscripts, thereby replacing the if tests with two additions. This requires translating
subscript references in all methods. If the class is properly encapsulated, users of the class will not
know about it.
private boolean[][] cell
. . .
public void flipC(int r,
int row = r + 1;
int col = c + 1;
cell[col ][row ] =
cell[col+1][row ] =
cell[col-1][row ] =
cell[col ][row+1] =
cell[col ][row-1] =
}
= new boolean[SIZE+2][SIZE+2];
int c) {
!cell[col ][row ];
!cell[col+1][row ];
!cell[col-1][row ];
!cell[col ][row+1];
!cell[col ][row-1];
Other examples
There are numerous cases in addition to subscription where the use of exceptions is entirely
inappropriate.
Danger from the intermediate layers - finally
Exceptions provide a good infrastructure for error processing. The simplicity of throwing an
exception at a deep level and catching it at a high level may generate problems at the intermediate,
skipped, levels. Did any of these methods leave any part of a data structure or resource in an
inconsistent state? Each place that this may be true of needs to enclose critical code in a
try...finally block.
References

Exception-Handling Antipatterns by Tim McCune,
today.java.net/pub/a/today/2006/04/06/exception-handling-antipatterns.htm, is a good
article if you're ready for some advanced exception usage.

Three Rules for Effective Exception Handling by Jim Cushing,
http://today.java.net/pub/a/today/2003/12/04/exceptions.html, has some useful "rules",
but even more useful is the list of links what was posted in response to this article.
Throwing Exceptions
Prev: Exceptions
Throwing predefined exceptions
It's common to test parameters of methods or constructors for legality. But if the value is illegal,
what should you do? If your class is designed to be called by other, you should define your own
exceptions, so you can document the errors for them more easily.
But if your methods are only being called by your own code, you can either use an assert or throw
an exception. I often use something like the following, supplying a comment with the class, method,
and meaningful comment.
if (age < 0) {
throw new
IllegalArgumentException("PhysicalExam.scaleBloodPressure: age is
negative");
}
Note that this shouldn't be used for illegal user input -- that should have been checked in the
interface. This should only be thrown if there is a programming error. Only the programmer should
see this exception.
Defining your own exceptions
You can also create your own exceptions. [Not yet written]
Define library exceptions to tell programmer they should fix their code
If you write a library that is used by others, throw your own exceptions if your code is called with
illegal values, eg, something isn't initialized. Your exceptions are a way to tell the applications
programmer that they should fix their code.
Methods 1 - Introduction to
methods
Purpose of this lesson:





Basic purpose of methods.
Term: call = Execution proceeds to the code in a method.
Term: return = Execution of a method finishes and then continues after point of call,
possibly using a value form the method.
Term: static method = Method requiring no extra object.
Term: instance method = Method that operates on the object before the dot.
New Java language features


Static call syntax: className.methodName( arguments )
Instance call syntax: object.methodName( arguments )
Basic idea - A named group of statements - Verbs
By now you have used a lot of the predefined library methods, and written many main methods.
This chapter explains methods in more detail.
Java statements are grouped together in methods. Each method must be inside a class. Every
method has a name, which starts with a lowercase character and typically is a verb because it does
something.
Other terms: The idea of method is in every programming language, but different terms are used
in many languages. You might have seen terms like function, procedure, or subroutine. We'll use
method consistently here, but you will hear programmers using these equivalent terms occasionally.
Business analogy - services provided by an organization
You could think of classes as corresponding to departments in an organization, and methods as
being the services they provide. Let's take an example of calling the telephone information service
to get someone's phone number. When you make the call, you pass information, the name of the
person whose number you want, to the method (information service). This called "method" then
does something, and returns a value to you (the desired phone number). Just as you don't have to
know how the information service performs its job, you typically don't need to know exactly how a
method does its work, unless of course, you are writing it.
Hierarchical organization. Computer programs are structured in many ways like an organization - higher levels rely on others to do much of the work. They "call" on lower levels to do the work,
passing them all necessary "arguments". In a similar way, the top level of a computer program,
main, often consists largely of method calls, and those methods may in turn call on yet other
methods.
Terms: call and return
Call. When a method call is encountered in a program, the program remembers where it was and
execution goes to the method (calls the method). After a small amount of initialization, the
statements in the method are executed starting at the beginning.
Return. When the end of the method is reached or a return statement is executed, the method
returns to the where it was called from, and execution continues in the calling method from that
point. A method may return a value (eg, parseDouble) or not (showMessageDialog). The callreturn terminology is almost universal.
Static (class) methods
Static. This starts with static (also called class) methods because all applications start with the
static method main, and many of the early library methods that you use are static methods. Static
methods are different than instance methods because they don't have an extra object passed to
them.
Instance methods are associated with an object (an "instance" of a class).
Identifying methods
Parentheses follow name. You can identify a method name because it is always followed by left
and right parentheses, which may enclose arguments (parameters). If you see a left parenthesis
with a name preceding it, it will be a method call or definition, or a constructor (constructors are
very similar to methods). In the following example each method name is highlighted.
When calling methods outside of the current class, eg, in the Java library, static methods are
preceded by the class name (followed by a dot), and instance methods are preceded by an object.
When a static method is defined, the keyword "static" will preceded it. The example below has only
static methods.
1
2
3
4
5
6
7
8
9
10
11
12
13
// File
:
// Purpose:
output.
// Author :
// Date
:
methods/KmToMiles.java
Convert kilometers to miles. Use JOptionPane for input /
Fred Swartz
22 Apr 2006
import javax.swing.*;
public class KmToMiles {
//============================================================
constants
private static final double MILES_PER_KILOMETER = 0.621;
//=================================================================
main
public static void main(String[] args)
{
//Note 1
//... Local variables
String kmStr;
// String km before conversion to double.
double km;
// Number of kilometers.
double mi;
// Number of miles.
//... Input
kmStr = JOptionPane.showInputDialog(null, "Enter
kilometers.");
km = Double.parseDouble(kmStr);
//... Computation
mi = km * MILES_PER_KILOMETER;
//... Output
JOptionPane.showMessageDialog(null, km + " kilometers is "
+ mi + " miles.");
14
}
}
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
Notes
1.
This defines a method called "main". Everything between the "{" on the end of this line to
the matching "}" second from the end is the "body" of the method.
The above code defines the static main method, which someone (eg, the operating system) will call
with KmToMiles.main(. . .).
To do its work, main calls on other methods: showInputDialog, which is defined in the
JOptionPane class, parseDouble, which is defined in the Double class, and
showMessageDialog, which is also in the JOptionPane class.
Whenever you call a static method in a different class, precede it with the name of the class
containing its definition, followed by a dot. If you don't specify the class name, it assumes the
method is defined in the current class.
Identifying instance methods
Object precedes. Instance method calls are identified in the following program. Note that they are
all preceded by an object reference. This object is used by the methods to do their work. In this
case, the objects are strings.
In addition to supplying the object's data to the method, the class of the object, eg String, is where
the method is defined.
1
2
3
// File
:
// Purpose:
first use.
// Author :
// Date
:
dialog/capitalize/Capitalize2.java
Capitalize first letter of each name.
Declare with
Fred Swartz - placed in public domain.
30 Mar 2006
import javax.swing.*;
public class Capitalize2 {
4
5
public static void main(String[] args) {
//.. Input a word
String inputWord = JOptionPane.showInputDialog(null, "Enter
a word");
6
7
8
9
//.. Process - Separate word into parts, change case, put
together.
String firstLetter = inputWord.substring(0,1); // Get first
letter
String remainder
= inputWord.substring(1);
// Get
remainder of word.
String capitalized = firstLetter.toUpperCase() +
remainder.toLowerCase();
10
11
12
13
14
//.. Output the result.
JOptionPane.showMessageDialog(null, capitalized);
}
}
15
16
17
18
19
20
21
22
What's before the dot tells whether it's a class or
instance method
What's before the dot? If it's a class name, then it's a static (class) method; if it's an object, it's
an instance method.
Nothing at front when calling methods in same class. When calling your own methods, you
don't have to write anything before the method name. The compiler assumes the same class or
object.
Methods 2 - Actual arguments
(parameters)
Purpose of this lesson:




Left-to-right argument evaluation
Term: actual argument = value which is passed in a method call.
Term: void method = method that doesn't return a value.
Term: value-returning method = method that does return a value.
Terms: actual argument, argument, actual parameter,
parameter
The values that are passed to a method are called actual arguments in the Java specification.
However, it is very common for them to be called just arguments, actual parameters, or just plain
parameters. These terms are so used interchangeably so often that even the Java specification isn't
entirely consistent. For a value which is passed in a call I'll try to stick to actual argument or just
argument, which are generally regarded as the "best" terms.
Identifying method arguments
When you call a method, you can pass information for it to use. These actual arguments are inside
parentheses following the method name. Use commas to separate arguments if there is more than
one. The previous program is shown below, but this time the arguments in the calls are highlighted.
// File
:
// Purpose:
/ output.
// Author :
// Date
:
1
2
3
metho
Conve
Fred
22 Ap
4
import javax.swin
5
6
public class KmTo
//===========
constants
private stati
7
8
9
10
//===============
main
public static
//... Loc
String km
double km
double mi
11
12
13
14
15
//... Inp
kmStr = J
kilometers.");
km = Doub
16
17
18
//... Com
mi = km *
19
20
//... Out
JOptionPa
21
22
}
23 Methods 3 - Defining a static
method
Purpose of this lesson:



Show how to define a method.
Explain parts of method header.
Term: formal parameter = variable in method which gets the argument value.
New Java language features
}

Syntax of method header
Method header syntax
A method header is the part of the method definition that occurs at the beginning. The following
definition leaves out a few obscure features, but gives the syntax of ordinary method headers.
See Syntax Notation to understand how to read the following.
[visibility] ["static"] returnType methodName "(" [parameterList]
methodHeader
=
visibility
= "public" | "private" | "protected" .
parameterList
= parameterDeclaration {"," parameterList} .
")" .
parameterDeclaration = type ParameterName .
returnType
= "void" | type
How to define your own method
The previous program is rewritten below to define a method to convert from kilometers to miles.
The method call, and the first line (header) of the method definition are highlighted.
// File
:
// Purpose:
1
JOptionPane
//
2 // Author :
// Date
:
3
methods/KmToMilesMethod.java
Convert kilometers to miles using a method.
IO.
Highlight call and method definition header.
Fred Swartz
22 Apr 2006
import javax.swing.*;
4 public class KmToMilesMethod {
//============================================================
constants
5
private static final double MILES_PER_KILOMETER = 0.621;
6
//=================================================================
main
7
public static void main(String[] args) {
//... Local variables
8
String kmStr;
// String km before conversion to double.
double km;
// Number of kilometers.
double mi;
// Number of miles.
9
10
11
//... Input
kmStr = JOptionPane.showInputDialog(null, "Enter
kilometers.");
km = Double.parseDouble(kmStr);
//... Computation
mi = convertKmToMi(km);
12
//Note 1
13
//... Output
JOptionPane.showMessageDialog(null, km + " kilometers is "
+ mi + " miles.");
14
}
15
//=========================================================
convertKmToMi
private static double convertKmToMi(double kilometers)
16
{
//Note 2
double miles = kilometers * MILES_PER_KILOMETER;
17
return miles;
}
18 }
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
Notes
1.
2.
Call our own method below to do the conversion. We could have qualified the name with
our class name, KmToMilesMethod.convertKmToMi(km), but this is unnecessary when
calling a static method in the same class.
Altho this method is trivial, just a multiplication, it is good practice to separate the
"model", or "logic", from the user interface. As programs become larger, this separation
becomes essential.
Anatomy of the
convertKmToMi
method header
We'll take a look at each of the parts of the method header in order.
Visibility - public, private, or package
private static double convertKmToMi(double kilometers) {
double miles = kilometers * MILES_PER_KILOMETER;
return miles;
}
For greatest reliability and flexibility in your programs, you should always give methods
the lowest visibility to others that you can.
When you define a method, you should think about who can use it. Generally you want to
choose the lowest level of visibility that makes your program usable, either private or
the default (package). Here are the four options, from least visible to most visible.




private - If you don't want any other class to use it, declare it private. This is
a good choice.
None (package) - If you don't specify anything, the default visibility allows only
classes in the same package (directory) to see it. This is a common choice. It's
common to use public visibility when package visibility is more appropriate -- I
do it myself. The lack of a keyword for package visibility makes it a little harder
to read.
protected - Don't use this protected, except in certain cases to let a child
class see it. Even then, its use is controversial.
public - Let's anyone see it. Choose this if you've defined a method that will be
used by others outside of your project. Note that main must be declared
public so the run-time system can call it.
Class (static) or instance method
private static double convertKmToMi(double kilometers) {
double miles = kilometers * MILES_PER_KILOMETER;
return miles;
}
A method should be declared static if it doesn't user instance variables or methods. A
static method must use only only parameters, local variables, and static constants, and
other static methods in the same class. If the static keyword is omitted, the method
will be an instance method. This example uses static, but soon you will learn about
instance methods too.
Return type
private static double convertKmToMi(double kilometers) {
double miles = kilometers * MILES_PER_KILOMETER;
return miles;
}
Method name
private static double convertKmToMi(double kilometers) {
double miles = kilometers * MILES_PER_KILOMETER;
return miles;
}
Method names should begin with a lowercase letter. Method names are typically verbs,
whereas variable names are usually nouns.
Parameter(s)
private static double convertKmToMi(double kilometers) {
double miles = kilometers * MILES_PER_KILOMETER;
return miles;
}
Parameters are enclosed in parentheses following the method name. They are also called
formal parameters). There is only one parameter in this example - kilometers, but if
there are more, they must be separated by commas. The type of each parameter is
specified before the name (eg, double). Parameters are local variables that only exist
inside the method. They are assigned initial values from the arguments when the method
is called.
Method body
private static double convertKmToMi(double kilometers) {
double miles = kilometers * MILES_PER_KILOMETER;
return miles;
}
The body of a method is the statements which are executed when the method is called
are enclosed in braces following the the method header. Additional local variables may be
defined (eg, miles).
Return statement
private static double convertKmToMi(double kilometers) {
double miles = kilometers * MILES_PER_KILOMETER;
return miles;
}
A method returns to the caller after it has done what it wants. If the method returns a
value (not a void method), it must contain a return statement that specifies a value to
return. When execution reaches the return statement, control transfers back to the
calling method, passing a return value to it.
Returning an expression
The above example returns the value in the local variable miles. The return statement
can be followed by any expression of the appropriate type, not just a single value. For
example, this method body could have been written as a single return statement.
private static double convertKmToMi(double kilometers) {
return kilometers * MILES_PER_KILOMETER;
}
Order of method definitions doesn't matter
If you define multiple methods in a class, you don't have to worry about the order of the
definitions, unlike some other languages.
24
25
26
27
28
29
30
Argument evaluation
Before a method is called, the arguments are evaluated left-to-right. In the example above most
arguments are simple values, except the second argument in the call to showMessageDialog.
Before the call can be made, this argument expression must be evaluated by performing the
conversions to string and the concatenations.
Void and value-returning methods
A method may return a value. In the example above, showInputDialog returns a String and
parseDouble returns a double value. These method calls can be used anywhere in an expression
where a String or double value is required. Here they simply provide the value for the right side of
an assignment.
void. If a method has a "side effect", but doesn't produce a value, it is called a void method. The
showMessageDialog method shows something to the user, but doesn't return a value, and is a
void method.
When a method is defined, you need to specify the keyword void if it doesn't return a value. You
can see this on line 13 where the main method definition starts.
Methods 4 - Local variables
Purpose of this lesson:





Local variables are declared within a method.
Local variable lifetime is from method entry to method return.
Local variable visibility is only within the method.
Local variables have no initial value.
Parameter variables are local variables initialized from the argument values.
New Java language features

final modifier to prevent assignment to parameters.
Principles / Style

Don't assign to parameter variables.
Local variables
Now that we've written two methods, main and convertKmToMi, you should know a little more
about the variables in them.
Variables that are declared in a method are called local variables. They are called local because they
can only be referenced and used locally in the method in which they are declared. In the method
below miles is a local variable.
private static double convertKmToMi(double kilometers) {
double miles = kilometers * MILES_PER_KILOMETER;
return miles;
}
Visibility: Only in defining method
No code outside a method can see the local variables inside another method. There is no need, or
even possibility, of declaring a local variable with a visibility modifier -- local variables are
automatically known only in the method itself.
Lifetime: From method call to method return
Local variables are created on the call stack when the method is entered, and destroyed when the
method is exited. You can't save values in local variables between calls. For that you have to use
instance variables, which you'll learn about a little later.
Initial value: None
Local variables don't have initial values by default -- you can't try to use their value until you assign
a value. It's therefore common to assignment a value to them when they're declared.
Compiler error. If you try to use a local variable before it's been assigned a value, the compiler
will notice it and give an error message. But the compiler doesn't really know the exact order of
execution in a program, so it makes some conservative assumptions. These assumptions can
sometimes be too conservative, and there are cases where you must initialize a local variable even
though you know it will have a value before it's referenced.
// BAD BAD BAD BAD BAD BAD BAD BAD BAD BAD BAD BAD BAD BAD BAD
private static double convertKmToMi(double kilometers) {
double miles;
return miles;
miles.
// Won't compile because nothing was assigned to
}
Parameters are preinitialized local variables
Method parameters are basically implemented as local variables. They have the same visibility
(none outside the method) and lifetime (created on method call, destroyed on method return).
Preinitialized. The difference is that parameters are initialized from the corresponding argument
values.
// Both kilometers and miles are implemented as local variables.
private static double convertKmToMi(double kilometers) {
double miles = kilometers * MILES_PER_KILOMETER;
return miles;
}
Style: Don't assign to a parameter
You can assign to a parameter variable, just as you would to a local variable, but this is often
considered bad style because it can deceive the casual reader in two ways:


Unexpected meaning change.. Programmers assume parameter variables represent
actual argument values. Assigning to parameters breaks that assumption.
Doesn't change actual argument. Because formal parameter variables are really local
variables, assigning new values to them doesn't have any effect on the actual parameters.
However, in some programming languages assignment to a parameter can assign to the
corresponding actual parameter (eg, C++ reference parameters). Therefore if you write an
assignment to a formal parameter variable, it may mislead the careless programmer with a
C++ background. Or the reader may pause and try to decide if you thought you were
assigning to the actual argument. In either case it reduces the readability.
Example. The example below shows how a parameter could be reused. The overhead of declaring
an extra variable is just about zero, so this really isn't more efficient, and even this small example is
astoundingly misleading.
// BAD BAD BAD BAD BAD BAD BAD BAD BAD BAD BAD BAD BAD BAD BAD
private static double convertKmToMi(double kilometers) {
kilometers = MILES_PER_KILOMETER * kilometers;
this, altho it works.
// BAD - Don't do
return kilometers;
}
Style:
final
keyword prevents assignment
Some programmers recommend using the final keyword for each parameter. This prevents
assignment to the parameter. Few programmers do this because it adds extra clutter, which in a
different way reduces the readability. The use of self-restraint in assigning to parameters is usually
suffcient, but specifying final isn't a bad idea.
private static double convertKmToMi(final double kilometers) {
double miles = kilometers * MILES_PER_KILOMETER;
return miles;
}
Methods 7 - How call works
Purpose of this lesson:



Examine the method call/return process in more detail.
Term: call stack = Memory that is used to save return address and local variables.
Term: stack frame = The storage on the call stack that is used by one method.
New Java language features

None.
The table below shows how the call stack changes as calls and returns in the KmToMilesMethods
program are made. This shows the first 8 changes to the call stack after main is entered.
Dynamic changes in the call stack memory allocation
The table below shows how the call stack changes as calls and returns in the KmToMilesMethods
program are made. This shows the first 8 changes to the call stack after main is entered.
There is actually something before main on the call stack, and the library methods that are called
call many methods of their own, which isn't shown here because we don't need to know what they
call.
Stack frame. Each box represents the information that's stored on the call stack for each method.
This block of information is often called a stack frame. There is internal information associated with
the method, for example, it saves the place to resume execution in the calling method. Each stack
frame is labelled with the method name and a list of parameters and local variables that are
allocated on the stack. "???" is written when we don't know (or care) what the local variables are
that are used by a library method.
1
2
main
args
kms
miles
main
args
kms
miles
3
main
args
kms
miles
getDouble getDouble
prompt
prompt
str
str
showInputDialog
???
4
main
args
kms
miles
5
main
args
kms
miles
getDouble getDouble
prompt
prompt
str
str
6
main
args
kms
miles
getDouble
prompt
str
7
main
args
kms
miles
8
main
args
kms
miles
convertKmToMi
kilometers
miles
parseDouble
???
Typical call sequence
1.
2.
3.
4.
5.
Evaluate arguments left-to-right. If an argument is a simple variable or a literal value,
there is no need to evaluate it. When an expression is used, the expression must be
evaluated before the call can be made.
Push a new stack frame on the call stack. When a method is called, memory is
required to store the following information.
o Parameter and local variable storage. The storage that is needed for each of
the parameters and local variables is reserved in the stack frame.
o Where to continue execution when the called method returns. You don't have to
worry about this; it's automatically saved for you.
o Other working storage needed by the method may be required. You don't have to
do anything about this because it's handled automatically.
Initialize the parameters. When the arguments are evaluated, they are assigned to the
local parameters in the called method.
Execute the method. After the stack frame for this method has been initialized, execution
starts with the first statement and continues as normal. Execution may call on other
methods, which will push and pop their own stack frames on the call stack.
Return from the method. When a return statement is encountered, or the end of a void
method is reached, the method returns. For non-void methods, the return value is passed
back to the calling method. The stack frame storage for the called method is popped off the
call stack. Popping something off the stack is really efficient - a pointer is simply moved to
previous stack frame. This means that the current stack frame can be reused by other
methods. Execution is continued in the called method immediately after where the call took
place.
Methods 5 - Example with three
methods
Purpose of this lesson:

Show definition of multiple methods.
Programming ideas



All code is in methods.
Style: The main method often consists largely of method calls.
Style: Methods should generally be no larger than one page.
Here is another variation of the program, this time using three methods. Altho there is no real need
for these methods in such a small program, large programs are in fact composed of many small
methods. It is the essential way that all code is structured.
Each of the user-defined method names, both in the call and the definition, is hilited.



One method is void, which means it doesn't return a value.
Three methods call other methods.
The main program consists mostly of calls to other methods.
Source code
1
//
//
//
//
File
:
Purpose:
Author :
Date
:
methods/KmToMilesMethods.java
Converts kilometers to miles using two methods.
Fred Swartz - placed in public domain
22 Apr 2006
2
import javax.swing.*;
3
4
public class KmToMilesMethods {
//=========================================================
constants
private static final double MILES_PER_KILOMETER = 0.621;
5
//==============================================================
main
6
7
public static void main(String[] args) {
double kms
= getDouble("Enter number of kilometers.");
double miles = convertKmToMi(kms);
displayString(kms + " kilometers is " + miles + " miles.");
}
8
9
//=====================================================
convertKmToMi
// Conversion method - kilometers to miles.
private static double convertKmToMi(double kilometers) {
double miles = kilometers * MILES_PER_KILOMETER;
10
return miles;
}
11
//=========================================================
getDouble
12
// I/O convenience method to read a double value.
private static double getDouble(String prompt) {
String tempStr;
13
tempStr = JOptionPane.showInputDialog(null, prompt);
return Double.parseDouble(tempStr);
14
}
//=====================================================
displayString
// I/O convenience method to display a string in dialog box.
private static void displayString(String output) {
16
JOptionPane.showMessageDialog(null, output);
}
17
}
15
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
Methods 6 - Overloading
Purpose of this lesson:

Explain overloading = multiple methods with the same name.
Programming ideas



The method name is important to the human programmer as the key to describing an
action to be performed.
It's often useful to do the "same" action, but with different kinds of parameters.
The compiler can distinguish methods that have the same name only if they have a
different number and / or type of parameters.
Here is a small program which simply computes the average of three numbers. It uses three
overloaded methods to read the numbers. For such a small program you would not use three
different methods, of course, but this shows how overloaded methods are defined and used. It's
very common for one overloaded method to call another. another variation of the program, this
time using three methods. Altho there is no real need for these methods in such a small program,
large programs are in fact composed of many small methods. It is the essential way that all code is
structured.
Each of the user-defined method names, both in the call and the definition, is hilited.



One method is void, which means it doesn't return a value.
Three methods call other methods.
The main program consists mostly of calls to other methods.
Good practices



Coherence. It's important that all the methods do the "same" thing, so that the program is
human comprehensible. All methods sharing the same name should return the same value,
have the same side effects, and all be either static or instance methods. The language
doesn't require this, but doing otherwise is asking for trouble.
Call each other. Because all overridden methods should be doing the same thing, it is very
common for there to be calls from one to another, supplying extra default parameter values
as required.
Default parameter values. Some programming languages allow you to specify default
values for parameters, and if a the parameter is not supplied, the default value is used.
Java doesn't have default parameters, but you can easily implement them using overloaded
methods.
Example of overloading - averaging three values
1
2
3
// File
: methods/avg3/AvgThreeOverloaded.java
// Description: Averages three numbers -- meaningless, but
// Purpose: Show an overloaded method, getDouble, with three
definitions,
//
differing in the number of parameters.
// Issues : Input isn't checked for legality (non-null number)
because
//
the point is to show overloading.
// Author : Fred Swartz - 2007-01-11 - placed in public domain
4
import javax.swing.*;
5
public class AvgThreeOverloaded {
6
//==============================================================
main
public static void main(String[] args) {
//... Read three numbers using the three different methods.
//
Using three different methods is only to show
8 overloading.
double n1
= getDouble();
double n2
= getDouble("Enter the second number.");
9
double n3
= getDouble("Enter last number.", 0.0, 100.0);
double average = (n1 + n2 + n3) / 3.0;
10
displayString("Average is " + average);
}
7
11
//=========================================================
getDouble
12
// I/O convenience method to read a double value.
//
This version of the getDouble method simply calls on
another
13
//
version passing it a generic input message.
private static double getDouble() {
14
return getDouble("Enter a number");
}
15
//=========================================================
getDouble
// I/O convenience method to read a double value given a prompt.
16
//
This version of getDouble displays the user supplied
prompt.
private static double getDouble(String prompt) {
17
String tempStr;
tempStr = JOptionPane.showInputDialog(null, prompt);
18
return Double.parseDouble(tempStr);
}
19
//=========================================================
getDouble
20
// I/O convenience method to read a double value in a range.
//
It builds a new prompt and calls another version to get
21
//
the value, looping until a value in the range is found.
private static double getDouble(String prompt, double low, double
high) {
22
double result;
String rangePrompt = prompt + " Value must be in range "
23
+ low + " to " + high;
24
//... Read and loop back if the number is not in the right
range.
do {
25
result = getDouble(rangePrompt);
} while (result < low || result > high);
26
return result;
}
27
//=====================================================
displayString
28
// I/O convenience method to display a string in dialog box.
private static void displayString(String output) {
29
JOptionPane.showMessageDialog(null, output);
}
}
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
Don't confuse overloading and overriding
This two terms are easily confused because they both have to do with multiple definitions of
methods. Better terms would have been nice, but these are what we have. Overloading is making
multiple method definitions which differ in the number or types of parameters, as described here.
Overriding is redefining a method in a super class, using exactly the same number and types of
parameters.
OOP 1. Introduction to Classes
and Objects
Purpose of this lesson:


Overview
o Classes combine data and methods.
o A class defines a data type.
o Advantage: Classes correspond to concepts in the problem domain.
o Advantage: Classes reduce complexity by increasing coherence and reducing
coupling.
Introduce classes to store data in value objects.
Terminology




Instance variable = Variable declared in class outside a method. Typically private.
Field = Synonym for instance variable, attribute. Common informal term.
Attribute = Synonym for instance variable, field. Often used in the design phase.
Property = Synonym for instance variable, field. Common term if field is known publicly.
New Java language features

Declaring fields (instance variables).
Object-Oriented Programming (OOP) concepts
Class = data + methods. Everything (data and methods) in Java is contained in classes. So far
you've been using classes to hold methods (main and perhaps a few other static methods). These
methods use local variables, which are completely private to the method, and which disappear when
the method returns.
Historical development. Classes can also be used to store data. Historically, programming
languages had something similar to classes for grouping data, usually called structs or records.
These were used for storing only data, not methods. Eventually, advantages of combining both data
and the methods to work on that data were recognized.
Classes model problem. One advantage of encapsulating data and methods in a class is to make
programming objects that reflect "objects" in the problem domain. If your problem deals with
orders and products, then you'll very likely have classes called Order and Product.
Classes reduce complexity. Another advantage of classes is reducing complexity. Complexity
limits the size and reliability of programs. Complexity is reduced by increasing cohesion (putting
things together that belong together) and reducing coupling (interconnections). The proper use of
classes can make large improvements in both of these.
Class, object, OOP. The name class was almost universally adopted for programming language
structure which combines data and methods, object is used for each instance of a class that is
created, and the practices that developed around these ideas is called Object-Oriented Programming
(OOP).
Value objects - Data-first approach. We'll start with classes that represent data, and then add
constructors and methods. Ultimately you will be more concerned with methods than data, and
you'll see how (and why) methods are used to completely hide the data implementation.
A class stores the attributes (data) of something
Group values. Classes are used to group a number of related, named, data values associated with
an entity. By entity we mean something that is typically a noun when you are talking about a
problem you are solving. For example, in a university computing system, you might have a class to
represent a student, an instructor, a classroom, a department, a course, a section of a course, ....
Student example. The information you would store about students, would be their name, id, etc.
We'll keep this example simple and just save name and id information.
Declare each field. A class contains declarations of the fields (instance variables, attributes) that
hold the data associated with a student. These declarations are like declaring a local variable in a
method, except that you will also specify the visibility. We'll start by using the visibility modifier
public, which lets anyone see them. For example, the following Student1 class can be used to
represent a student. As you go through these notes, we'll make improvements to this class.
public class Student1 {
public String firstName;
public String lastName;
public int
}
id;
A class is a type
Noun. Classes are usually given the name of a noun, and the fields (variables) in it are attributes
associated with that noun. Predefined Java classes that you have already used are String, which
contains the characters in the string and the length, JOptionPane, which contains information
necessary to produce a dialog box on the screen, etc. These predefined Java classes are used for
the programming infrastructure that you need. Many common infrastructure classes are available in
the 3000+ predefined Java library classes. But, of course, these don't address your problems.
Business objects. Most classes you define will concern your problem domain, where they
represent business objects (Student, TimeOfDay, Order, ...).
Declaring business object variables is like declaring any other variable. Use the class name as a
type, just as you've used String, int, etc. For example, the following declares two Student1
variables.
Student1 bestInClass;
// This variable references a Student1 object.
Student1 t;
// And here is another
These don't have values yet, but we'll do that in the next section.
Does your problem require classes or simple variables?
If the data you are working with, for example a temperature, can be expressed as a simple value
and the operations on it are all defined by operators, then just use a simple variable for it (int,
double, String, ...). Often the data associated with an entity in your problem is not a simple
value, but has multiple attributes.
Examples showing classes as groups of attriutes.



Instead of working with simple temperature numbers, you might have
TemperatureMeasurement objects, which have several attributes: the temperature, the
time, and the location.
A Student class would represent information about a student: name, id, address, ... Each
object of this class would have a data about a specific student.
A Classroom class would have information about a classroom's building, room number,
capacity, whether it has a projector, etc.
Object-Oriented Design involves deciding which classes you need to represent the things (entities)
in your problem. For simple programs, you often use only simple variables, but as programs get
larger, you will define more and classes to represent the things you are working with.
Similarity to database table
If your are familiar with databases, a class is very similar to a table definition. If you're not familiar
with databases, don't worry because these lessons don't assume you are.
OOP 2. Data - Student Class
Purpose of this lesson:

Classes versus objects.


How to create objects and assign values to the instance variables (fields).
Good practice: One class per file is the standard.
New Java language features


Using new to create an object.
Referencing fields using dot notation.
One class per file is standard practice
Here is the class again that represents information about a student. Typically there is one class
definition per file, so this would be stored in Student1.java.
// File
: oop/dataclass/Student1.java
// Purpose: Information about a student.
public class Student1 {
public String firstName; // First name
public String lastName;
// Last name
public int
// Student id
id;
}
Class versus object
A class is a template that defines what attributes an object can have. You make one class definition,
then create objects of that class using the new keyword. Some analogies might make this clearer.
Analogy: Cookie cutter and cookies. A cookie cutter is like a class definition. It isn't a cookie,
but can be used to create a cookie. Each cookie can will have the same attributes (shape), but each
cookie can have different values for the attributes (type of dough, thickness, ...).
Analogy: Dog and Fido. The concept of Dog is like a class, but there are many possible instances
of this class, eg, my dog Fido, or your dog Rover.
Analogy: Form stamp and filled out forms. There are rubber inkpad stamps that are used to
stamp out a small form. These have been used in several places in my passport, where passport
control stamped my passport, then filled out the fields with the date, how long I could stay, etc. The
rubber stamp is like a class, defining the fields. The filled out form in each passport are the objects,
with specific values for each field.
Use
new
to create a new object
A class defines what fields an object will have when it's created. When a new Student1 object is
created, a block of memory is allocated, which is big enough to hold these three fields -- as well as
some extra overhead that all objects have.
Student1 tatiana;
tatiana = new Student1();
// Create Student1 object with new.
"new" and parentheses
To create a new object, write new followed by the name of the class (eg, Student1), followed by
parentheses. Later we'll see that we can specify arguments in the parentheses when creating a new
objects.
Default field values - null, zero, false
Unlike local variables in a method, fields do have default values (like the default values in arrays).
Object references are null, numbers are zero, and booleans are false.
Access public fields with dot notation
The fields (firstName, lastName, id) name data which is stored in each object. Another term
for field is instance variable. All public fields can be referenced using dot notation (later we'll see
better ways to access and set fields). To reference a field, write the object name, then a dot, then
the field name.
Student1 tatiana;
Student1 object.
// Declare a variable to hold a
//... Create a new Student1 object for Tatiana.
tatiana = new Student1();
// Create a new Student1 object
with default values.
tatiana.firstName = "Tatiana";
// Set values of the fields.
tatiana.lastName = "Johnson";
tatiana.id
= 9950842;
JOptionPane.showMessageDialog(null, "One student is named: "
+ tatiana.lastName + ", " + tatiana.firstName);
Awkward? This simple example with one student is somewhat awkward, but we'll get to examples
that show real advantages soon.
A class definition is a template for creating objects
A class defines which fields an object has in it. You need to use new to create a new object from the
class by allocating memory and assigning a default value to each field. A little later you will learn
how to write a constructor to control the initialization.
It's not very interesting to create only one object of class, so the following example creates a couple
of them.
//
1
2
3
4
File
: oop/dataclass/TestStudent1.java
import javax.swing.*;
public class TestStudent1 {
public static void main(String[] args) {
Student1 tatiana;
Student1 pupil;
//... Create new Student1 object with new.
tatiana = new Student1();
tatiana.firstName = "Tatiana";
5
tatiana.lastName
tatiana.id
6
= "Johnson";
= 9950842;
//... Create another Student1 object.
pupil = new Student1();
pupil.firstName = JOptionPane.showInputDialog(null, "First
7
name");
8
9
pupil.lastName
pupil.id
=
Integer.parseInt(JOptionPane.showInputDialog(null, "ID"));
JOptionPane.showMessageDialog(null, "One student is named: "
+ tatiana.lastName + ", " + tatiana.firstName
+ "\n and another is named: "
+ pupil.lastName + ", " + pupil.firstName);
10
11
}
12
13
14
15
16
17
18
19
20
21
22
23
24
25
= JOptionPane.showInputDialog(null, "Last
name");
}
26
27
OOP 3. Constructor - Student
Class
Purpose of this lesson:


To introduce the concept of constructors.
Purpose of constructors is both guaranteed initialization and convenience.
New Java language features

Constructor syntax - like a method but with class name and implicit type/value.
Add a constructor for better initialization
Avoid bad initializations. One problem with the Student1 class is that the user has to explicitly
initialize all fields. This requires extra typing, but more importantly, it is error-prone. If we forget to
initialize a field, the default value could have bad consequences.
Convenience. Defining a constructor makes creation of an object easier to write.
Constructor Syntax
Similar to method. A constructor is similar to a method -- it's called like a method, has
parameters like a method, and it returns. But it must have the same name as the class for which it
is a constructor. Also, the type and return value are implicit.
Student2 example with a constructor
Here is the Student1 class with a constructor which simply initializes the fields (instance variables)
from its parameters. Often constructors do more work in initialization, including checking for legal
values, but for now we'll just simply copy the parameter values.
// File
: oop/dataclass/Student2.java
// Purpose: Information about a student. Defines constructor.
public class Student2 {
public String firstName; // First name
public String lastName;
// Last name
public int
// Student id
id;
//======================================== constructor
public Student2(String fn, String ln, int idnum) {
firstName = fn;
lastName
= ln;
id
= idnum;
}
}
Note that a constructor has no return type and the name is the same as the class name.
Using the constructor
Here is the first program rewritten to use the above class definition with a constructor.
1
// File
: oop/dataclass/TestStudent2.java
// Purpose: Tests Student2 constructor.
import javax.swing.*;
2
3
public class TestStudent2 {
public static void main(String[] args) {
Student2 tatiana;
Student2 pupil;
4
//... Create new Student2 object with new.
tatiana = new Student2("Tatiana", "Johnson", 9950842);
5
//... Create another Student2 object.
String first = JOptionPane.showInputDialog(null, "First
6
name");
7
8
String last
int
studID=
Integer.parseInt(JOptionPane.showInputDialog(null, "ID"));
pupil = new Student2(first, last, studID);
9
JOptionPane.showMessageDialog(null, "One student is named: "
+ tatiana.lastName + ", " + tatiana.firstName
+ "\n and another is named: "
+ pupil.lastName + ", " + pupil.firstName);
10
11
12
13
14
= JOptionPane.showInputDialog(null, "Last
name");
}
}
15
16
17
18
19
20
21
22
23
24
25
When you define a constructor, the Java compiler doesn't create a default constructor
if you define a constructor in a class, the Java compiler no longer automatically creates a default
(parameterless) constructor. All object creation therefore must use your explicitly defined
constructor. For example,
Student2 someone;
someone = new Student2();
constructor.
// ILLEGAL.
someone = new Student2("Michael", "Maus", 1);
values.
There is no default
// OK.
Must specify 3
The constructor can check that all fields are defined with legal values. We're not going to extend the
Student2 class any further to test for legal values, but we will in the next example.
For the moment we'll leave the Student class, and move to something different to show the same
ideas.
Class and Interface Concepts
Here are some of the basic building blocks of Objected-Oriented Programming that you will become
familiar with:
class
A collection of fields (instance and class variables) and methods.
instance variable (aka field variable or member variable
An instance variable is a variable that is defined in a class, but outside of a method. There
is one copy of the variable for every instance (object) created from that class.
A common problem is trying to reference an instance variable from a static method. A static
method (eg, main) can only reference static variables in its own class (or its own local
variables).
class variable (aka static variable)
A class variable or static variable is defined in a class, but there is only one copy regardless
of how many objects are created from that class. It's common to define static final
variables (constants) that can be used by all methods, or by other classes. Color.blue is
an example of a static final variable.
constructor
When an object is created, a constructor for that class is called. If no constructor is defined,
a default constructor is called. It's common to have multiple constructors taking different
numbers of parameters. Before a constructor is executed, the constructor for the parent
class is called implicitly if there is no parent constructor called explicitly on the first line.
inner class
If a class is defined within another class, it is an inner class. There are two common reasons
to do this: to attach an anonymous listener to a control at the point where the control is
being built, and to have access to the fields and methods of the enclosing class.
override (applies to methods)
If a subclass redefines a method defined in a superclass, the method in the superclass is
overridden. A common use of this is in defining a subclass of JPanel that you use for
graphics. When you define the paintComponent method, you are overriding the one that
is already defined in JPanel. In paintComponent, but not in most overriding methods, you
should call the method in the parent class with super.paintComponent. The "super"
keyword is how you refer to the overridden parent method. There is no way to explicitly call
the "grandparent's" method if it was overridden by the parent class.
overload (applies to methods)
A method in a class is overloaded if there is more than one method by the same name. If
the same name is used, the methods must different in the number and/or types of the
parameters so that there is no confusion. This really has nothing to do with classes, only
methods.
abstract class
A class which doesn't define all it's methods is called an abstract class. To be useful, there
must be a subclass which defines the missing methods. The "You must declare this class
abstract" error message from the Java compiler is rather misleading. This usually means
that you declared your class to implement an interface, but failed to write all required
methods -- or more commonly that there's a spelling error in a method header.
interface
An interface is a list of methods that must be implemented. A class that implements an
interface must define all those methods. The method signatures (prototypes) are listed in
the interface. Interfaces may also define public static final "constants". An interface is
essentially the same as an completely abstract class.
Other views on OOP

OOP Is Much Better in Theory Than in Practice at www.devx.com.

Don't Fear the Oop! - A light hearted, but incomplete intro to OOP. By the late Johannes
Claerbout.
Constructors
When you create a new instance (a new object) of a class using the new keyword, a constructor for
that class is called. Constructors are used to initialize the instance variables (fields) of an object.
Constructors are similar to methods, but with some important differences.

Constructor name is class name. A constructors must have the same name as the class
its in.

Default constructor. If you don't define a constructor for a class, a default parameterless
constructor is automatically created by the compiler. The default constructor calls the
default parent constructor (super()) and initializes all instance variables to default value
(zero for numeric types, null for object references, and false for booleans).

Default constructor is created only if there are no constructors. If you define any
constructor for your class, no default constructor is automatically created.

Differences between methods and constructors.
o
There is no return type given in a constructor signature (header). The value is this
object itself so there is no need to indicate a return value.
o
There is no return statement in the body of the constructor.
o
The first line of a constructor must either be a call on another constructor in the
same class (using this), or a call on the superclass constructor (using super). If
the first line is neither of these, the compiler automatically inserts a call to the
parameterless super class constructor.
These differences in syntax between a constructor and method are sometimes hard to see
when looking at the source. It would have been better to have had a keyword to clearly
mark constructors as some languages do.

this(...) - Calls another constructor in same class. Often a constructor with few
parameters will call a constructor with more parameters, giving default values for the
missing parameters. Use this to call other constructors in the same class.

super(...). Use super to call a constructor in a parent class. Calling the constructor for
the superclass must be the first statement in the body of a constructor. If you are satisfied
with the default constructor in the superclass, there is no need to make a call to it because
it will be supplied automatically.
Example of explicit this constructor call
public class Point {
int m_x;
int m_y;
//============ Constructor
public Point(int x, int y) {
m_x = x;
m_y = y;
}
//============ Parameterless default constructor
public Point() {
this(0, 0);
// Calls other constructor.
}
. . .
}
super(...) - The superclass (parent) constructor
An object has the fields of its own class plus all fields of its parent class, grandparent class, all the
way up to the root class Object. It's necessary to initialize all fields, therefore all constructors
must be called! The Java compiler automatically inserts the necessary constructor calls in the
process of constructor chaining, or you can do it explicitly.
The Java compiler inserts a call to the parent constructor (super) if you don't have a constructor
call as the first statement of you constructor. The following is the equivalent of the constuctor above.
//============ Constructor (same as in above example)
public Point(int x, int y) {
super();
// Automatically done if you don't call constructor
here.
m_x = x;
m_y = y;
}
Why you might want to call super explicitly
Normally, you won't need to call the constructor for your parent class because it's automatically
generated, but there are two cases where this is necessary.
1.
You want to call a parent constructor which has parameters (the automatically generated
super constructor call has no parameters).
2.
There is no parameterless parent constructor because only constructors with parameters
are defined in the parent class.
Constructor Puzzle
This class compiles without a problem
1
/////////////////// class WITHOUT a parameterless
constructor.//////////////////
class Parent {
2
int _x;
Parent(int x) {
_x = x;
}
3
4
// Constructor with a parameter.
}
5
6
7
8
9
But why won't this subclass compile?
1
////////////////// Why won't this class compile?
///////////////////////////////
class Child extends Parent {
int _y;
2
Child(int y) {
_y = y;
}
3
// This line mysteriously generates an error!
}
4
5
6
7
8
Hint
The error message from the compiler is:
Child.java:5: cannot find symbol symbol : constructor Parent()
But you defined a constructor for Parent, and anyway, you didn't even call the Parent constructor,
so what's the problem with line 5?
Constructor chaining - implicit or explicit constructor call as first statement
Before you can initialize an object in a constructor, the object's parent constructor must be called
first. If you don't write an explicit call to the super() constructor, Java automatically inserts one in
your constructor. The compiler automatically inserts superclass constructor calls in both
constructors.
Parent(int x) {
super();
// Compiler inserts this statement to call Object().
_x = x;
}
This is fine because there is a parameterless constructor for Object. However, when the Child
class constructor is modified to call its superclass constructor, there's a problem.
Child(int y) {
super();
// Compiler inserts this statement to call Parent().
_y = y;
}
No parameterless constructor
The problem is that the Parent class has no parameterless constructor. When any constructor is
explicitly defined (as in Parent above), the compiler no longer produces a default parameterless
constructor.
Possible solution 1 - Explicit constructor call
Usually the best solution is for the subclass constructor to explicitly call the superclass constructor
so that its fields are correctly initialized.
Child(int y) {
super(-666);
// Make explicit call to superclass constructor.
_y = y;
}
Possible solution 2 - Define a parameterless constructor
But no invalid values please. Advice you will sometimes see is to always define a parameterless
constructor, so that this problem doesn't occur. But an essential element of data encapsulation is
that the value of a object can be guaranteed to be a legal value. A constructor insures that the
initial value of an object is valid. Many objects can't be given a valid value with a default constructor.
This peculiar semantic-free example Parent class might be changed to have a parameterless
constructor as follows (supposing that a value of -666 makes sense for this class):
1
2
/////////////////// class with parameterless constructor.
//////////////////////
class Parent {
int _x;
Parent() {
// Parameterless constructor
this(-666);
3
// Call other constructor with default value.
}
4
Parent(int x) {
_x = x;
}
5
// Constructor with a parameter.
}
6
7
8
9
10
11
12
13
Example class where a default constructor would be a disaster
It's common to have a class with no legal default values. For example, what should the default
constructor do for this class?
1
2
3
4
5
6
7
8
// A parameterless constructor would be wrong here.
public class Student2 {
private String firstName; // First name
private String lastName; // Last name
private int
id;
// Student id
//======================================================
constructor
public Student2(String fn, String ln, int idnum) {
firstName = fn;
lastName = ln;
id
= idnum;
}
//======================================== parameterless
constructor
public Student2() {
????
// No possible legal values.
}
//==========================================================
setters
public void setID(int id) {
this.id = id;
10
}
9
11
. . .
}
12
13
14
15
16
17
18
19
20
21
22
23
24
25
If you defined a default constructor for Student2, what would you assign to the fields - null for
the names and zero for the id? Whatever you choose it's illegal. There are setters so you hope that
the user will set the fields to legal values. Or you will check for the illegal initial values and throw an
exception or give some other error when there is an attempt to use them. Perhaps there are times
when this is acceptible in a small one-person project, but it's a disaster waiting to happen in
anything larger.
Never define a parameterless constructor unless it can create a valid object.
Constructor Chaining Exercise 1
Name _______________________________
The first line of every constructor must be either

A this call to another constructor in the same class.

A super call to a parent constructor.
If no constructor call is written as the first line of a constructor, the compiler automatically inserts a
call to the parameterless superclass constructor.
Question
What is printed by this program?
// File
: ConstructorChain.java
// Purpose: Illustrate constructor chaining.
// Author : Fred Swartz
// Date
: 5 May 2003
class ConstructorChain {
public static void main(String[] args) {
Child c = new Child();
}
}
class Child extends Parent {
Child() {
System.out.println("Child() constructor");
}
}
class Parent extends Grandparent {
Parent() {
this(25);
System.out.println("Parent() constructor");
}
Parent(int x) {
System.out.println("Parent(" + x + ") constructor");
}
}
class Grandparent {
Grandparent() {
System.out.println("Grandparent() constructor");
}
}
You can check your answer with Constructor Chaining Answer.
Interfaces
An interface is a list of methods that must be defined by any class which implements that
interface. It may also define constants (public static final).
Similar to abstract class. An interface is similar to a class without instance and static variables
(static final constants are allowed), and without method bodies. This is essentially what a
completely abstract class does, but abstract classes do allow static method definitions, and
interfaces don't.
Contractual obligation. When a class specifies that it implements an interface, it must define all
methods of that interface. A class can implement many different interfaces. If a class doesn't define
all methods of the interfaces it agreed to define (by the implements clause), the compiler gives an
error message, which typically says something like "This class must be declared abstract". An
abstract class is one that doesn't implement all methods it said it would. The solution to this is
almost always to implement the missing methods of the interface. A misspelled method name or
incorrect parameter list is the usual cause, not that it should have been abstract!
A very common use of interfaces is for listeners. A listener is an object from a class that
implements the required methods for that interface. You can create anonymous inner listeners, or
implement the required interface in any class.
Interfaces are also used extensively in the data structures (Java Collections) package.
Classes versus Interfaces
Classes are used to represent something that has attributes (variables, fields) and
capabilities/responsibilities (methods, functions). Interfaces are only about capabilities. For
example, you are a human because you have the attributes of a human (class). You are a plumber
because you have the ability of a plumber (interface). You can also be an electrician (interface). You
can implement many interfaces, but be only one class.
This analogy fails in one way however. Capabilities (methods) of a class are unchanging (if a class
implements an interface, it is implemented for all instances), whereas the human skills we're talking
about are dynamic and can be learned or forgotten. The analogy is flawed, as all analogies are, but
it gives some idea of a distinction between classes and interfaces.
Interfaces replace multiple inheritance
Simpler. A C++ class can have more than one parent class. This is called multiple inheritance.
Managing instance variable definitions in multiple inheritance can be really messy, and leads to
more problems (eg, the "Deadly Diamond of Death") than solutions. For this reason Java designers
chose to allow only one parent class, but allow multiple interfaces. This provides most of the useful
functionality of multiple inheritance, but without the difficulties.
Implementing an Interface
You may implement as many interfaces in a class as you wish; just separate them with commas.
For example,
// Note:
//
ActionListener requires defining actionPerformed(...)
//
MouseMotionListener requires defining mouseMoved(...) and
mouseDragged(...).
public class MyPanel extends JPanel implements ActionListener,
MouseMotionListener {
public void actionPerformed(ActionEvent e) {
/* Method body */
}
public void mouseDragged(MouseEvent me) {
/* Method body */
}
public void mouseMoved(MouseEvent me) {
/* Method body */
}
// Everything else in this class.
}
It is common for a panel that does graphics and responds to the mouse to implement its own
mouse listeners (but not action listeners) as above.
Declaring an interface
For simple programs you are more likely to use an interface than define it. Here is what the
java.awt.event.ActionListener interface definition looks something like the following.
public interface ActionListener {
public void actionPerformed(ActionEvent e);
}
Tagging Interfaces
Java defines a few interfaces that are just used as a boolean property of a class, but don't actually
require the implemenation of any methods. These are called tagging interfaces.
Tagging interfaces are an abuse of the interface principle, but Java makes use of object-oriented
features to solve all problems if possible, rather than invent a more appropriate feature.
Common tagging interfaces that you might see are:
Cloneable
Implementing this interface indicates that the class has overridden Object's
clone() method. But there is no check that this is true, and because subclasses
inherit interfaces, it will look like all subclasses have defined clone() altho that
is not necessarily true. Yes, this is not the normal spelling of the English word. ???
Why needed.
Serializable This tagging interface indicates that a class can serialized - that an object of this
class can be written out and read back in using ???. This can be useful for shortterm storage of objects, but should not be used for long-term storage because
any change to the class definition makes that persistent copy unreadable!
Enums
Problem: How to represent a set of named constant values. First we'll look at the "old" Java
solution, then see how Java 5 enums substantially improve the situation.
Older, but common, solution
Just define a number of public static final int constants. For example:
//... Constants to represent possible shapes.
public static final int RECTANGLE = 0;
public static final int CIRCLE
= 1;
public static final int LINE
= 2;
...
int drawing = RECTANGLE;
// But any int could be assigned.
These values can then be assigned to an integer variable, and can be used in switch statements.
This style is useful, but is not a great solution.

Allows illegal values. Any variable containing one of these values could also be assigned
any integer value, although there are only three legal choices. Eg,
drawing = 99;

// Illogical value, but allowed by compiler.
Updates not reflected in other code. If there are additions, deletions, or reorderings,
code from other classes will not automatically be readjusted to reflect these changes. All
code that uses these definitions would have to be recompiled.

No easy I/O. To convert values to and from a string form requires maintaining an
additional array and lookup code.

Fragile for loops. There is no obvious first and last value so iterating over all values is
subject to errors which are not diagnosed at compile time if the values are rearranged,
deleted, or added to. There is no way to use the enhanced for loop.

No behavior. This style is pre-OOP -- there are values, but no behavior defined for them.
Defining an enum type
An enum type is a kind of class definition. The possible enum values are listed in the curly braces,
separated by commas. By convention the value names are in upper case.
public enum Shape { RECTANGLE, CIRCLE, LINE }
Declaring enum variables and using enum values
The enum class name can be use like any other class type in declarations. Usually enum values
must be prefixed with the enum type name.
Shape drawing = Shape.RECTANGLE;
assigned.
// Only a Shape value can be
Printing enum values
The enum class has a toString() method defined that returns the unqualified string version of
the value. This means that it's easy to print these values without any special conversion effort.
System.out.println(drawing);
// Prints RECTANGLE
Looping over all enum values with foreach loop
The static values() method of an enum type returns an array of the enum values. The foreach
loop is a good way to go over all of them.
//... Loop over all values.
for (Shape shp : Shape.values()) {
System.out.println(shp);
// Prints RECTANGLE, CIRCLE, ...
}
Switch statement
The switch statement was enhanced to allow a convenient use of enums. Note that the case
values don't have to be qualified with the enum class name, which can be determined from the
switch control value.
switch (drawing) {
case RECTANGLE: g.drawRect(x, y, width, height);
break;
case CIRCLE
: g.drawOval(x, y, width, height);
break;
case LINE
: g.drawLine(x, y, x + width, y + height);
break;
}
Getting an integer equivalent of an enum value
Each enum value in an enum class has an associated default value, starting with zero for the first
value and incrementing by one for each additional value. This may be accessed with the ordinal()
method.
System.out.println(drawing.ordinal());
// Prints 0 for RECTANGLE.
Input
The valueOf() method can be used to convert a string value to an enum value. Here is an
example of reading in a Shape value from a Scanner object in.
drawing = Shape.valueOf(in.next());
Defining additional fields, methods, and constants for your enum type
Methods can be defined for an enum class, including defining a different method body for each of
the constants. See the Sun article for examples of this. If you are using switch statements with
cases for each of the enum constants, consider putting the code into the enum class.
Related data structure classes: EnumSet and EnumMap
The java.util.EnumSet class provides an efficient implementation of sets of enums as bit maps, or
powersets as they were called in Pascal. EnumSet can also generate an Iterable for use with subsets
in the for-each statement.
java.util.EnumMap provides an efficient implementation of a map for enums based on an array.
Further reading

Enums is a good Sun overview of the Java enum features. It's very readable with good
examples.

Example: PaintDemo is a small paint program which represents the shape with an enum. It
shows how to use an enum to represent simple constants, and also how to associate a
method with each constant.

Class Enum<E extends Enum<E>> is the API documentation for the superclass of all
enums. You'll find useful methods in this class such as compareTo(...), ordinal(),
toString(), and valueOf(...). The addition of generics negated the former Java
claim to simplicity, and it's this Enum definition which is often used as an example of the
incomprehensible. It's hard to find anyone who understands this obscure declaration.
Fortunately, the use of enums doesn't require that that you know what this declaration
means.
Download