Joel Murach, Michael Urban - Murach's Beginning Java With NetBeans (Training & Reference) - 2015
Joel Murach, Michael Urban - Murach's Beginning Java With NetBeans (Training & Reference) - 2015
Michael Urban
TRAINING & REFERENCE
Joel Muraoh
Michael Urban
109 8765 43 2 1
ISBN: 978-1-890774-84-4
Content
Introduction xvii
Appendixes
Appendix A How to set up Windows for this book 607
Appendix B How to set up Mac OS X for this book 617
Expanded contents VII
Expanded contents
Section 1 Get started right
Chapter 1 An introduction to Java programming
An overview of Java 4
Java timeline 4
Java editions 4
How Java compares to C++ and C# 6
Types of Java applications 8
Two types of desktop applications 8
Two types of web applications 10
Mobile apps 12
An introduction to Java development 14
The code for a console application 14
How Java compiles and interprets code 16
Introduction to IDEs for Java development 18
An introduction to NetBeans 20
How to open a project 20
How to open a file in the code editor window 22
How to compile and run a project 24
How to use the Output window with a console application 24
How to work with two or more projects 26
How to close or delete a project 26
Companion books
When you finish this book, you’ll have all of the Java skills that you need
for web or mobile programming with Java. Then, if you want to move on to web
programming, Munich’ s Java Servlets and JSP will show you how to use Java
servlets and JavaServer Pages to develop professional web applications. Or, if
you want to move on to Android programming, Munich’s Android Programming
will get you started with that.
Another Murach book that you should be aware of is Munich’s Java
Programming. This book has been one of the best-selling Java books since its
first edition in 2001, but it isn’t a beginning book. As a result, it is organized
differently, moves faster, goes into greater depth, and presents some additional
subjects, particularly on GUI programming and handling data. In general,
though, you shouldn’t need this book if you have Munich’s Beginning Java.
XX Introduction
An overview of Java 4
Java timeline 4
Java editions 4
How Java compares to C++ and C# 6
Types of Java applications 8
Two types of desktop applications 8
Two types of web applications 10
Mobile apps 12
An introduction to Java development 14
The code for a console application 14
How Java compiles and interprets code 16
Introduction to IDEs for Java development 18
An introduction to NetBeans 20
How to open a project 20
How to open a file in the code editor window 22
How to compile and run a project 24
How to use the Output window with a console application 24
How to work with two or more projects 26
How to close or delete a project 26
Perspective 28
4 Section 1 Get started right
An overview of Java
In 1996, Sun Microsystems released a new programming language called
Java. Today, Java is owned by Oracle and is one of the most widely used
programming languages in the world.
Java timeline
Figure 1-1 starts by describing all major releases of Java starting with
version 1 .0 and ending with version 1 . 8. Throughout Java’s history, the terms
Java Development Kit (JDK) and Software Development Kit (SDK) have been
used to describe the Java toolkit. In this book, we’ll use the term JDK since it’s
the most current and commonly used term.
In addition, different numbering schemes have been used to indicate the
version of Java. For example, Java SE 8 or Java 1 .8 both refer to the eighth
major version of Java. Similarly, Java SE 7 and Java 1 .7 both refer to the seventh
major version of Java. The documentation for the Java API uses the 1 .x style
of numbering. As a result, you should be familiar with it. However, it’s also
common to only use a single number such as Java 6.
This book shows how to use Java 8. However, Java is backwards compatible,
so it should also work for future versions of Java. In addition, most of the skills
described in this book have been a part of Java since its earliest versions. As a
result, those skills should work with earlier versions of Java.
Java editions
This figure also describes the three most common editions of Java. To start,
there is the Standard Edition, which is known as Java SE. It’s designed for
general purpose use on desktop computers and servers, and it’s the edition that
you’ll learn how to work with in this book. For example, you can use Java SE to
create a desktop application like the one presented at the end of chapter 22.
The Enterprise Edition is known as Java EE. It’s designed to develop distrib¬
uted applications that run on an intranet or the Internet. You can use Java EE to
create web applications.
The Micro Edition is known as Java ME. It’s designed to run on devices that
have limited resources such as mobile devices, TV set-top boxes, printers, smart
cards, hotel room key cards, and so on.
With some older versions of Java, Java SE was known as J2SE (Java 2
Platform, Standard Edition). Similarly, Java EE was known as J2EE (Java 2
Platform, Enterprise Edition). If you are searching for information about Java on
the Internet, you may come across these terms. However, they aren’t commonly
used anymore.
Chapter 1 An introduction to Java programming 5
Java timeline
Year Month Event
1996 January JDK 1.0 released.
1997 February JDK 1.1 released.
1998 December SDK 1,2 released.
1999 August Java 2 Platform, Standard Edition (J2SE) released.
December Java 2 Platform, Enterprise Edition (J2EE) released.
2000 May J2SE with SDK 1.3.
2002 February J2SE with SDK 1.4.
2004 September J2SE 5.0 with JDK 1.5.
2006 December Java SE 6 with JDK 1.6.
2010 April Oracle buys Sun.
2011 July Java SE 7 with JDK 1.7.
2014 March Java SE 8 with JDK 1.8.
Java editions
Platform Description
Java SE (Standard Edition) For general purpose use on desktop computers
and servers. Some early versions were called
J2SE (Java 2 Platform, Standard Edition).
Java EE (Enterprise Edition) For developing distributed applications that
run on an intranet or the Internet. Some early
versions were called J2EE (Java 2 Platform,
Enterprise Edition),
Java ME (Micro Edition) For devices with limited resources such as
mobile devices, TV set-top boxes, printers,
and smart cards.
Description
• The Java Development Kit ( JDK) includes a compiler, a runtime environment, and
other tools that you can use to develop Java applications. Some early versions were
called the Software Development Kit (SDK).
Java compared to C#
Feature Description
Syntax Java syntax is similar to C# syntax.
Platforms Like Java, compiled C# code can run on any platform that has
a runtime environment for it.
Speed Java runs faster than C# in most contexts.
Memory Like Java, C# handles most memory operations automatically.
A console application
Command Prompt -java -jar FutureValueConsolejar
icrosoft Windows [Version 6.1.7601]
Copyright (c) 2009 Microsoft Corporation- All rights reserved
C:\Users\Joel>cd \murach\java_netbeansSf iles
C: \murach\jaua_netbeans\f iles >jaua -jar FutureUalueConsole . jar
We leone to the Future Value Calculator
Enter monthly investment: 100
Enter yearly interest rate: 3
Enter number of years: 3
Future value: $3,.771. 46
Continue? <y/n>:
A GUI application
Description
• A console application uses the console to interact with the user.
• A GUI application uses a graphical user interface to interact with the user.
An applet
i Applet Viewer; murach/ui/FutureValueA...
Applet
Calculate
Applet started.
v _ J
A servlet
■
CD localhost:8080/ch
_ J
Description
• An applet is a type of Java application that runs within a web browser.
• In the past, it was possible to run applets in most web browsers. Today, fewer and
fewer web browsers support applets. As a result, they are effectively obsolete.
• A servlet is a type of Java application that runs on a web server.
• A servlet accepts requests from clients and returns responses to them. Typically, the
clients are web browsers.
Mobile apps
You can also use Java to develop mobile apps, which are applications that
run on a mobile device such as a smartphone or tablet. In particular, Java is
commonly used to write the code for apps that run on Android devices. For
example, figure 1-5 shows a mobile app that was developed with Java. This app
performs the same task as the applications presented in the previous figures.
An app works much like a traditional application. However, the user inter¬
face has to be modified so that it’s appropriate for a mobile device. In this figure,
for example, the user interface has been modified to work with a touch-screen
device that has a small screen and no keyboard. As a result, the user can use the
keypad that’s displayed onscreen to enter numbers and can press the Done button
on this keypad to perform the calculation.
The Android operating system includes its own virtual machine that supports
a subset of Java, including most features of Java 6 and 7. As a result, if you use
Java to develop Android apps, you can’t use all of the features of Java, especially
the newest ones. That’s because the Android virtual machine is not a Java virtual
machine. In other words, the Android virtual machine can’t run compiled Java
code, and a Java virtual machine can’t run compiled Android code. Still, you can
use most features of Java to write code for Android apps, and it’s easy enough to
compile that code so the Android virtual machine can run it.
Chapter 1 An introduction to Java programming 13
A mobile app
* J rn 2:03
Future Value
Years 3
1 2 3 -
4 5 6 f
7 00 9 <a
■ 0 Done
a3 C=ji
Description
• A mobile app uses a mobile device such as a smartphone or tablet to interlace with
the user.
• The Android operating system supports a subset of Java, including most features of
Java 6 and 7.
Code editor
Description
• When you develop a Java application, you typically use a code editor to work with
the source code lor the application. Files that contain source code have the .java
extension.
• The Java compiler translates Java source code into a platform-independent
format known as Java bytecodes. Files that contain Java bytecodes have the .class
extension.
• A Java virtual machine {JVM) includes a Java interpreter that executes Java
bytecodes. Most modern implementations of the JVM have replaced the Java
interpreter with a just-in-time compiler ( JIT compiler). A JIT compiler is similar to
an interpreter in some ways, but it improves performance significantly.
• A Java runtime environment ( JRE ) has all of the components necessary to run
bytecodes including a JVM. Since JREs are available for most operating systems,
Java bytecodes can be run on most operating systems.
Description
• To develop Java applications, you typically use an Integrated Development
Environment (IDE) like those listed above. All of these IDEs are either free or have
free editions.
An introduction to NetBeans
In NetBeans, a project is a virtual folder that contains all the folders and files
for an application. The easiest way to get started with NetBeans is to open an
existing project. For example, you can open any of the applications for this book
after you download them from our website as described in the appendixes.
To clearly indicate when a folder contains a Java project, the Open Project dialog
box displays a small coffee cup icon to the left of the folder name. Then, you can
open the project by selecting it and clicking the Open Project button.
Chapter 1 An introduction to Java programming 21
Description
• A NetBeans project consists of a top-level folder that contains the subfolders and
files for a Java application.
• To open a project, click the Open Project button in the toolbar or select the
File->Open Project command. Then, use the Open Project dialog box that’s
displayed to locate and select the project and click the Open Project button.
• You can also open a project by using the File-ÿOpen Recent Project command and
then selecting the project from the list that’s displayed.
A project that uses the Output window for input and output
Q ch01_FutureValueCon&ole * NetBeans IDE S O LHI
File Edrt View Navigate Source Refactor Run Debug Profile Team Tools Window Help Q? i+r
Continue? (y/n):
& rmmmfeii & < m r
ch01_FutLreValueConsole (run) #2 \ running.., ij m (lmore...) (T)| | INS
l:1
k _ j
Mac OS X note
• To enable right-clicking, you can edit the system preferences for the mouse.
• To use the Windows keys shown in this book, you may need to hold down the
Command or Function (Fn) keys to modify those keys.
Description
• NetBeans lets you open and work with two or more projects at the same time.
• The Projects window displays all open projects.
Perspective
In this chapter, you learned some background information about Java. In
addition, you learned how to use NetBeans to open, compile, and run existing
projects. With that as background, you’re ready to start learning how to write
Java code and create new projects.
Summary
• You can use the Java Development Kit (JDK) to develop Java applications.
• The Standard Edition (SE) of Java is called Java SE.
• You can use Java SE to create desktop applications that run on your
computer.
• A desktop application can use a graphical user interface (GUI) or a console
to display output and get user input. Applications that use a console to
interact with the user are known as console applications.
• You can use the Enterprise Edition of Java, which is known as Java EE, to
create server-side applications using servlets and JavaServer Pages (JSPs).
• The Java compiler translates source code into a platform-independent format
known as Java bytecodes.
• A Java runtime environment ( JRE ) includes all of the software needed to run
bytecodes.
• A JRE includes an implementation of a Java virtual machine (JVM).
• A JVM includes a Java interpreter to translate the Java bytecodes into native
code that can be understood by the underlying operating system.
• Most modern JVMs have replaced the Java interpreter with a just-in-time
compiler (JIT compiler). A JIT compiler is similar to an interpreter in some
ways, but it improves performance significantly.
• An Integrated Development Environment (IDE) can make working with Java
easier by providing code completion, error detection, automatic compilation,
and a debugger.
• In NetBeans, a project is a folder that contains all of the files that make up
an application.
• If an application prints text to the console, NetBeans displays the text in the
Output window. NetBeans also allows you to enter input into the Output
window.
Chapter 1 An introduction to Java programming 29
Open and run the console version of the Future Value application
1. Start NetBeans. When the Start Page is displayed, review it. Then, close this
page.
2. Open the project named ch01_FutureValueConsole. This project should be
stored in this folder:
murach/ java_net beans/book_apps
-
> M end of main method
>
- end of class
Description
• A class stores Java code. Each class starts with a class declaration.
• A package is a folder that contains one or more classes. They are useful for
organizing multiple classes. Most classes start with a package statement that identi¬
fies the folder that contains the class.
• A method, is a block of code that performs a task. A class can contain one or more
methods.
• A class can contain one main method. This method is often the starting point for an
application. You can execute this method by running the class.
• Opening and closing braces identify the start and end of classes and methods. The
code within the braces can be referred to as a block of code.
• The public keyword is an access modifier that allows a class or method to be used
by other code.
• The file name for a class is the same as the class name with .java as the extension.
Description
• A statement performs a task and ends with a semicolon.
• You can start a statement at any point in a line and continue the statement from one
line to the next. To make your code easier to read, you should use indentation and
extra spaces to align statements and parts of statements.
• A comment typically documents what the code does. Well-written comments can be
helpful to the programmer who writes the code and to other programmers who need
to review or maintain the code later.
• To code a single-line comment, type // followed by the comment. You can code a
single-line comment on a line by itself or after a statement. A comment that’s coded
after a statement is sometimes called an end-of-line comment.
• To code a block comment, type /* at the start of the block and */ at the end. You can
also code asterisks to identify the lines in the block, but that isn’t necessary.
Description
• Although the appearance of a console may differ from one system to another, you
can always use the println and print methods of the System.out object to print data
to the console.
....... .. ..
Steps Choose Project
...
Java Free-Form Project
| EE
| Qi HTML5
i (J,. Maven
j--® PHP
| 5-, NetBeans Modules
Sampies
ipilation
Description
• To create a new project, use the File New Project command or click the New
Project button in the toolbar to display the New Project dialog box. Then, select a
project type, click the Next button, and respond to the dialog box that’s displayed.
• To create a Java Application project, enter the project name and location. Then,
enter the name you want to use for the main class. It’s generally considered a best
practice to supply a package name for this class.
File Edit View Navigate Source Refactor Run Debug Profile Team Tools Window Help <v ri+n
vH |r u
C—,' ■9 (r <default oonfig >
3
+}ÿ © Libraries
4
5
6
7 package murach , teat;
8
9
10
11 aDtnor
12
13 public class CodeTesterApp {
14
15 R
16 0P args
17 -
Navigator S* H
18 0 public static void mam (String[] args) {
Members < empty > LQj 19
B -|V, CodeTesterApp 20
(J) mainfStrmgC args) 21
22
23
Description
• To open a .java file in the code editor, double-click on it in the Projects window.
Then, you can use normal editing techniques to work with the source code.
• To collapse the code for a method or comment, click the minus sign (-) to its left.
Then, a plus sign (+) appears to the left of the method or comment, and you can
click the plus sign to display the code again.
• To save the source code for a file, use the File-ÿSave command (Ctrl+S) or click
the Save All Files button in the toolbar. This automatically compiles the file so it
doesn’t have to be compiled when the project is run.
• To rename a file, right-click on it, select the Refactor Rename command, and
enter the new name in the resulting dialog box.
• To delete a file, you can right-click on it, select the Delete command, and confirm
the deletion in the resulting dialog box.
Figure 2-5 How to work with Java source code and files
42 Section 1 Get started right
File Edit View Navigate Source Refactor Run Debug Profile Team Tools Window Help <v sear
10
11 anttiar Parameters :
12 x - The String to be printed.
13 public cla33 Cod<
14
IS 0
16 iparaiLi ar
17
18 public atatij
19 System . out . pr|
20 > print(Object obi) void
21 Q print ( String s) void
22 G print(boolean b) void
23 O print (char c) void
main - Navigator S3 El
Members
3 -IVJ CodeTesterApp
▼ <empty> WIH ■ _ print (chart! s)
G print ( double d)
void
void
. print ( float f) void
. . main (String!] args)
G print(int i)
Q print(long 1) void
voih
G printf ( String format. Object,,, args) PrintStream
G printf ( Locale 1, String format, Object... args) PrintStreair.
G println ( ) void
[ D if I irsifi561l © 1 51] iGi CodeTesterApp y (J) main _ println(Object x) void
• println(String st)
G pri ntln(boolean x) void
voidl INS
println(char x) void
G println(char [ 1 x) void
Description
• You can use the code completion feature to help you enter the names of classes
and objects and select from the methods and fields that are available for a class or
object.
• To activate the code completion feature for entering a class or object name, press
Ctrl+Spacebar alter entering one or more letters of the class or object name. Then,
a list of all the classes and objects that start with those letters is displayed.
• To activate the code completion feature for a method or field of a class or object,
enter a period after a class or object name. Then, a list of all the methods and fields
for that class or object is displayed.
• To insert an item from a code completion list, use the arrow keys to select the item and
press the Enter key. If the item requires parentheses, they’re added automatically. If
the item requires one or more arguments, default values are added for those arguments
and the first argument is highlighted so you can enter its value. Then, you can press
the Tab key and enter the values for any remaining arguments.
• If you enter the opening quote for a string of text, the code completion feature
automatically adds the closing quote and places the cursor between the two quotes
so you can enter the text.
Description
• NetBeans often detects syntax errors as you enter code into the code editor.
• When NetBeans detects a syntax error, it displays a red error icon to the left of the
statement in error and it places a red wavy line under the statement.
• To get more information about a syntax error, you can position the mouse pointer
over the error icon. Or, you can move the cursor to the line that contains the error
and press Alt+Enter.
Example
double productPrice; // declaration statement
productPrice =14-95; // assignment statement
Example
double productPrice =14.95; // initialize a double variable
Java keywords
boolean if interface class true
char else package volatile false
byte final switch while throws
float private case return native
void protected break throw implements
short public default try import
double static for catch synchroni zed
int new continue finally const
long this do transient goto
abstract super extends instanceof null
Description
• Java provides for eight primitive data types that you can use for storing values in
memory. The two most common are the int and double data types.
• A variable stores a value that can change as an application executes.
• To create a variable, you can start by declaring its data type and name. Then, you
can assign a value to the variable to initialize it. It’s common to initialize integer
variables to 0 and double variables to 0.0.
• A keyword, is a word that’s reserved by the Java language such as int and double. As
a result, you can’t use a keyword as the name for a variable.
Figure 2-8 Flow to declare and initialize variables
48 Section 1 Get started right
For some common variable names, programmers typically use just one or
two lowercase letters. For instance, they often use i as the name of an int variable
that’s used as a counter variable. This is acceptable in short blocks of code where
it’s easy to understand what the variable does.
When naming a variable, you can’t use a Java keyword as the name of the
variable. There are 50 keywords reserved by the Java language that are shown
in figure 2-8. To help you identify keywords in your code, most Java IDEs
display these keywords in a different color than the rest of the Java code. As you
progress through this book, you’ll learn how to use most of these keywords.
Description
• An assignment statement assigns a value to a variable that’s already declared This
value can be a literal value, another variable, or an expression like the arithmetic
expressions shown in the next figure.
• If you attempt to declare a variable a second time, it causes an error.
• Java is a case-sensitive language. As a result, make sure to use the correct case
when referring to the names of variables.
Description
• An arithmetic expression consists of one or more operands and arithmetic
operators.
• When an expression mixes the use of int and double variables, Java automatically
casts the int types to double types. To retain the decimal places, the variable that
receives the result must be a double.
• If you use multiple operators in one expression, you can use parentheses to specify
the sequence of operations. Then, Java performs the operations in the innermost set
of parentheses first, followed by the operations in the next set, and so on.
Examples
_
String messagel = "Invalid data entry.";
String message2 ii ii
i
»
/ / an empty string
String message3 = null; // a null string
Description
• A string can consist of one or more characters including letters, numbers, and
special characters like *, &, and #.
• In Java, a string is actually a String object that’s created from the String class that’s
part of the Java API ( Application Programming Interface). This API provides all
the classes that are included as part of the JDK.
• Since a string is an object created from the String class, you start the declaration
for a string by coding String with a capital S. By contrast, you don’t use any capital
letters when declaring primitive types such as the int and double types.
• To specify the value of a string, you can enclose text in double quotation marks.
This is known as a string literal.
• To assign a null to a string, you can use the null keyword. This means that the
String variable doesn’t point to a String object that’s allocated in memory.
• To assign an empty string to a String object, you can code a set of quotation
marks with nothing between them. This means that the string doesn’t contain any
characters.
• To join (or concatenate ) a string with another string or a data type, use a plus sign
(+). Whenever possible, Java automatically converts the data type and joins it with
the string.
Quotation marks
"Type \"x\" to exit"
Backslashes
"C i \\java\\files"
Description
• Within a string, you can use escape sequences to include certain types of special
characters such as new lines and tabs. You can also use escape sequences to include
characters that are part of the Java syntax such as quotation marks and backslashes.
Figure 2-12 Flow to include special characters in strings
56 Section 1 Get started right
The console
// perform a calculation
double total = price * quantity;
Perspective
The goal of this chapter is to get you started with Java programming. Now,
if you understand how the Code Tester application works, you can get some
hands-on experience coding variables and arithmetic expressions of your own.
However, this application doesn’t get input from the user or format the output
that’s displayed to the user. To do that, you can use some of the classes that are
available from the Java API as described in the next chapter.
Also, keep in mind that this chapter is just an introduction to Java program¬
ming. In chapter 7, you’ll learn more about working with primitive data types,
including how to work with the other six primitive data types. And in chapter 9,
you’ll learn more about working with strings.
Summary
• A class stores Java code. A package is a folder that can store one or more
Java classes. Packages are used to organize classes.
• A class can contain one or more methods. A method is a block of code that
performs a task,
• A main method is a special type of method that’s executed when you run the
class that contains it.
• A statement performs a task and ends with a semicolon.
• Comments typically document what code does.
• You can use the NetBeans code editor to enter and edit code. As you enter
code, you can use the code completion feature to help you enter the names of
classes and objects and select from fields and methods.
• Java provides for eight primitive data types. Two of the most common are
the int and double types.
• Variables store data that changes as an application runs. An assignment
statement can assign a value to a variable.
• A string can consist of one or more characters including letters, numbers,
and special characters. You can use the plus sign to join a string with another
string or primitive type.
• You can use escape sequences to include special characters in strings.
Chapter 2 How to start writing Java code 59
Sum: 301.75
Count: 6
Average: 50.291666666666664
Common packages
Package name Description
java.lang Classes that are fundamental to the Java language, including classes
that work with primitive data types and strings,
java.ut i 1 Utility classes, including those for getting input from the console.
java.t ext Classes that handle text, including those that format numbers and dates.
Common classes
- -
java lang String
- -
java lang Integer
java.lang.Double
-
java -util Scanner
- -
j ava 1 ext NumberFormat
Example
Scanner sc = new Scanner(System.in); // creates a Scanner object named sc
Example
String line = sc.nextLine( ); // get a String object from the console
Example
double price = Double.parseDouble(line); // convert a String to a double
Description
• When you create an object from a Java class, you are creating an instance of the
class. Then, you can use the methods of the class by calling them from the object.
• Some Java classes contain static methods. You can call these methods directly from
the class without creating an object.
• When you create an object from a class, the constructor may require one or more
arguments. These arguments must have the required data types. If there are multiple
arguments, you must code them in the correct sequence, and you must separate each
argument with a comma.
• When you call a method from an object or a class, the method may require one or
more arguments. Here again, these arguments must have the required data types. If
there are multiple arguments, you must code them in the correct sequence, and you
must separate each argument with a comma.
• When you call a method from an object or a class, the method may return a primitive
value or an object. If you want to use this data, you can assign the primitive value or
object to a variable.
Here, the argument is the String variable named line created in the second
example. This method returns a double value, and this example assigns it to the
double variable named price.
As you read this book, you’ll learn how to use dozens of classes and
methods. For now, though, you just need to focus on the syntax for creating an
object from a class, for calling a method from an object, and for calling a static
method from a class.
Description
• The Java SE API contains thousands of classes and methods that can help you do
most of the tasks that your applications require.
• You can use a browser to view the Java SE API on the Internet by going to this
address:
http://docs.oracle.com/ javase/ 8/docs/api
• You can select the name of the package in the top left frame to display information
about the package and the classes it contains. Then, you can select a class in the
lower left frame to display the documentation for that class in the right frame.
• Once you display the documentation for a class, you can scroll through it or click a
link to get more information.
Figure 3-3 How to use the API documentation to research Java classes
68 Section 1 Get started right
Description
• To create a Scanner object that gets input from the console, specify System.in in the
parentheses.
• When the nextLine method of the Scanner class runs, the application waits for the
user to enter text with the keyboard. To complete the entry, the user presses the
Enter key.
• Since the Scanner class is not in the java.lang package, you typically include an
import statement whenever you use this class.
Description
• The Integer and Double classes provide static methods that you can use for
converting values from a String object to an int or double value.
• If the parselnt and parseDouble methods can’t successfully parse the string, they
will cause an error to occur. In Java terminology, this is known as throwing an
exception. Later in this book, you’ll learn how to handle exceptions by catching
them.
-
import java.util Scanner; // import the Scanner class
How to get a double value from the user with two statements
String priceLine = sc.nextLine();
double price = Double.parseDouble(priceLine );
How to get a double value from the user with one statement
double price = Double.parseDouble(sc.nextLine());
Description
• When you use the format method, the result is automatically rounded by using
a rounding technique called half-even. This means that the number is rounded
up if the preceding digit is odd, but the extra decimal places are truncated if the
preceding digit is even.
• Since the NumberFormat class is in the java.text package, you typically include an
import statement when you use this class.
The examples in figure 3-7 use the default currency, percent, and number
formats for the United States. If you want to use the default format for the
current locale, you can modify the method that gets the NumberFormat object by
passing it this argument:
Locale.getDef ault ( )
For example, you can call the getCurrencylnstance method like this:
NumberFormat - getCurrencylnstance(Locale.getDef ault ( ));
Then, the NumberFormat object that’s created uses the currency format for the
current locale. For example, if you’re in Europe, it uses the symbol for the Euro
instead of the symbol for the U.S. dollar.
// perform a calculation
double total = price * quantity;
The console
Description
• Although the appearance of a console may differ from one system to another, you
can always use the print and println methods to print data to the console.
Relational operators
Operator Name Description
== Equality Returns a true value if both operands are equal,
1
* = Inequality Returns a true value if left and right operands are not equal.
> Greater Than Returns a true value if left operand is greater than right
operand.
< Less Than Returns a true value if left operand is less than the right
operand.
>= Greater Than Or Equal Returns a true value if left operand is greater than or equal
to right operand,
<= Less Than Or Equal Returns a true value if left operand is less than or equal to
right operand.
Description
• A Boolean expression is an expression that evaluates to either true or false.
• You can use the relational operators to compare two numeric operands and return a
Boolean value that is either true or false.
• To test two strings for equality, you must call one of the methods of the String
class. The equality operator (==) does not test two strings for equality.
// get input from the user, process it, and display output here
The console
Description
• A while loop executes the block of statements within its braces as long as the
Boolean expression is true. When the expression becomes false, the while loop
skips its block of statements so execution continues with the next statement in
sequence.
• Any variables that are declared in the block of statements for a while loop have
block scope. As a result, you can only access them within that block.
• If the Boolean expression in a while loop never becomes false, the loop never ends.
Then, the application goes into an infinite loop. In NetBeans, you can cancel an
infinite loop by clicking on the Stop button in the Output window.
Description
• An if/else statement, or just if statement, always contains an if clause. In addition, it
can contain one or more else if clauses, and a final else clause.
• Any variables that are declared within a block for an if/else clause have block
scope. As a result, they can only be accessed within that block.
• If a clause requires just one statement, you don’t have to enclose the statement in
braces. However, it’s generally considered a good practice to always include braces.
That way, if you decide to add more statements to a clause later, you won’t acciden¬
tally introduce a bug.
Description
• When the application starts, the user can enter a product code that identifies a
product and the quantity for that product. The application determines the product
price based on the product code. Then, it calculates the total amount for the line
item and displays the line item.
• After calculating the total for the invoice, the user can enter “y” or “Y” at the
prompt to continue. Or, the user can enter “n” or any other character to end the
application.
The code
Figure 3-13 shows the code for the Line Item application. Although this
application is simple, it gets input from the user, performs a calculation that uses
this input, and displays the result of the calculation.
This code begins with a package statement that declares that it is stored in
the murach.lineitem package. As a result, this code is stored in the
murach/lineitem subfolder of the application folder.
The two import statements import the NumberFormat and Scanner classes.
As a result, the rest of this code can use these classes without having to prefix
the class name with the package name.
The class declaration specifies a name of LineltemApp. As a result, this code
is stored in a file named LineltemApp.java.
The main method is coded within the braces of the LineltemApp class. This
method is executed when you run the LineltemApp class.
The main method begins by printing a welcome message to the console.
Then, it creates a Scanner object named sc. Although this object could be created
within the while loop, that would mean that the object would be recreated each
time through the loop, which would be inefficient.
Before the while loop, the code declares a String variable named choice and
initializes it to “y”. Then, the loop checks whether the choice variable is equal
to “y”. If so, it starts by getting the product code from the user and storing it
in a String variable named productCode. Then, it gets a quantity from the user,
converts it from a String object to an int value, and stores it in a variable named
quantity.
After getting this data, an if/else statement sets the double variable named
price based on the value of product code. If, for example, the productCode is
equal to “java”, the price is set to 57.50.
When the if/else statement is finished, this code calculates the line item total
by multiplying the price and quantity. Then, it stores the result of that calculation
in a double variable named total.
After this calculation, this code uses the NumberFormat class to apply
currency formatting to the price and total variables. In addition, it creates a
String variable named message that contains string literals, variables, and escape
sequences for new line characters. Then, it prints that string to the console.
After printing this data to the console, this code displays a message that asks
the user if he or she wants to continue. If the user enters “y” or “Y”, the loop is
repeated. Otherwise, the application ends.
If you’re new to programming, you can learn a lot by writing simple
applications like the Line Item application. This gives you a chance to become
comfortable with getting input, performing calculations, and displaying output.
In addition, it gives you a chance to get comfortable with control statements such
as while loops and if/else statements.
Chapter 3 How to use classes and methods 87
// calculate total
double total = price * quantity;
System.out .println(message );
Continue? (y/n): y
Continue? (y/n): n
Bye!
Description
• When the application starts, the user can enter a monthly investment, yearly interest
rate, and number of years. Then, it calculates the future value of the investment at
the end of the specified number of years and displays that value to the user.
• After calculating the future value, the user can enter “y” or “Y” at the prompt to
continue. Or, the user can enter “n” or any other character to end the application.
Figure 3-14 The user interface for the Future Value application
90 Section 1 Get started right
The code
Figure 3-15 shows the code for this application. This code uses a while loop
to determine when the application ends. Within this loop, the code gets the three
entries from the user. Then, it converts these entries to the same time unit, which
is months. To do that, it multiplies the number of years by 12 and divides the
yearly interest rate by 12. In addition, it divides the yearly interest rate by 100 so
it calculates the interest correctly.
Once those variables are prepared, a second while loop calculates the future
value. This loop executes one time for each month. Within this loop, the first
statement adds the monthly investment to the future value. The second statement
calculates the amount of monthly interest. The third statement adds the monthly
interest to the future value. And the fourth statement increments the counter
variable.
When this loop finishes, the code displays the result. To do that, it uses the
NumberFormat class to apply currency formatting to the future value. Then, it
asks whether the user wants to continue.
Chapter 3 How to use classes and methods 91
Perspective
The goal of this chapter has been to show you how to create a console
application that uses classes and methods from the Java API to get input from
the user and display output to the user. Now, if you understand how the Line
Item and Future Value applications work, you’ve come a long way. However,
these applications don’t use objects in a professional way. That’s why the next
two chapters show you how to convert the Line Item application into an
object-oriented application that uses objects in a professional way.
Also, keep in mind that this chapter is just an introduction to Java program¬
ming. As a result, you’ll learn more details about writing Java code as you
progress through this book. For example, you’ll learn more about coding
control statements in chapter 8.
Summary
• You call a method from an object and you call a static method from a class.
A method may require one or more arguments.
• Before you use a class from the Java SE API that isn’t in the java.lang
package, you typically code an import statement for the class.
• When you use a constructor to create an object from a Java class, you are
creating an instance of the class.
• You can use the static methods of the Integer and Double classes to convert
strings to int and double values.
• You can use the NumberFormat class to apply standard currency, percent,
and number formats to any of the primitive numeric types.
• You can code a while loop that executes a block of statements repeatedly
when its Boolean expression returns a true value and skips that block of
statements when its Boolean expression returns a false value.
• You can code an if statement to control the logic of an application based on
the true or false values of Boolean expressions.
Chapter 3 How to use classes and methods 93
2. Open the file named LineltemApp.java. Then, review the code for this file.
3. Run this application and test it with valid product codes like “java” and valid
quantities like 2, 1 0, and 1 000 that make it easy to see whether or not the
calculations are correct.
4. Run the application again and test it with an invalid quantity value like “two”.
This should cause the application to crash. Study the error message and
determine which line of source code was running when the error occurred.
5. Run the application again and enter “x” when the application asks you
whether you want to continue. What happens and why?
Modify the application
6. Modify the if/else statement so it sets a description for the product. Then,
modify the code that displays the data for the line item so it includes the
description. When you’re done, the application should look like this:
An introduction to classes 96
How encapsulation works 96
The relationship between a class and its objects 98
How to work with a class that defines an object 100
How to use NetBeans to create a new class 100
The Product class 102
How to code instance variables 104
How to code constructors 106
How to code methods 108
How to create an object from a class 110
How to call the methods of an object 112
How to work with static fields and methods 114
The ProductDB class 114
How to code and call static fields and methods 116
When to use static fields and methods 116
The Product Viewer application 118
The user interface 118
The Product App class 118
More skills for working with classes and methods 120
Reference types compared to primitive types 120
How to overload methods 122
How to use the this keyword 124
The Product class with overloading 126
Perspective 128
96 Section 1 Get started right
An introduction to classes _
The first two figures in this chapter introduce you to some concepts that
apply to classes. That includes how encapsulation works and how a class relates
to its objects.
+setCode( String)
+getCode(): String
+ set Descript ion(String)
+ getDescription(): String Methods
+setPrice(double)
+ getPrice(): double
+ getPriceFormatted(): String
Description
• The fields of a class store the data of a class.
• The methods of a class define the tasks that a class can perform. Often, these
methods provide a way to work with the fields of a class.
• Encapsulation is one of the fundamental concepts of object-oriented programming.
This means that the class controls which of its fields and methods can be accessed
by other classes. As a result, the fields in the class can be hidden from other classes,
and the methods in a class can be modified or improved without changing the way
that other classes use them.
productl
-code = ’'java"
-description = "Murach'is Java Programming1'
-price = 57,50
JPJ ■■ vW
prodMb
uctÿ1
mm A
-code = "mysql"
-description = "Murach's MySQL"
-price = 54,50
Description
• A class can be thought of as a template from which objects are made.
• Once an instance of a class is created, it has an identity (a unique address) and a
state (the data that it stores). As an application runs, an object’s state may change.
Description
• To create a new class, right-click on the package where you want to add the class,
select the New Java Class command, and respond to the resulting dialog box. At
the least, you should enter a name for the class in the Class Name text box.
• Although this dialog box encourages you to select a package for the class, this isn’t
required. If you don’t select a package for the class, NetBeans stores the class in the
default package.
• When you store a class in a package, the first statement of the class must be a
package statement that specifies the name of the package.
• If you specify a package when you add a new class and that package doesn’t
already exist, NetBeans automatically creates it for you.
• If you add a new class to a package, NetBeans automatically adds the necessary
package statement to the class.
// the constructor
public Product ( ) {
code = nn;
description =
price = 0;
}
Examples
private double price;
private int quantity;
private String code;
private Product product;
Description
• A field of a class defines the data that’s available to the entire class. A field can be
an instance variable or a constant. To learn how to work with constants, see
chapter 7.
• An instance variable stores data that’s available to the entire object. In other words,
an instance variable stores data that’s available to an instance of a class.
• An instance variable may be a primitive data type, an object created from a Java
class such as the String class, or an object created from a user-defined class such as
the Product class.
• Typically, instance variables are declared with the private keyword. This helps to
prevent other classes from directly accessing instance variables.
• You can declare the instance variables for a class anywhere outside the constructors
and methods of the class.
Description
• A constructor can be used to create, or construct, an object from a class.
• The constructor must use the same name and capitalization as the name of the class.
• To code a constructor that has parameters, code a data type and name for each
parameter within the parentheses that follow the class name.
• The name of a constructor combined with the parameter list forms the signature
of the constructor. Although you can code multiple constructors for a class, each
constructor must have a unique signature. This is known as overloading a constructor.
• You can use the keyword named this to refer to an instance variable of the current
object. This is required if an instance variable has the same name as a parameter of
the constructor. Otherwise, it’s optional.
• If you don’t explicitly initialize an instance variable, Java automatically initial¬
izes it for you by setting numeric variables to zero, boolean variables to false, and
variables for objects to null.
A set method
public void setCode( String code) {
this.code = code;
}
Description
• To allow other classes to access a method, use the public keyword. To prevent other
classes from accessing a method, use the private keyword.
• When you name a method, you should start each name with a verb. It’s a Java
standard to use the verb set for methods that set the values of instance variables and
to use the verb get for methods that return the values of instance variables. These
methods are typically referred to as set and get accessors.
• To code a method that doesn’t return data, use the void keyword for the return type.
• To code a method that returns data, code a return type in the method declaration.
Then, code a return statement in the body of the method to return the data.
• To code a method that has a parameter, code the data type and name of the param¬
eter between the parentheses of the method.
No arguments
Product product;
product = new Product ( );
No arguments
Product product = new Product ( );
Three arguments
Product product = new Product ( "java", "Murach's Java Programming", 57-50)
Description
• To create an object, you use the new keyword to create a new instance of a class.
Each time the new keyword creates an object, Java calls the constructor for the
object, which initializes the instance variables lor the object and stores the object in
memory.
• After you create an object, you assign it to a variable. When you do, a reference
to the object is stored in the variable. Then, you can use the variable to refer to the
object. As a result, objects are known as reference types.
• The variable for a reference type stores a reference to an object.
• To send arguments to the constructor, code the arguments between the paren¬
theses that follow the class name. To send more than one argument, separate the
arguments with commas.
• When you send arguments to the constructor, the arguments must be in the
sequence called for by the constructor and they must have data types that are
compatible with the data types of the parameters for the constructor.
Description
• To call a method that doesn’t accept arguments, type an empty set of parentheses
after the method name.
• To call a method that accepts arguments, enter the arguments between the paren¬
theses that follow the method name. Here, the data type of each argument must be
compatible with the data type that’s specified by the method’s parameters.
• To code more than one argument, separate the arguments with commas.
• If a method returns data, you can code an assignment statement to assign the data
that’s returned to a variable. Here, the data type of the variable must be compatible
with the return type of the method.
Description
• You can use the static keyword to identify a method as a static method.
• A more realistic ProductDB class would get the data for the Product object from a
database.
import java.util.Scanner;
Description
• You can use the static keyword to code static methods and static fields. Since static
methods and static fields belong to the class, not to an object created from the class,
they are sometimes called class methods and class fields.
• There are two types of fields: variables and constants. To learn how to code
constants, see chapter 7.
• When you code a static method, you can only use static fields and fields that are
defined in the method. In other words, you can’t use instance variables in a static
method.
• To call a static method, type the name of the class, followed by the dot operator,
followed by the name of the static method, followed by a set of parentheses. If the
method requires arguments, code the arguments within the parentheses, separating
multiple arguments with commas.
• To call a static field, type the name of the class, followed by the dot operator,
followed by the name of the static field.
Figure 4-11 How to code and call static methods and fields
118 Section 1 Get started right
The console
import java.util.Scanner;
Description
• A variable for a primitive type always stores its own copy of the primitive value. As
a result, changing the value for one primitive type variable doesn’t change the value
of any other primitive type variables.
• A variable for a reference type stores a reference to the object. This allows multiple
reference type variables to refer to the same object. As a result, changing the data
for one object also changes the data for any other variables that refer to that object.
• When you code a method that has a primitive type parameter, the parameter gets its
own copy of the value that’s passed to the method. As a result, if the method changes
the value of the parameter, that change doesn’t affect any variables outside the method.
• When you code a method that has a reference type parameter, the parameter
refers to the object that’s passed to the method. As a result, if the method uses the
parameter to change the data in the object, these changes are reflected by any other
variables outside the method that refer to the same object.
The console
Description
• When you create two or more methods with the same name but with different
parameter lists, the methods are overloaded. It’s common to use overloaded methods
to provide two or more versions of a method that work with different data types or
that supply default values for omitted parameters.
• The name of the method combined with the parameter list forms the signature of the
method. Although you can use the same name for multiple methods, each method
must have a unique signature.
• Within a class, you can call one regular method from another regular method by
coding the method name and its arguments. In other words, you don’t need to prefix
the method name with the object name.
Description
• Java implicitly uses the this keyword for instance variables and methods. As a
result, you don’t need to explicitly code it unless a method parameter or a variable
that’s declared within a method has the same name as an instance variable. Then,
you need to use the this keyword to identify the instance variable.
• If you use the this keyword to call one constructor from another constructor in the
same class, the statement that uses the this keyword must be the first statement in
the constructor.
public Product ( ) {
this("", nn, 0);
}
// all get and set methods are the same as the Product class
// shown earlier in this chapter
Perspective
At this point, you may be wondering why you should take the time to
create an object-oriented application like the one shown in this chapter. After
all, you could accomplish the same task with less code by coding a procedural
application like the one shown in chapter 3.
Although there are many advantages to the object-oriented approach, I’ll
just mention two for now. First, dividing the code into classes makes it easier
to reuse code. For example, any application that needs to work with products
can use the Product and ProductDB classes. Second, using classes helps you
separate the different layers of an application. That can simplify the devel¬
opment of the application and make the application easier to maintain and
enhance later on. In the next chapter, you’ll learn how to use classes to struc¬
ture an application so it has three layers.
Summary
• The Unified Modeling Language (UML) is the standard modeling language
for working with object-oriented languages. You can use UML class
diagrams to identify the fields and methods of a class.
• Encapsulation lets you control the fields and methods within a class that are
exposed to other classes. When fields are encapsulated within a class, it’s
called data hiding.
• Multiple objects can be created from a single class. Each object can be
referred to as an instance of the class.
• The data that makes up an object can be referred to as its state. Each object
is a separate entity with its own state.
• Afield is a variable or constant that’s defined at the class level. An instance
variable stores data that’s available to an object (instance) of a class.
• You can use a constructor to create, or construct, an object from a class.
• When you code the methods of a class, you often code public get and set
methods, called accessors, that provide access to its instance variables.
• If you want to code a method or constructor that accepts arguments, you
code a list of parameters between the parentheses for the constructor or
method. For each parameter, you must include a data type and a name.
• You can use the static keyword to define static fields and static methods.
Then, you can call those fields and methods directly from the class, not from
an object created from the class.
• The name of a method combined with the list of parameter types is known as
the signature of the method. You can overload a method by coding different
parameter lists for methods that have the same name.
• When coding a class, you can use the this keyword to refer to the current
object.
Chapter 4 How to code your own classes and methods 1 29
Presentation
classes
Business tier
Business
Database tier
Description
• To simplify development and maintenance, many applications use a three-tier
architecture to separate the application’s user interface, business rules, and database
processing. Each tier of the architecture may consist of one or more classes.
• The classes in the presentation tier control the application’s user interface. For
a console application, the presentation tier typically consists of a class with a
main method and any other classes related to console input and output. For a GUI
application, the user interface typically consists of one class for each window of the
GUI.
• The classes in the database tier handle all of the application’s data processing.
• The classes in the business tier define the business objects and rules for the applica¬
tion. These classes act as an interface between the classes in the presentation and
database tiers.
ui
-
ProductBB java
LineltemApp.java
import murach.business.Product;
import java.util.Scanner;
import murach.db.ProductDB;
import murach.business.Lineltem;
import murach.business.Product;
Description
• A package can store one or more classes.
• Each package name corresponds with a folder that has the same name. The names
you use should be unique to prevent conflicts with other packages.
• When you store a class in a package, the first statement of the class must be a
package statement that specifies the name of the package.
• After the package statement, you can code the import statements for the class.
These statements work the same for the packages and classes that you create as
they do for the packages and classes of the Java API,
Description
• To navigate through existing packages, use the Projects window to expand or
collapse the packages within a project.
• To add a new package to a project, right-click on the project name or the Source
Packages folder in the Projects window, select the New Java Package command,
and enter the name of the package in the resulting dialog box.
• To rename a package, select the RefactorÿRename command and use the resulting
dialog box to specify the new name.
• To move a class from one package to another, drag it in the Projects window. Then,
click the Refactor button in the resulting dialog box.
• To delete a package from a project, right-click on the package and select the Delete
command from the resulting menu. If the package contains classes, this also deletes
those classes.
• When you use NetBeans to work with packages, it automatically updates the
corresponding folders. In addition, it automatically updates any package or import
statements in the project that need it.
public Lineltem() {
this.product = null;
this.quantity = 0;
}
import java.util.Scanner;
import murach.db.ProductDB;
import murach.business.Lineltem;
import murach.business.Product;
Perspective
If you understand the Line Item application presented in this chapter, you
understand a lot about Java programming, including how to use packages and
classes to create a three-tier structure. With that as background, you’re ready to
learn more details about using Java. And that’s what you’ll learn in the rest of
this book.
But first, the next chapter shows how to test and debug the Line Item
application presented in this chapter. That way, whenever your code doesn’t
work correctly, you’ll have some skills that you can use to fix it.
Summary
• A three-tier architecture separates an application into three layers, or tiers.
• The presentation tier consists of the user interface.
• The database tier consists of the database and the database classes that work
with it.
• The business tier consists of the business classes that define the business
objects and rules of the application.
LINE ITEM
Code: java
Description: Murach 1 s Java Programming
Price: $57-50
Quantity: 2
Total: $59.50
Continue? (y/n):
Description
• To test a Java application, you run it to make sure that it works properly no matter
what combinations of valid or invalid data you enter.
• When you debug an application, you find the cause of all the errors {bugs) that
you find when you test the application. Then, you fix those errors. This process is
known as debugging.
A compile-time error
Output - chOS Lineltem (run) S8
A.
—
3 --
s E a ■ ra — — x
_ * J x E
Q
H> Compiling 1 source file to C:\murach\java_netbearL3\book_apps\ch05_LineItem\build\cla3ses >
A runtime error
Output - ch05_Lineltem (run)
A logic error
Output - chQ5_Uneltem (run) sa B
H> Welcome to the Line Item Calculator >
LIKE ITEM
Code: j ava
Description: Hurach's Java Programming
Price: 157,50
m.
Quantity: d
Total: $59.50
Continue? (y/n): *
Description
• The first step in fixing an error is to determine the cause of the error. Once you
know the cause of the error, it’s often easy to fix the error.
• For a compile-time error, go to the line in the source code that won’t compile. In
NetBeans, you can do that by clicking on the link to the line of source code. That
should give you a strong indication of what caused the error.
• For a runtime error, go to the line in the source code that was running when the
application crashed. In NetBeans, you can do that by clicking on the link to the line
of source code. That should give you a strong indication of what caused the error.
• For a logic error, review the output, review the source code, and try to figure out
how the source code produced that output. It’s often difficult to determine what
caused the error, but some of the techniques presented later in this chapter can help.
Description
• A simple way to trace the execution of an application is to insert println statements
at key points in the code that print messages to the console.
• The messages that are printed to the console can indicate what code is being
executed, or they can display the values of variables.
• When you see an incorrect value displayed, there is a good chance that the applica¬
tion contains a logic error between the current println statement and the previous
one.
_
File Edit View Navigate Source Refactor Run Debug Profile Team Tools Window Help Or Si
Projects K Files Services □ i-.l4 Line I tern App, java ss | (rtj Lineltem.java ss| n
h chOSjJneltem
- Source Packages
Source History
> I 1? I o□ = =1 H-
0- 33 return, quant it’
0-j | murach. business
34
f—[c£l Linelteni.java 35
Product, java
(3 j_ j
36 0 public double getTotal {) {
murach.db
jd£| ProductDB.java
37 double total = guantlt .
duct gerPrice ( };
38 return total;
& Q muraeh.ui L
39
leg-, LinertemApp.java
40
±> Libraries
41 Q public String getTotalFormatted.( ) {
>le total = thi3.getTotal O ;
43 Number For mat currency = Number Format.get CurrencyInstance();
44 String totalFormatted - currency.format (total j;
45 return total Format ted;
46 >
getTota I Formatted - Navigator 0 47
Members :'emp m
Description
• When debugging, you need to stop application execution before the line of code
that caused the error. Then, you can examine variables and step through code as
described in the next few figures.
• To stop application execution, you can set a breakpoint. Then, when you run the
application, execution stops when it reaches the breakpoint.
• To set a breakpoint for a line, open the code editor for the class and click on the line
number. The breakpoint is identified by a small red square that’s placed to the left
of the line of code.
• To remove a breakpoint, click on the breakpoint icon.
• You can set and remove breakpoints either before you start debugging or while
you’re debugging. In most cases, you’ll set at least one breakpoint before you start
debugging.
• To start debugging for the main project, click the Debug Main Project button on the
toolbar. If a single project is open and it’s not set as the main project, the name of
this button is Debug Project.
• You can also start debugging by right-clicking on a project and selecting the Debug
command or by right-clicking on the file that contains the main method you want to
run and selecting the Debug File command.
A debugging session
Description
• When a breakpoint is reached, execution is stopped before the line is executed.
• The arrow in the bar at the left side of the code editor window shows the line that will
be executed next.
• The Variables window shows the values of the variables that are in scope for the current
method. This window is displayed by default when you start a debugging session. If you
close it, you can open it again using the Window-ÿDebugging-ÿ Variables command.
• If a variable in the Variables window refers to an object, you can view the values
for that object by clicking the plus sign to the left of the object name to expand it.
• You can use the buttons on the Debug toolbar to control the execution of an application.
Figure 6-6 Flow to step through code and inspect variables
160 Section 1 Get started right
Description
• A stack trace is a list of the methods that have been called in the reverse order in
which they were called.
• By default, NetBeans displays a stack trace in the Debugging window that’s
included in the group of windows at the left side of the IDE.
• You can also display a stack trace in the Call Stack window, which appears in the
group of windows below the code editor. You can display this window by selecting
the Window ->Debugging->Call Stack command.
• To jump to a line of code in the code editor that’s displayed in the stack trace,
double-click on that line in the stack trace.
Perspective
Before you put an application into production, you should test it and debug
it thoroughly. Now that you’ve completed this chapter, you should have the
skills you need to test an application to identify any bugs it may contain. In
addition, you should be able to use the NetBeans debugger to locate the cause
of those bugs.
The skills presented in this chapter should give you a solid foundation for
testing and debugging any application that you develop. However, NetBeans
provides some additional features that you can use to test and debug your appli¬
cations. After reading this chapter, you should have the background you need to
learn more about other debugging features that are available from NetBeans.
As you test an application, you may also run into memory or
performance-related problems. To help identify the source of these problems,
you can use the NetBeans Profiler. This tool lets you monitor the performance
of an application. Then, you can use the data it provides to locate code in your
application that can be optimized so the application will run more efficiently.
As you begin to develop more complex applications, you may also want
to learn about unit testing. Unit testing is a way of creating tests for individual
units of source code such as methods to make sure they work correctly. Unit
tests can automate much of the application testing you would normally have
to do manually. By automating the testing, it’s more likely that the testing will
actually be done each time an application is updated. This makes it easier to
find and fix a bug since it’s easier to determine what new code introduced the
bug.
Summary
• To test an application, you run it to make sure that it works properly no
matter what combinations of valid or invalid data you enter.
• When you debug an application, you find and fix all of the errors (bugs) that
you find when you test the application. This process is known as debugging.
• Compile-time errors violate the rules for how Java statements must be
written. These errors are detected by the Java compiler before you can run
the application.
• Runtime errors occur while you are running an application. These types of
errors throw exceptions that stop the execution of the application.
• Logic errors don’t cause the application to crash, but they prevent it from
working correctly.
• A simple way to trace the execution of an application is to insert println
statements at key points in the code.
• NetBeans includes a powerful tool known as a debugger that can help you
find and fix these errors.
Chapter 6 How to test and debug an application 163
• You can set a breakpoint on a line of code to stop code execution just before
that line of code. Then, you can step through the code and view the values of the
variables as the code executes.
• A stack trace is a list of methods in the reverse order in which they were called.
1 1 . Click the Step Over button in the toolbar repeatedly to step through the
statements in this method. After each step, review the values in the Variables
window to see how they have changed.
1 2. Click the Continue button in the toolbar to continue the execution of the appli¬
cation.
1 3. Display the Output window again. Then, enter “n” to exit the application and
end the debugging session.
Set a breakpoint and step through the application
1 4. Open the LineltemApp class and set a breakpoint on the first line of code in
the main method.
1 5. Click on the Debug Project button in the toolbar.
1 6. Use the Step Over and Step Into buttons to step through each line of the
application. To do that, use the Step Over button for most statements and the
Step Into button for any statements that call constructors and methods from
the Lineltem, Product, and ProductDB classes. As you do this, use the Output
window to enter data and the Variables window to inspect the variables. This
should give you a good idea of how this code works.
Stop the debugger and remove the breakpoints
1 7. Once you have the hang of stepping through this application, click the Finish
Debugger Session button to end the application.
1 8. Remove the breakpoints that you set earlier in this exercise. To do that, you
can click on the red square icon for the breakpoint.
Section 2
Essential skills
as you need them
This section consists of four chapters that show you how to use more of the
core Java features. Chapter 7 presents the most important skills for working
with data types and operators. Chapter 8 presents the most important skills
for working with control statements. Chapter 9 presents the most important
skills for working with strings. And chapter 10 presents the concepts and
techniques you need to know to work with arrays.
We have designed each chapter in this section as an independent unit.
As a result, you can read these chapters in any sequence you like. If, for
example, you want to learn more about control structures, you can read
chapter 7 next. Or, if you want to learn about arrays, you can read chapter 9
next.
7
How to work with primitive
types and operators
In chapter 2, you learned how to use two of the eight primitive data types. In
addition, you learned how to use operators to perform some simple arithmetic
calculations. Now, you’ll learn about the other six primitive data types. In
addition, you’ll learn the details for using operators to work with these data
types at a professional level.
Description
• Integers are whole numbers.
• Floating-point numbers provide for very large and very small numbers that require
decimal positions, but with a limited number of significant digits. A single-precision
number provides for numbers with up to 7 significant digits. A double-precision
number provides for numbers with up to 16 significant digits.
• The Unicode character set provides for over 65,000 characters with two bytes used
for each character. The ASCII character set provides characters for the English
language. These characters are the first 256 characters of the Unicode character set.
• A Boolean value can be true or false. In Java, the boolean data type provides for
Boolean values. Like the other primitive types, it uses all lowercase letters.
Technical notes
• To express the value of a floating-point number, you can use scientific notation.
For example, 2.382E+5 means 2.382 times 105, which is a value of 238,200.
Conversely, 3.25E-8 means 3.25 times 10 s, which is a value of .0000000325. Java
sometimes uses this notation to display the value of a floating-point number.
• Because of the way floating-point numbers are stored internally, they can’t repre¬
sent the exact value of the decimal places in some numbers. This can cause a
rounding problem. Later in this chapter, you’ll learn how to use the BigDecimal
class to solve these rounding problems.
• By default, Java uses Intel 80-bit extended precision floating-point when it is avail¬
able from the CPU. As a result, code that uses floating-point numbers may produce
slightly different results on different systems.
Example
int counter; // declaration statement
counter =1; // assignment statement
Examples
int counter = 1; // initialize an int variable
double price = 14.95; // initialize a double variable
float interestRate = 8.125F; // F indicates a floating-point value
long numberOf Bytes = 20000L; // L indicates a long integer
int populationl = 1734323; // initialize an int variable
int population2 = 1_734_323; // improve readability - Java 7 and later
double distance = 3.65e+9; // scientific notation
char letterl = 'A1; // stored as a two-digit Unicode character
char letter2 = 65; // integer value for a Unicode character
boolean valid = false; // where false is a keyword
int x = 0, y = 0; // initialize 2 variables with 1 statement
Description
• A variable stores a value that changes as an application executes. In other words, a
variable varies as an application executes.
• Before you can use a variable, you must declare its data type and its name.
• After you declare a variable, you can assign a value to the variable. To do that, you
use the assignment operator (=).
• You can initialize a variable by declaring it and assigning a value to it. To do that,
you can use two statements, but it’s common to use one statement.
• To declare and initialize more than one variable for a single data type in a single
statement, use commas to separate the assignments.
• To identify float values, you must type an/or F after the number.
• To identify long values, you can type an / or L after the number.
Naming conventions
• Start variable names with a lowercase letter and capitalize the first letter in all
words alter the first word. This naming convention is known as camel case.
• Try to use meaningful names that are easy to remember as you code.
Examples
final int DAYS_IN_NOVEMBER = 30;
final float SALES_TAX = .075F;
final double LIGHT_ YEAR_MILES = 5.879e+12
Description
• A constant stores a value that does not change as an application executes. In other
words, a constant remains constant as an application executes.
• To declare a constant, you begin the declaration statement with the final keyword.
After that, the skills for initializing variables also apply to constants.
• To make it easy to distinguish between variables and constants, most Java devel¬
opers use camel case for variables and all caps for constants.
Naming conventions
• Capitalize all of the letters in constants and separate words with underscores.
• Try to use meaningful names that are easy to remember.
Description
• An arithmetic expression consists of arithmetic operators that operate on one or
more numbers known as operands.
• Binary operators operate on two operands.
• An assignment statement can assign the value of an expression to a variable. Then,
when Java executes the assignment statement, it determines the value of the expres¬
sion and stores the result in the variable.
Description
• Unary operators operate on just one operand.
• When you use an increment or decrement operator as a postfix to a variable, Java
performs the increment or decrement operation alter other operations.
• When you use an increment or decrement operator as a prefix to a variable, Java
performs the increment or decrement operation before other operations.
• If you code an increment or decrement operation as a single statement, not as part
of an expression, it doesn’t matter whether the operator is prefixed or postfixed.
Statements that use the same variable on both sides of the equals sign
count = count + 1; // count is increased by i
count = count
total = total
— Is100.0; II
II
count is decreased by i
total is increased by 100.0
—* .8;
+
total = total 100.0; II total is decreased by 100.0
price = price II price is multiplied by .8
sum = sum + nextNumber; II sum isi increased by the value
Description
• Besides the assignment operator (=), Java provides for five compound assignment
operators. These operators provide a shorthand way to code common assignment
operations.
• The compound assignment operators are also referred to as the augmented assign¬
ment operators.
If you have trouble creating an expression like this for a difficult calculation,
you can often break the expression down into a series of statements as shown
in the last four lines of code. Here, the first statement adds the monthly invest¬
ment amount to the current value. The second statement calculates the monthly
interest rate. The third statement calculates the monthly interest amount. And the
fourth statement adds the interest to the current value. This takes away the need
for parentheses. In addition, it makes the code easier to read and debug,
Chapter 7 How to work with primitive types and operators 1 81
Description
• Unless parentheses are used, the operations in an expression takes place from left to
right in the order of precedence.
• To specify the sequence of operations, you can use parentheses. Then, the opera¬
tions in the innermost set of parentheses are done first, followed by the operations
in the next set, and so on.
double d = 95-0;
int i = 86, j = 91;
double average = (d+i+j )/3; // convert i and j to double values
/ / average = 90.666666...
Examples
int grade = (int) 93-75; // convert double to int (grade = 93)
double d = 95-0;
int i = 86, j = 91;
int average = ( (int )d+i+j )/3; // convert d to int value (average = 90)
int remainder = ( (int )d+i+j )%3; // convert d to int value (remainer = 2)
Description
• If you assign a less precise data type to a more precise data type, or you assign a
smaller data type to a larger data type, Java automatically performs the cast and makes
the conversion. This can be referred to as an implicit cast or a widening conversion.
• When you code an arithmetic expression, Java implicitly casts the less precise data
types to the most precise data type.
• To code an assignment statement that assigns a more precise data type to a less
precise data type, you must use parentheses to specify the less precise data type.
This can be referred to as an explicit cast or a narrowing conversion.
• When you code an explicit cast in an arithmetic expression, Java performs the cast
before any arithmetic operations.
• Since each char value has a corresponding int value, you can implicitly or explicitly
cast between these types.
Description
• You can use the static methods of the Math class to perform common arithmetic
operations. This figure summarizes the methods that are the most useful for
business applications.
• When a method requires one or more arguments, you code them between the
parentheses, separating multiple arguments with commas.
• In some cases, you need to cast the result to the data type that you want.
Description
• The BigDecimal class provides a way to perform accurate decimal calculations in
Java. It also provides a way to store numbers with more than 16 significant digits.
Description
• With this code, all of the numbers are stored in BigDecimal objects, and all of the
results have two decimal places that have been rounded correctly when needed.
• Once the results have been calculated, you can use the NumberFormat methods to
format the values in the BigDecimal objects without any fear of rounding problems.
The code
Much of the code for the Invoice application works like the code for the Line
Item application presented in chapter 3. As a result, the following description
focuses on the new skills that were presented in this chapter.
To start, this code imports the BigDecimal class and the RoundingMode
enumeration. This allows you to use the BigDecimal class to round numbers that
have decimal places as described earlier in this chapter.
Within the while loop, the first statement prompts the user to enter a
subtotal. Then, the second statement gets a String object for the text that the
user entered. Next, the third statement creates a new BigDecimal object from
this String object, calls the setScale method directly from this object, and
calls the doubleValue method directly from the setScale method. This returns
a double value that’s rounded to 2 decimal places and stores it in the variable
named subtotal. This is necessary because it’s possible that the user might enter
a subtotal that had more than 2 decimal places. In that case, this code would
prevent a rounding error by rounding the number to 2 decimal places.
After getting a double value for the subtotal, the loop uses an if/else state¬
ment to calculate the discount amount based on the value of the subtotal. If, for
example, the subtotal is greater than or equal to 200, the discount amount is .2
times the subtotal (a 20% discount). If that condition isn’t true and the subtotal
is greater than or equal to 100, the discount is . 1 times subtotal (a 10% discount).
Otherwise, the discount amount is 0.
Chapter 7 How to work with primitive types and operators 191
The console
The code
-
package murach invoice;
import java.util.Scanner;
import java.t ext.NumberForma t;
import java.math.BigDecimal;
import java.math.Round ingMode;
After the if/else statement, this code calculates the discount amount by
multiplying the subtotal by the discount percent. Since this can result in more
than 2 decimal places, this code uses the BigDecimal class to round the result
to 2 decimal places, and it returns the number as a double value. To do that, this
code creates a new BigDecimal object from the double value for the discount
amount, uses the setScale method to round the number, and uses the double Value
method to return the double value. Then, this code calculates the total before tax
by subtracting discount Amount from subtotal.
This code continues by declaring a constant named SALES_TAX_PCT
that stores the sales tax percent. Here, this constant is set to a value of .05 (5%).
Then, this code multiplies this constant by the total before tax to get the sales tax
amount. Since this amount might contain more than 2 decimal places, this code
uses the BigDecimal class to round this number to 2 decimal places using the
same technique that was used earlier in this class.
After this code finishes making all of its calculations, it uses the
NumberFormat class to apply currency and percent formatting to the monetary
and percent values. Then, it prints a message to the console that includes these
values. Since all of the monetary values have been rounded to 2 decimal places
before this formatting was applied, the values that are displayed should add up.
In other words, this application shouldn’t contain any rounding errors.
Unfortunately, this application still doesn’t handle the exception that’s
thrown if the user doesn’t enter a valid value for the subtotal. However, you’ll
learn how to handle this exception in the next chapter.
Chapter 7 How to work with primitive types and operators 1 93
// calculate total
double total = totalBef oreTax + salesTax;
System.out .println(message );
Perspective
If this chapter has succeeded, you should now be able to work with any of
the primitive data types you need in your applications. In addition, you should
be able to use the Math class whenever you need it. And you should be able
to use the BigDecimal class to solve the problems that are associated with
floating-point numbers such as rounding errors.
Summary
• Java provides eight primitive data types to store integer , floating-point,
character, and boolean values.
• Variables store data that changes as an application runs. Constants store data
that doesn’t change as an application runs. You use assignment statements to
assign values to variables.
• You can use arithmetic operators to form arithmetic expressions, and you
can use some assignment operators as a shorthand for some types of arith¬
metic expressions.
• Java can implicitly cast a less precise data type to a more precise data type.
Java also lets you explicitly cast a more precise data type to a less precise
data type.
• You can use the static methods of the Math class to perform mathematical
operations such as calculating the square root of a number.
• You can use the BigDecimal class to create BigDecimal objects that store
decimal values that aren’t limited to 16 significant digits. In addition, you
can use the methods of these objects to perform operations such as addition,
subtraction, multiplication, division, and rounding,
Chapter 7 How to work with primitive types and operators 195
7. Before the while loop, declare a total variable of the float type. After the code
that displays the line item, use the compound addition operator to add the
total for the line item to the total variable. After the while loop, display the
total like this:
8. Before the while loop, declare one variable of the float type that stores the
largest line item and another variable of the float type that stores the smallest
line item. After displaying the line item, use the max and min methods of the
Math class to update the values for the largest and smallest line items. After
the loop, display the total like this:
To get this to work correctly, you need to initialize the minimum value to a
very large value. Also, within the min and max methods of the Math class,
you need to cast the value that’s returned by the getTotal method of the
Lineltem class to a float value.
196 Section 2 Essential skills as you need them
m/
Relational operators
Operator Name Description
== Equality Returns a true value if both operands are equal,
1
* = Inequality Returns a true value if the left and right operands
are not equal,
> Greater Than Returns a true value if the left operand is
greater than the right operand.
< Less Than Returns a true value if the left operand is less
than the right operand,
>= Greater Than Or Equal Returns a true value if the left operand is
greater than or equal to the right operand.
<= Less Than Or Equal Returns a true value if the left operand is less
than or equal to the right operand.
Boolean expressions
discountPercent == 2.3 // equal to a numeric literal
letter == // equal to a char literal
isValid == true II equal to a true value
Description
• You can use the relational operators to create a Boolean expression that compares
two operands and returns a Boolean value that is either true or false.
• If you compare two numeric operands that are not of the same type, Java converts
the less precise operand to the type of the more precise operand before comparing
the operands.
• A variable of the boolean type stores a Boolean value of true or false.
• The floating-point types (double and float) don’t always represent the exact value of
a number. As a result, you shouldn’t use the equals operator (==) to compare them
for eq uality.
• String objects are reference types, not primitive types. As a result, you shouldn’t
use the equals operator (==) to compare them for equality. Instead, you should use
the equals or equalsIgnoreCase methods of the String class as described in
chapter 3.
Logical operators
Operator Name Description
&& And Returns a true value if both expressions are true. This operator
only evaluates the second expression if necessary.
Or Returns a true value if either expression is true. This operator
only evaluates the second expression if necessary.
I
* Not Reverses the value of the expression.
(subtotal > 250 && subtotal < 500) isValid // 2 logical operators
Description
• You can use the logical operators to create a Boolean expression that combines two
or more Boolean expressions.
• Since the && and II operators only evaluate the second expression if necessary,
they’re sometimes referred to as short-circuit operators and are slightly more
efficient than the & and I operators.
• By default, Not operations are performed first, followed by And operations, and
then Or operations. These operations are performed after arithmetic operations and
relational operations.
• You can use parentheses to change the sequence of operations. In addition, you can
use parentheses to clarify the sequence of operations.
Description
• An if/else statement, or just if statement, always contains an if clause. In addition, it
can contain one or more else if clauses, and one else clause.
• A pair of braces defines a block of code. Any variables declared within a block have
block scope. As a result, they can only be used within that block.
• Java evaluates if/else statements from the top down. Once a clause evaluates to true,
Java skips the rest of the if/else statement. As a result, it’s most efficient to code the
most likely conditions first and the least likely conditions last.
If efficiency isn’t your primary concern, you should code the conditions
in a logical sequence. For example, you could start by coding a condition that
checks for the highest subtotal and work your way down to the lowest subtotal.
This would simplify the condition for each clause by removing the need for the
logical operators. As always, the easier your code is to read and understand, the
easier it is to test, debug, and maintain.
The fourth example of this figure shows an if/else statement that contains
multiple statements within each clause. Here, the first statement sets the variable
named discountPercent, and the second statement sets the variable named
shippingMethod. Since these clauses contain multiple statements, the braces are
required.
If a clause only contains a single statement, the braces are optional. In that
case, you can just end the clause with a semicolon as shown in the fifth and sixth
examples. Here, the fifth example shows an if/else statement that uses two lines
per clause. Then, the sixth example shows an if statement that uses one line.
Some programmers prefer the second approach since it clearly shows that the
clause should only contain a single statement.
However, it’s generally considered a good coding style to use braces for all
if/else statements. That’s why the first three examples in part 1 of this figure use
them. That way, you won’t introduce bugs later if you add more statements and
forget to add the braces.
When coding if statements, it’s a common practice to code one if state¬
ment within another if statement. This is known as nesting if statements, and
it’s shown by the third example in this figure. When you nest if statements,
it’s a good practice to indent the nested statements and their clauses since this
allows the programmer to easily identify where each nested statement begins
and ends. In this figure, for example, Java only executes the nested statement if
the customer type is “r”. Otherwise, it executes the statements in the outer else
clause.
Chapters How to code control statements 205
Nested if statements
double discountPercent;
if ( customerType.equals( "r" )) {
if (subtotal >= 100) { // begin nested if
discountPercent = .2;
} else {
discountPercent =.1;
} // end nested if
}
else {
discountPercent = .4;
}
Description
• If a clause in an if/else statement contains just one statement, you don’t have to
enclose the statement in braces. You can just end the clause with a semicolon.
• It’s generally considered a good coding style to use braces for all if/else statements.
That way, you won’t introduce bugs later if you add more statements and forget to
add the braces .
• Whenever necessary, you can nest one if statement within another.
Description
• Prior to Java 7, the switch statement could only be used with an expression that
evaluated to one of these integer types: char, byte, short, or int.
• Starting with Java 7, the switch statement can also be used with string expressions.
Then, the switch statement uses the equals method of the String object to compare
the strings. As a result, the strings in switch statements are case-sensitive.
• The switch statement transfers control to the appropriate case label. If control isn’t
transferred to one of the case labels, the optional default label is executed.
• For primitive types, switch statements are generally more efficient than if/else
statements.
The third example shows how to code a switch statement that sets a day
variable to “weekday” or “weekend” depending on the value of the integer in the
variable named dayOfWeek. Here, the case labels for 1 , 2, 3, and 4 don’t contain
any statements, so execution falls through to the case label for 5. As a result, day
is set to “weekday” for any of those values. Similarly, whenever dayOfWeek
equals 6 or 7, day is set to “weekend”.
Although a break statement is coded at the end of the last case label in this
example, you should know that it isn’t required. If you omit this break statement,
program execution automatically falls through to the statement that follows
the switch statement. However, it’s generally considered a good programming
practice to code a break statement at the end of the last case label. That way,
if you add a new case label after the last case label, your switch statement still
works correctly. Similarly, if you move the last case label so it occurs earlier in
the switch statement, it still works correctly.
When you code switch statements, you can nest one statement within
another. You can also nest if/else statements within switch statements and switch
statements within if/else statements. Here again, you should try to code the state¬
ments with a logical structure that is relatively easy to understand. If necessary,
you can also add comments that clarify the logic of your code.
Chapter 8 How to code control statements 209
Description
• If a case label doesn’t contain a break statement, code execution/ÿ//.? through to the
next label. Otherwise, the break statement ends the switch statement.
• The case labels can be coded in any sequence.
The console
Welcome to the Invoice Calculator
INVOICE
Subtotal: $100.00
Discount percent: 10%
Discount amount: $10.00
Total before tax: $90.00
Sales tax: $4.50
Invoice total: $94.50
Continue? (y/n): n
Bye!
Description
• In a while loop, the condition is tested before the loop is executed.
• A while loop executes the block of statements within the loop as long as its
Boolean expression is true.
• If a loop requires more than one statement, you must enclose the statements in
braces. This identifies the block of statements that are executed by the loop, and
any variables or constants that are declared in that block have block scope.
• If a loop requires just one statement, you don’t have to enclose the statement in
braces. However, it’s generally considered a good practice to use braces to identify
the statements that are executed by the loop.
• If the condition for a loop never becomes false, the loop never ends. This is known
as an infinite loop. Although infinite loops can be useful at times, beginning
programmers often code them accidentally. In NetBeans, you can cancel an infinite
loop by clicking on the Stop button in the Output window,
Description
• A do-while loop works like a while loop, except that the condition is tested after the
loop is executed.
• In general, while loops are preferred over do-while loops. In practice, while loops
are commonly used and do-while loops are rarely used.
• One problem with a do-while loop is that it’s possible for the while statement to
get separated from the loop if a programmer inserts code between the loop and the
while statement. This can introduce a bug that’s difficult to find and fix.
Description
• Afar loop is useful when you need to increment or decrement a counter that
determines how many times the loop is executed.
• Within the parentheses of a for loop, you code an initialization expression that gives
the starting value for the counter, a Boolean expression that determines when the
loop ends, and an increment expression that increments or decrements the counter.
• The loop ends when the Boolean expression is false.
• If necessary, you can declare the counter variable before the for loop. Then, this
variable is in scope after the loop finishes executing.
• Within the parentheses of a for loop, all three expressions are optional. As a result,
you can code an infinite for loop by coding the semicolons that separate these
expressions but by not coding any of these expressions.
The console
The console
Description
• To jump to the end of the current loop, you can use the break statement.
• To skip the rest of the statements in the current loop and jump to the top of the
current loop, you can use the continue statement.
Description
• An exception is an object that contains information about an error that has occurred.
When an error occurs in a method, the method throws an exception.
• If an exception is thrown when you’re testing a console application, some informa¬
tion about the exception, including its name and stack trace, is displayed at the
console.
• A stack trace is a list of the methods that were called before the exception occurred.
The list appears in reverse order, from the last method called to the first method
called.
• All exceptions are subclasses of the Exception class. The Exception class repre¬
sents the most general type of exception. Each successive layer of subclasses
represents more specific exceptions.
• The RuntimeException class represents exceptions that occur at runtime. All of the
exceptions described in this chapter are runtime exceptions.
Console output
Description
• In a try statement (or try/catch statement), you code any statements that may throw
an exception in a try block. Then, you can code a catch block that handles any
exceptions that may occur in the try block.
• When an exception occurs, any remaining statements in the try block are skipped
and the statements in the catch block are executed
• Any variables or objects that are used in both the try and catch blocks must be
declared before the try and catch blocks so both the try and catch blocks can access
them.
• If you use a catch block to catch a specific type of exception, you should also
import the package that contains that exception class.
The code
Part 1 of this figure shows the Financial class that’s stored in the package
named murach.calculators. This class contains a single static method named
calculateFutureValue. This method accepts three arguments: (1) the monthly
investment, (2) the yearly interest rate, and (3) the number of years. From these
arguments, this method calculates the future value and returns it.
Within this method, the first two statements convert the yearly values to
monthly values. To do that, the first statement divides the yearly interest rate by
12 to convert it to a monthly interest rate, and divides that rate by 100 to convert
it to a percent value. Then, the second statement multiples the number of years
by 1 2 to get the number of months.
After this method creates the monthly variables, it uses a for loop to calcu¬
late the future value. To do that, it executes the loop once for each month.
Within the loop, the first statement adds the monthly investment to the future
value. The second statement calculates the amount of interest for the month. And
the third statement adds the interest to the future value. After the loop, the return
statement method returns the future value to the calling method.
Chapter 8 How to code control statements 225
The console
return futureValue;
}
}
Part 2 of this figure shows the Console class that’s stored in the package
named murach.ui. This class contains static methods that display data on the
console and get input from the console.
To start, this class begins with the import statement for the Scanner class.
Then, within the class, the first statement declares a static instance variable for
a Scanner object named sc and creates this object. As a result, all of the static
methods in this class can use that Scanner object.
The two displayLine methods use the println method of the System.out
object to display data to the console. Here, the first displayLine method displays
a blank line, and the second displayLine method displays the specified string on
its own line.
The getString method begins by displaying the specified string to prompt the
user to enter data. For example, you could specify a string of “Enter your name:”
to prompt the user to enter a string. Then, this method uses the nextLine method
of the Scanner object to get a String object for the data that the user enters, and it
returns that String object.
The getlnt method begins by declaring an int variable named i. This variable
stores the int value that’s returned by this method. Then, this method uses an
infinite while loop to continue prompting the user until he or she enters a valid
integer. Within the infinite while loop, the first statement displays the prompt.
For example, you specify a string of “Enter years:” to prompt the user to enter an
integer for the number of years.
After the prompt, this method uses a try/catch statement. Within the try
block, the first statement attempts to convert the data that the user enters to an
integer. If this conversion throws a NumberFormatException, the catch block
prints an error message that indicates that the user didn’t enter a valid integer
and the while loop continues. As a result, it prompts the user for the integer
again.
However, if this conversion succeeds, the code in the try block stores the
integer in the variable named i. Then, the try block calls the break statement.
This exits the while loop, which returns the integer stored in the variable
named i.
The getDouble method works like the getlnt method. However, it works with
the double type instead of the int type.
Chapter 8 How to code control statements 227
import java.util.Scanner;
Part 3 of this figure shows the Main class that’s stored in the package named
m urach.ui. This class contains the main method for the application. Much of the
code for this method works like the main method for the Line Item application
presented in chapter 3. As a result, the following description focuses on the new
skills that were presented in this chapter.
To start, this application begins with import statements that import the
NumberFormat class and the Financial class shown in part 1 of this figure. As a
result, this application can use the Financial class to calculate the future value,
and it can use the NumberFormat class to format the future value.
Within the main method, the first two statements use the Console class to
display a welcome message. Then, within the while loop, the first three state¬
ments use the getDouble and getlnt methods of Console class. These statements
get the double and int values that correspond with the monthly investment, the
yearly interest rate, and number of years. Here, the Console class converts the
string that’s entered by the user to the correct numeric type and handles the
exception that’s thrown if the user enters an invalid number. As a result, it makes
it easy to get numeric data from the user.
After getting the numeric data from the user, this code uses the Financial
class shown earlier to calculate the future value. Then, this code uses the
Console class and the NumberFormat class to display the future value with
currency formatting.
After displaying the future value, this code uses the Console class to ask
the user if he or she wants to continue. To do that, this code uses the getString
method to get the data that’s entered by the user.
Chapter 8 How to code control statements 229
Perspective
If this chapter has succeeded, you should now be able to use if, switch,
while, do-while, and for statements. These are the Java statements that imple¬
ment the selection, case, and iteration structures, and they provide the logic of
an application. You should also be able to code try/catch statements that handle
some runtime exceptions that occur when the user enters invalid numbers.
Summary
• You can use the relational operators to create Boolean expressions that
compare primitive data types and return true or false values, and you can use
the logical operators to connect two or more Boolean expressions.
• To determine whether two strings are equal, you can call the equals or
equalsIgnoreCase method from a String object.
• You can use if/else statements and switch statements to control the logic of
an application, and you can nest these statements whenever necessary.
• You can use while, do-while, and/or loops to repeatedly execute one or more
statements until a Boolean expression evaluates to false, and you can nest
these statements whenever necessary.
• You can use break statements to jump to the end of the current loop, and you
can use continue statements to jump to the start of the current loop.
• An exception is an object that’s created from the Exception class or one
of its subclasses. This object contains information about an error that has
occurred
• The stack trace is a list of methods that were called before an exception
occurred
• You can code a try statement to create an exception handler that catches and
handles any exceptions that are thrown. This is known as exception handling.
Chapter 8 How to code control statements 231
Description
• You can initialize a String variable by assigning a String literal or another variable
that refers to a String object.
• To join (or concatenate) one string with another string or another data type, you can
use the + operator.
• To append a string or another data type to a string, you can use the += operator.
• When you join or append other data types to a String object, Java automatically
converts the other data types to String objects so they can be used as part of the
string.
Description
• The String class provides methods that you can use to compare strings.
• The equality operator (==) checks whether two strings refer to the same String
object. It’s possible for two strings to contain the same characters, but to refer
to different String objects. As a result, you should not use this operator to check
whether two strings contain the same characters.
Code that gets the index values for the two spaces
String name = "Martin Van Buren";
int indexl = name.indexOf ( " "); // indexl is 6
int index2 = name.indexOf ( " ", indexl+1); // index2 is 10
Another way to get the index values for the two spaces
String name = "Martin Van Buren";
int indexl = name.last IndexOf ( " "); // indexl is 10
int index2 = name.last IndexOf ( " ", indexl-1); // index2 is 6
Description
• You can use an index to refer to each character within a string where 0 is the first
character, 1 is the second character, and so on.
Code that removes spaces from the start and end of a string
String choice = " y ";
choice = choice.trim(); // choice is "y"
Code that parses a first name and last name from a string
String name = "Mike Murach";
int index = name.indexOf ( " "); // index is 4
String firstName = name.substring ( 0, index); // firstName is "Mike"
String lastName = name.substring(index + 1); // lastName is "Murach"
}
-
temp += ccNumber charAt ( i );
}
ccNumber = temp;
Description
• String objects are immutable. As a result, they can’t grow or shrink.
• StringBuilder objects are mutable, which means you can modify the characters
in the string. The capacity of a StringBuilder object is automatically increased if
necessary.
• The StringBuilder class was introduced with Java 5. It’s designed to replace the
older StringBuffer class.
• The StringBuffer class has identical constructors and methods as the StringBuilder
class. As a result, you can use it to accomplish the same tasks.
• The StringBuffer class isn’t as efficient as the StringBuilder class, but it is
thread-safe. As a result, you can use it instead of the StringBuilder class whenever
you need to make sure your code is thread-sale.
As you learned earlier in this chapter, you can accomplish the same task
by using the String class and the += operator. However, if you do that, Java
must create a new String object for each statement. In contrast, when you
use the append method of the StringBuilder class, Java doesn’t create a new
StringBuilder object. Instead, it increases the length of the StringBuilder object.
If necessary, it also increases the capacity of the StringBuilder object. As a
result, the StringBuilder object usually works more efficiently than the String
object.
The second example in figure 9-5 shows how a StringBuilder object
automatically increases its capacity as the length of the string increases. Here,
the first statement creates an empty StringBuilder object with a capacity of 8
characters. The second statement uses the capacity method to verify that the
capacity is 8. The third statement appends a string of 1 7 characters to the empty
string. Since this exceeds the capacity of the StringBuilder object, Java automati¬
cally increases the capacity by doubling the current capacity and adding 2. As a
result, this code increases the capacity from 8 to 1 8 characters. Then, the last two
statements verify the new length and capacity.
■
i-- ?
>
>
Code that parses a credit card number
String parti = ccNumber.substring( 0,4 );
String part2 = ccNumber.substring(4, 8 );
String part3 = ccNumber.substring( 8, 12);
String part4 = ccNumber.substring( 12 );
Description
• The StringBuilder class provides many of the same methods as the String class. In
addition, it contains some methods that make it easier to modify strings.
The console
} -
return s substring(0, length);
}
}
- -
import murach db ProductDB;
import murach.business.Product;
list .append (
StringUtil.pad("=========", CODE_WIDTH) );
list .append (
StringUtil.pad("=================================", DESC_WIDTH) );
list .append (
StringUtil.pad("=========", PRICE_WIDTH) );
list.append ( "\n" );
list .append (
StringUtil.pad(product .getCode( ), CODE_WIDTH) );
list .append (
StringUtil.pad(product.getDescription( ), DESC_WIDTH) );
list .append (
StringUtil.pad(product.getPriceFormatted(), PRICE_WIDTH) );
list .append ( "\n" );
Perspective
Now that you’ve finished this chapter, you should be able to use the String
and StringBuilder classes to work with strings. These skills are fundamental to
developing Java applications. Keep in mind that this chapter has only covered
some of the most useful methods of these classes. As a result, if you want to
learn about the other methods of these classes, you can look them up in the
documentation for the Java API.
Summary
• You can use methods of the String class to compare all or part of a string,
locate a string within another string, and return parts of a string.
• When working with strings, you often need to use an index to refer to the
characters that make up the string. In a string, the first character has an index
of 0, the second character has an index of 1 , and so on.
• String objects are immutable. As a result, you can’t add, delete, or modify
individual characters in a string.
• StringBuilder objects are mutable. As a result, you can use the methods of
the StringBuilder class to append, insert, delete, or replace characters in a
StringBuilder object.
• StringBuilder objects are more efficient than String objects, especially if you
need to modify the string that you’re working with.
Chapter 9 How to work with strings 251
Or this:
1. Open the project named ch9_ex l_NameParser that’s in the ex_starts folder.
Then, review the code in the NameParserApp class.
2. Add code that separates the name into two or three strings depending on
whether the user entered a name with two words or three.
3. Display each word of the name on a separate line.
4. If the user enters fewer than two words or more than three words, display an
error message.
5. Make sure the application works even if the user enters one or more spaces
before or after the name.
6. Test the application to make sure it works correctly.
Section 2 Essential skills as you need them
m/
Other examples
An array of String objects
String[] titles = new String[3];
Description
• An array can store multiple primitive types such as int values or multiple reference
types such as String objects. An element is one of the items in an array.
• To create an array, you must declare a variable of the correct type and instantiate an array
object that the variable refers to. You can declare and instantiate the array in separate
statements, or you can combine the declaration and instantiation into a single statement.
• To declare an array variable, you code a set of empty brackets after the type or the
variable name.
• To instantiate an array, you use the new keyword and specify the length, or size, of
the array in brackets following the array type.
• When you instantiate an array of primitive types, numeric types are set to zeros and
boolean types to false. When you create an array of reference types, they are set to nulls.
The syntax for creating an array and assigning values in one statement
type[] arrayName = {valuel, value2, value3, ...};
Description
• To refer to the elements in an array, you use an index that ranges from zero (the first
element in the array) to one less than the number of elements in the array.
• If you specify an index that’s less than zero or greater than the upper bound of the
array, Java throws an ArraylndexOutOfBoundsException.
• You can instantiate an array and provide initial values in a single statement by
listing the values in braces. The number of values you provide determines the size
of the array.
Description
• You can use lor loops to process each element in an array.
• You can use the length field of an array to determine the number of elements in the
array.
Description
• Java 5 introduced the enhanced for loop. This loop simplifies the code required
to loop through arrays. The enhanced for loop is sometimes called a foreach loop
because it lets you process each element of an array.
• Within the parentheses of an enhanced for loop, you declare a variable with the
same type as the array followed by a colon and the name of the array.
• With each iteration of the loop, the variable that’s declared by the for loop is
assigned the value of the next element in the array.
• You can also use enhanced for loops to work with collections as described in
chapter 14.
Description
• Two-dimensional arrays use two indexes and allow data to be stored in a table that
consists of rows and columns. This can also be thought of as an array of arrays
where each row is a separate array of columns.
• Most two-dimensional arrays are rectangular arrays where each row has the same
number of columns. However, it’s also possible to create jagged arrays where each
row may have a different number of columns.
• If necessary, you can extend this two-dimensional syntax to work with arrays that
have more than two dimensions.
Figure 10-5 Flow to work with rectangular arrays
264 Section 2 Essential skills as you need them
m/
Description
• All of these methods accept arrays of primitive data types and arrays of objects for
the array argument, and they all accept primitive types and objects for the value
argument.
• For the sort method to work correctly with an array of objects created from a
user-defined class, such as the Product class, the class must implement the
Comparable interface. For more information about implementing interfaces, see
chapter 12.
The first example in figure 10-7 shows how this works. Here, the code
creates two variables that refer to the same array. More specifically, the grades
variable and the percentages variable both refer to the same array. As a result,
any change to the grades variable is reflected by the percentages variable and
vice versa. In this example, for instance, the third statement sets percentages! 1 ]
to 70.2. As a result, this change is reflected by grades! 1 ]. This is shown by the
statement that prints grades! 1 J. Since the percentages and grades variables both
refer to the same array, this statement prints the value 70.2.
Description
• Like a string, an array is a reference type.
• To create a reference to an existing array, you can use the assignment operator (=)
to assign a variable that points to an existing array to another variable. Then, both
variables point to the same array.
• To check if two array variables refer to the same array, you can use the equality
operator (==).
• The copyOf method was introduced with Java 6. As a result, it only works with
Java 6 and later. Prior to Java 6, you can use the arraycopy method of the System
class.
• When you copy an array, the new array must be the same type as the source array.
The console
// validate input
if (monthNumber < 1 monthNumber > monthName.length) {
||
Console.displayLine( "Invalid month number. Try again.");
continue;
}
// display output
int monthlndex = monthNumber - 1;
Console.displayLine( "You selected: "
+ monthName[monthlndex] + "\n");
Perspective
Now that you’ve finished this chapter, you should know how to work with
one-dimensional and two-dimensional arrays. Although arrays are a core part
of Java, they may not always provide the functionality you need. In many
cases, it’s preferable to use a more advanced data structure called a collection.
For example, instead of using an array as shown in this chapter, you may want
to use an ArrayList object as shown in chapter 1 4.
Summary
• An array is a special type of object that can store multiple elements of the
same type.
• When working with arrays, you can use an index to identify any element
in the array. An index of 0 refers to the first element, 1 refers to the second
element, and so on.
• The length (or size) of an array is the number of elements that are in the
array.
• For loops are often used to process arrays. Java 5 introduced a new type of
for loop, called an enhanced for loop or a fo reach loop, that lets you process
each element of an array without using indexes.
• A one -dimensional array provides for a single column of elements. In
contrast, a two-dimensional array, or an array of arrays, provides for a table
of elements that has rows and columns.
• A two-dimensional array can be rectangular, where each row has the same
number of columns, or jagged, where each row may have a different number
of columns.
• You can use the Arrays class to fill, sort, search, copy, and compare arrays.
• Like a string, an array is a reference type. As a result, you should use the
copy method of the Arrays class if you want to copy the data of an array, and
you should use the equals method of the Arrays object if you want to check
whether two arrays store the same data.
Chapter 10 How to work with arrays 271
4. Use the sort method of the Arrays class to sort the values in the array, and
print the median value (the 50th value) to the console like this:
5. Print the 9th value of the array to the console and every 9th value after that like
this:
272 Section 2 Essential skills as you need them
m/
Object-oriented
programming skills
In the first section of this book, you learned how to create your own classes
and use them to create a well-structured, object-oriented application. That’s
a great start to object-oriented programming. Now, the chapters in this
section teach the rest of the skills Tor object-oriented programming that you
should know. Chapter 1 1 shows you how to use inheritance, an important
object-oriented skill. Chapter 12 shows you how to use interlaces, another
important object-oriented skill. And chapter 1 3 shows several more skills
including how to work with inner classes, how to work with enumerations,
and how to add API documentation to the classes that you create.
Because each of the chapters in this section builds on the previous
chapters, we recommend reading these chapters in sequence. In addition,
we recommend reading all of the chapters in this section before going on
to section 4 or 5. That’s because most of the chapters in sections 4 and 5
expect you to understand how inheritance, interfaces, inner classes, and
enumerations work.
11
How to work
with inheritance
Inheritance is one of the key concepts of object-oriented programming* It
lets you create a class that’s based on another class. When used correctly,
inheritance can reduce code duplication and simplify the overall design of an
application.
An introduction to inheritance
Inheritance allows you to create a class that’s based on another class. The
next two figures introduce some of the basic concepts of inheritance.
i
Book Software
void setCode(String c) void setCode(String c)
String getCodeO String getCodeO
void setDescription(String d) void setDescription(String d)
String getDescriptionO String getDescriptionO
void setPrice(double p) void setPrice(double p)
double getPriceO double getPriceO
String getPriceFormattedO String getPriceFormattedO
String toStringO String toStringO
Description
• Inheritance lets you create a new class based on an existing class. Then, the new
class inherits the fields and methods of the existing class.
• A class that inherits from an existing class is called a derived class, child class, or
subclass. A class that another class inherits is called a base class, parent class, or
superclass.
• A subclass can extend the superclass by adding new fields and methods to the
superclass. It can also override a method from the superclass with its own version
of the method.
toString ( ) Returns a String object containing the class name, followed by the
@ symbol, followed by a hexadecimal representation of the hash
code for this object. If that’s not what you want, you can override
this method as shown in the next fieure.
equals( Object Returns true if this variable refers to the same object as the specified
variable. Otherwise, it returns false, even if both variables refer to
objects that contain the same data. If that’s not what you want, you
can override the equals method as shown later in this chapter.
getClass( ) Returns a Class object that represents the type of this object.
clone( ) Returns a copy of this object as an Object object. Before you can
use this method, the class must implement the Cloneable interface.
hashCode( ) Returns an int value that represents the hash code for this object.
Description
• The Object class in the java.lang package is the superclass for all classes. In other
words, every class inherits the Object class or some other class that ultimately
inherits the Object class. As a result, the methods defined by the Object class are
available to all classes.
• When coding classes, it’s recommended to override the toString method so that it
returns a string that’s concise, informative, and easy for a person to read.
Access modifiers
Keyword Description
private Available within the current class,
public Available to classes in all packages,
protected Available to classes in the same package and to subclasses,
no keyword coded Available to classes in the same package.
public Product ( ) {
}
// get and set accessors for the code, description, and price
// instance variables
(ÿOverride
public String toStringO {
return description;
}
Description
• Access modifiers specify the accessibility of the members declared by a class.
• Protected members are accessible to the current class, to other classes in the same
package, and to subclasses.
• An annotation is a standard way to provide information about your code. When you
override a method, you can add the ©Override annotation to the method.
public Book( ) {
super(); // call constructor of Product superclass
author = "";
count ++;
}
(ÿOverride
public String toString() { // override the toString method
return super.toString( ) + // call method of Product superclass
" by " + author;
}
}
Description
• You can directly access fields that have public or protected access in the superclass
from the subclass.
• You can extend the superclass by adding new fields and methods to the subclass.
• You can override the public and protected methods in the superclass by coding
methods in the subclass that have the same signatures as methods in the superclass.
However, you can’t override private methods in the superclass because they aren’t
available to the subclass.
• You use the super keyword to call a constructor or method of the superclass. If you
call a constructor of the superclass, it must be the first statement in the constructor
of the subclass.
Product p;
P = b;
System.out .println(p.toString()); // calls toString from the Book class
p = s;
System.out .println(p.toString()); // calls toString from the Software class
Description
• Polymorphism is a feature of inheritance that lets you treat objects of different
subclasses that are derived from the same superclass as if they had the type of the
superclass, if, for example, Book is a subclass of Product, you can treat a Book
object as if it were a Product object.
• if you access a method of a superclass object and the method is overridden in the
subclasses of that class, polymorphism determines which method is executed based
on the object’s type. For example, if you call the toString method of a Product
object, the toString method of the Book class is executed if the object is a Book
object.
The console
Figure 1 1 -6 shows the console for the Product application. This application
works much like the Product application presented in chapter 4. However, there
are three main differences. First, this application displays an additional piece of
information about each product, which varies depending on whether the product
is a book or software. In particular, it displays an author for a book and a version
number for software. Second, this application displays a count of the total
number of objects it has created. Third, if the user enters an invalid product code,
the application displays an appropriate error message.
Chapter 11 How to work with inheritance 287
Description
• This version of the Product application handles two types of products: books and
software.
• If you enter the product code for a book, the information about the product includes
an author.
• If you enter the product code for software, the information about the product
includes a version n umber.
(ÿOverride
public String toStringO {
return description;
}
public Book() {
super( );
author = 11 11;
count ++;
}
(ÿOverride
public String toString() {
return super.toString ( ) + " by " + author;
}
}
public Software() {
super( );
version =
count ++;
}
(ÿOverride
public String toString() {
return super.toString ( ) + 11 11 + version;
}
}
Product p = null;
if (productCode.equalsIgnoreCase ( "java11 )
productCode.equalsIgnoreCase( 11 j sp" )
productCode.equalsIgnoreCase( "mysql " )) {
Book b = new Book( );
if (productCode.equalsIgnoreCase( 11 java" )) {
b.setCode(productCode);
b.setDescription( "Murach 1 s Java Programming" );
b.set Price(57.50);
b.set Author( "Joel Murach");
> else if (productCode.equalsIgnoreCase( "jsp" )) {
b.setCode(productCode );
b.setDescription( "Murach 1 s Java Servlets and JSP");
b.set Price(57.50);
b.setAuthor( "Mike Urban" );
} else if (productCode.equalsIgnoreCase( "mysql" )) {
b.setCode(productCode);
b.setDescription( "Murach 1 s MySQL" );
b.setPrice( 54.50 );
b.setAuthor( "Joel Murach");
}
p = b; // set Product object equal to the Book object
} else if (productCode.equalsIgnoreCase( "netbeans" )) {
Software s = new Softwaref);
s.setCode( "netbeans" );
s.setDescription( "NetBeans" );
s.setPrice(0.00);
s.setVersion("8.0");
p = s; // set Product object equal to the Software object
}
return p;
}
}
import java.util.Scanner;
import murach.db.ProductDB;
import murach.business.Product;
System.out .println( );
System.out .println( "Product count: " + Product .getCount ( ) + "\n");
The console
Description
• Java can implicitly cast a subclass to a superclass. As a result, you can use a
subclass whenever a reference to its superclass is called for. For example, you can
specify a Book object whenever a Product object is expected because Book is a
subclass of Product.
• You must explicitly cast a superclass object when a reference to one of its
subclasses is required. For example, you must explicitly cast a Product object to
Book if a Book object is expected. This only works if the Product object is a valid
Book object. Otherwise, this throws a ClassCastException.
• Casting affects the methods that are available from an object. For example, if you
store a Book object in a Product variable, you can’t call the setAuthor method
because it’s defined by the Book class, not the Product class.
• You can use the instanceof operator to check if an object is an instance of a
particular class.
Both variables refer to different objects that store the same data
Product product 1 = new Product ();
Product product 2 = new Product ( );
if (product 1.equals(product2 )) // expression returns false
Description
• To test if two objects variables refer to the same object, you can use the equals
method of the Object class.
• To test if two objects store the same data, you can override the equals method in the
subclass so it tests whether all instance variables in the two objects are equal.
• Many classes from the Java API (such as the String class) already override the
equals method to test for equality.
(ÿOverride
public String toStringO {
return description;
}
(ÿOverride
public String getDisplayText ( ) { // implement the abstract method
return super.toString( ) + " by n + author;
}
}
Description
• An abstract class is a class that can be inherited by other classes but that you can’t
use to create an object. To declare an abstract class, code the abstract keyword in
the class declaration.
• An abstract class can contain fields, constructors, and methods just like other
superclasses. In addition, an abstract class can contain abstract methods.
• To create an abstract method, you code the abstract keyword in the method declara¬
tion and you omit the method body. Abstract methods cannot have private access.
However, they may have protected or default access (no access modifier).
• When a subclass inherits an abstract class, all abstract methods in the abstract class
must be overridden in the subclass. Otherwise, the subclass must also be abstract.
• An abstract class doesn’t have to contain abstract methods. However, any class that
contains an abstract method must be declared as abstract.
A final class
public final class Book extends Product {
// all methods in the class are automatically final
}
A final method
public final String getVersion() {
return version;
}
A final parameter
public void setVersion( final String version) {
Description
• To prevent a class from being inherited, you can create a final class by coding the
final keyword in the class declaration.
• To prevent subclasses from overriding a method of a superclass, you can create a
final method by coding the final keyword in the method declaration. In addition, all
methods in a final class are automatically final methods.
• To prevent a method from assigning a new value to a parameter, you can code the
final keyword in the parameter declaration to create a final parameter. Then, if a
statement in the method tries to assign a new value to the parameter, the compiler
reports an error.
Perspective
Conceptually, this is one of the most difficult chapters in this book.
Although the basic idea of inheritance isn’t that difficult to understand, the
complications of polymorphism, overriding, and casting make inheritance
a difficult topic. So if you find yourself a bit confused right now, don’t be
disheartened It will become clearer as you actually use the techniques you’ve
learned here and see them used in the Java API.
The good news is that you don’t have to understand every nuance of how
inheritance works to use it. In fact, since all classes automatically inherit the
Object class, you’ve already been using inheritance without even knowing
it. Now that you’ve completed this chapter, you should have a better under¬
standing of how the Java API works. In addition, you should have a better idea
of how you can use inheritance to improve the design of your own classes.
Summary
• Inheritance lets you create a new class based on an existing class. The
existing class is called the superclass, base class, or parent class, and the
new class is called the subclass, derived class, or child class.
• A subclass inherits all of the fields and methods of its superclass that aren’t
private. The subclass can extend the superclass by adding its own fields and
methods, and it can override a method with a new version of the method.
• All classes inherit the java.lang.Object class. This class provides methods,
such as the toString and equals methods, that are available to all classes.
• You can use access modifiers to limit the accessibility of the fields and
methods declared by a class. Protected members can be accessed only by
classes in the same package or by subclasses.
• An annotation is a standard way to provide information about your code
to other software tools and developers. When you override a method, it’s
generally considered a good practice to add the ©Override annotation to the
method.
• In a subclass, you can use the super keyword to access the fields, construc¬
tors, and methods of the superclass.
• Polymorphism is a feature of inheritance that lets you treat subclasses as
though they were their superclass.
• Java can implicitly cast a subclass type to its superclass type, but you must
use explicit casting to cast a superclass type to a subclass type.
• You can use the instanceof operator to check if an object is an instance of a
particular class.
• Abstract classes can be inherited by other classes but can’t be used to create
an object. Abstract classes can include abstract methods.
Chapter 11 How to work with inheritance 303
• If you extend an abstract class, you must implement all abstract methods.
Otherwise, you must also declare your class as abstract.
• You can use the final keyword to declare final classes, final methods, and
final parameters. No class can inherit a final class, no method can override a
final method, and no statement can assign a new value to a final parameter.
3. Open the Product class, and add an equals method as shown in this chapter.
Then, run the project again. This time, the output should indicate that the
products are being compared based on their data like this:
4. Repeat step 3 for the Lineltem class. This time, the comparisons for both the
products and line items should be based on their data like this:
12
How to work
with interfaces
Interlaces are similar to abstract classes* However, they have several advantages
that make them easier to create and more flexible to use*
The lava API defines hundreds of interlaces* Many classes in the Java API
use these interfaces* You can use interlaces from the Java API in your own
applications. In addition, you can create and use your own interfaces.
An introduction to interfaces
In some object-oriented programming languages, such as C++, a class can
inherit more than one class. This is known as multiple inheritance. Although
Java doesn’t support multiple inheritance, it does support a special type of
coding element known as an interface. An interlace provides many of the advan¬
tages of multiple inheritance without some of the problems that are associated
with it.
A simple interface
Figure 12-1 illustrates how you create and use an interface. Here, the first
example shows the code for a simple interface named Printable. This code is
similar to the code that defines a class and is stored in a file named Printable.
java. However, the code for an interface uses the interface keyword instead of the
class keyword. In addition, all of the methods in an interface are automatically
public and abstract. As a result, you don’t need to code the public or abstract
keywords for the methods in an interface.
The second example shows a Product class that implements the Printable
interface. To implement the Printable interface, the declaration for the Product
class uses the implements keyword followed by the name of the interface. Then,
the body of the Product class implements the print method that’s specified by the
Printable interface.
The third example shows that a Product object that implements the Printable
interface can be stored in a variable of the Printable type. In other words, an
object created from the Product class shown in this figure is both a Product
object and a Printable object. As a result, you can use this object anywhere a
Printable object is expected as shown later in this chapter.
Chapter 12 How to work with interfaces 309
Resulting output
Description
• An interface can define one or more methods. These methods are automatically
public and abstract. As a result, the interface only specifies the method signatures,
not any code that implements the methods.
• A class that implements an interface can use any constants defined by the interface.
In addition, it must provide an implementation for each abstract method defined by
the interface. If it doesn’t, it must be declared as abstract.
A Printable interface
public interface Printable {
void print ( );
}
Advantages of an interface
• A class can only directly inherit one other class, but a class can implement multiple
interlaces.
Description
• A default method of an interface works much like a regular (non-static) method of
a class.
Although this makes it clear where the constant is stored, it also takes more
code. As a result, most programmers typically omit the interface name when
referring to constants.
Even if a class doesn’t implement an interface, you can still use any of the
constants defined by that interface. However, in that case, you must qualify the
constant with the name of the interface as shown above.
Chapter 12 How to work with interfaces 315
(ÿOverride
public void print ( ) {
String dept = "Unknown";
if (department == ADMIN) {
dept = "Administration";
> else if (department == EDITORIAL) {
dept = "Editorial";
} else if (department == MARKETING) {
dept = "Marketing";
}
Description
• To declare a class that implements an interlace, you use the implements keyword.
Then, you provide an implementation for each method defined by the interface.
• If you forget to implement a method that’s defined by an interface that you’re
implementing, the compiler will issue an error message.
• A class that implements an interface can use any constant defined by that interface.
(ÿOverride
public void print ( ) { // implement the Printable interface
System.out .println( super.getDescription( ) + " by " + author);
}
}
Description
• A class can inherit another class and also implement one or more interfaces.
• If a class inherits another class that implements an interface, the subclass automati¬
cally implements the interface. However, you can code the implements keyword in
the subclass for clarity.
• If a class inherits another class that implements an interface, the subclass has access
to any methods of the interface that are implemented by the superclass and can
override those methods.
Resulting output
Resulting output
Description
• You can declare a parameter that’s used by a method as an interface type. Then, you
can pass any object that implements the interface to the parameter.
• You can also declare a variable as an interface type. Then, you can assign an instance
of any object that implements the interface to the variable, and you can pass the
variable as an argument to a method that accepts the interface type.
A ProductReader interface
public interface ProductReader {
Product getProduct ( String code);
String getProducts( );
}
A ProductWriter interface
public interface ProductWriter {
boolean add(Product p);
boolean update(Product p);
boolean delete(Product p);
}
A ProductConstants interface
public interface ProductConstants {
int CODE_SIZE = 10;
int DESCRIPTION_SIZE = 34;
int PRICE_SIZE = 10;
>
A ProductDAO interface that inherits these three interfaces
public interface ProductDAO extends ProductReader, ProductWriter,
ProductConstants {
// all methods and constants are inherited
}
Description
• An interface can inherit one or more other interfaces by specifying the inherited
interfaces in an extends clause.
• An interface can’t inherit a class.
• A class that implements an interface must implement all abstract methods declared
by the interface as well as all abstract methods declared by any inherited interfaces
unless the class is defined as abstract.
• A class that implements an interface can use any of the constants declared in the
interface as well as any constants declared by any inherited interfaces.
Description
• With Java 8 and later, you can add regular (non-abstract) methods to an interface.
These methods are known as default methods.
• To add a regular method to an interface, you can begin the declaration for the
method with the default keyword.
• When you code a class that implements an interface, you don’t need to implement
its default methods. Instead, you can use the default methods defined in the inter¬
lace in your class. However, if you want to change the functionality of a default
method, you can override it.
Description
• With Java 8 and later, you can include static methods in interlaces.
• To call a static method from an interface, prefix the static method with the name of
the interface.
The console
Figure 12-10 shows the console for the Product Viewer application. From
the user’s perspective, this application works the same as earlier versions of the
Product Viewer application. In short, it allows the user to enter a product code.
Then, it displays the details of the product with the specified code.
The console
import murach.business.Product;
import murach.business.Product;
(ÿOverride
public Product getProduct ( String productCode) {
Product product = new Product ( );
product.setCode(productCode );
if (productCode.equalsIgnoreCase( "java" )) {
product.setBescription( "Murach 1 s Java Programming" );
product.setPrice(57.50);
} else if (productCode.equalsIgnoreCase( "jsp" )) {
product.setBescription( "Murach 1 s Java Servlets and JSP");
product.setPrice(57.50);
} else if (productCode.equalsIgnoreCase( "mysql" )) {
product.setBescription( "Murach 1 s MySQL" );
product.setPrice(54.50);
} else {
product.setBescription( "Unknown" );
}
return product;
}
(ÿOverride
public String getProducts( ) {
return "This method hasn't been implemented yet.";
}
import java.util.Scanner;
import murach.business.Product;
import murach.db.ProductDB;
import murach.db.ProductReader;
Perspective
In this chapter, you’ve learned how to use interlaces and how they can
be used to improve the design of an application. That means that you should
now be able to implement all types of classes that are commonly used in
business applications. In the next chapter, though, you’ll learn some additional
object-oriented skills that will round out your knowledge of object-oriented
programming.
Summary
• An interface is a special type of coding element that can contain static
constants and abstract methods.
• With Java 8 and later, an interface can also contain regular methods, known
as default methods, and static methods.
• A class can only inherit one other class, but it can implement more than one
interface.
• To implement an interface, a class must implement all the abstract methods
defined by the interface.
• An interface can inherit other interfaces. Then, the implementing class must
also implement all the abstract methods of the inherited interfaces.
• An interface defines a Java type. As a result, you can use an object that’s
created from a class that implements an interface anywhere that interface is
expected.
• A class does not have to implement default methods provided by the inter¬
face, but it can override them.
Test Button
Two AWT classes that you can use to handle a button click
Interface/Class Description
java.awt.event .ActionListener An interface that defines the method that contains the
code that’s executed when a user clicks a button.
java.awt.event ActionEvent
- A class that defines an object that contains information
about an event such as the event that occurs when a
user clicks a button.
Description
• Most modern applications use a GUI (graphical user interface) that displays
windows and components, such as buttons, to interact with the user.
• Swing is the most common Java library for creating GUIs. Its classes are stored in
the javax.swing package.
• With Swing, a window is also known as a frame.
• When you write code Tor a GUI, you can handle events that occur on it. For
example, you can handle the event that occurs when a user clicks on a button. To
do that, you typically code an event listener that contains the code that’s executed
when an event occurs.
• To handle events, Swing uses interfaces and classes from another Java library, the
AWT ( Abstract Window Toolkit). This library is stored in the java.awt package.
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public TestFrame( ) {
// code that sets up the frame
this.setTitle( "Test Frame" );
this.setSize(400, 100);
this.setLocationByPlatf orm(true );
this.setDef aultCloseOperation(JFrame.EXIT_ON_CLOSE);
Description
• An inner class is a class that’s coded within another class.
Description
• An anonymous class is a type of inner class that doesn’t have a name.
• You can code the braces for an anonymous class immediately after the parentheses
that attempt to create an object from an interface.
• Within the braces for an anonymous class, you can supply the code that implements
the interface.
• If you want to use the object that’s created from the inner class more than once, you
can assign that object to a variable.
Description
• An enumeration contains a set of related constants. The constants are defined
with the int type and are assigned values from 0 to the number of constants in the
enumeration minus 1.
• An enumeration defines a type. Because of that, you can’t specify another type
where an enumeration type is expected That means that enumerations are type-safe.
(ÿOverride
public String toString() {
String s = "";
if (ordinal() == 0) {
s = "UPS Next Day (1 business day)";
} else if (this.ordinal ( ) == 1) {
s = "UPS Second Day (2 business days)";
} else if (this.ordinal ( ) == 2) {
s = "UPS Ground (5 to 7 business days)";
}
return s;
}
}
Resulting output
Description
• All enumerations inherit the java.lang.Object and java.lang.Enum classes and can
use or override the methods of those classes or add new methods.
• By default, the toString method of an enumeration constant returns the same string
as the name method.
• You can use a static import to import all of the constants of an enumeration or all of
the static fields and methods of a class.
Figure 13-5 How to enhance an enumeration and work with static imports
344 Section 3 Object-oriented programming skills
/ **
* The Product class represents a product and is used by
* the Lineltem and ProductBB classes.
*/
public class Product {
I **
* Creates a new Product with default values.
*/
public Product ( ) {
code = nn;
description =
price = 0;
}
I **
* Sets the product code to the specified String.
*/
public void setCode( String code) {
this.code = code;
}
I **
* Returns a String that represents the product code.
*/
public String getCode( ) {
return code;
}
Description
• A javadoc comment begins with /** and ends with */, and asterisks within the
comment are ignored. You can use javadoc comments to describe a class and its
public and protected fields, constructors, and methods.
• A comment should be placed immediately above the class or member it describes.
For a class, that means that the comment must be placed after any import
statements.
• If you enter a slash (/) followed by two or more asterisks on a blank line before
the code for a class, field, constructor, or method in NetBeans, NetBeans generates
beginning javadoc comments. That includes comments with some of the javadoc
tags you’ll learn about in the next figure.
The Product class with comments that use HTML and javadoc tags
package murach.business;
/ **
* The < code > Product </ code > class defines a product and is used
* by the <code>LineItem</code> and <code>ProductDB</code> classes.
* ©author Joel Murach
* ©version 1.0.0
*/
public class Product {
private String code;
private String description;
private double price;
I **
* Creates a <code>Product</code> with default values.
*/
public Product ( ) {
code = " 11;
description =
price = 0;
}
/ **
* Sets the product code.
* ©param code A <code>String</code> for the product code.
*/
public void setCode( String code) {
this.code = code;
}
I **
* Gets the product code.
* ©return A <code>String</code> for the product code.
*/
public String getCode( ) {
return code;
}
Figure 13-7 Flow to use FITML and javadoc tags in javadoc comments
348 Section 3 Object-oriented programming skills
Here, I selected the murach.business package from the upper left frame.
When I did that, the two classes in that package were listed in the lower left
frame. Then, when I selected the Product class, the documentation for that class
was displayed in the right frame.
The documentation for the Product class indicates that the Product class
is in the murach.business package. It also includes a brief description of the
Product class, which was generated from the javadoc comment for the class.
Next, it provides a summary of the constructors and methods of the class that
are available to other classes, along with the descriptions I provided. If this class
contained public or protected fields, the documentation would also include a
summary of those fields. Finally, the documentation includes details of all the
fields, constructors, and methods in the summaries. This is where you’ll see any
information provided with ©param and ©return tags.
Note that the documentation doesn’t expose the code that is encapsulated
within the class. As a result, the documentation makes it easy for other program¬
mers to use your classes without knowing the details of how they’re coded.
Chapter 13 How to work with inner classes, enumerations, and documentation 349
C D file:///t:/murach/javajietbeans/book_apps/chl3JjneItern/dist/javadoc/mdex.htm
All Classes OVERVIEW PACKAGE USE TREE DEPRECATED INDEX HELP
Packages
PREV CLASS NEXT CLASS FRAMES NO FRAMES
murach. business SUMMARY: NESTED | FIELD | CONSTR | METHOD DETAIL: FIELD | CONSTR | METHOD
murach.db
murach. ui murach.business
Class Product
java. lang.Object
murach.business.Product
murach. business
public class Product
Classes extends java .lang .Object
Lineltem
The Product class defines a product and is used by the Lineltem and ProductDB
Product
classes.
Constructor Summary
Product ( )
Creates a Product with default values.
Method Summary
Description
• To generate or view the documentation lor a project from NetBeans, you can
right-click on the project in the Projects window and select the “Generate Javadoc”
command. When you do, NetBeans generates the Java documentation for the
project and displays it in the default web browser.
• By default, NetBeans stores the documentation for a project in a subfolder named
dist/javadoc that’s in the project’s root folder. This folder contains an index.html
file that you can double-click to view the documentation.
• If the project already contains documentation, NetBeans overwrites existing files
without any warning.
Figure 13-8 How to generate and view the documentation for a package
350 Section 3 Object-oriented programming skills
Perspective
Now that you’ve finished this chapter, you should understand the concepts
for working with inner classes. You should be able to create and work with
enumerations. And you should be able to document your classes so other
programmers can use them. At this point, you have all of the object-oriented
programming skills you need to learn about more of the classes that are
available from the Java API such as the collection classes described in the
next chapter. In addition, you have a solid foundation for working with GUI
programming as described at the end of this book.
Summary
• An inner class is a class that’s coded within another class. This is useful
when a class only makes sense within the context of another class.
• An anonymous class is a type of inner class that doesn’t have a name. This
often results in more concise code than an inner class that has a name.
• You can use an enumeration to define a set of related constants as a type.
Then, you can use the constants in the enumeration anywhere the enumera¬
tion is allowed.
• You can use static imports to import the constants of an enumeration or the
static fields and methods of a class. Then, you can refer to the constants,
fields, and methods without qualification.
• You can use javadoc comments to document a class and its fields, construc¬
tors, and methods. Then, you can generate HTML-based documentation for
your class.
Chapter 13 How to work with inner classes, enumerations, and documentation 351
Create an enumeration
1. Open the project named ch 1 3_ex2_Enumeration that’s in the ex_starts folder.
2. Create an enumeration named CustomerType. This enumeration should
contain constants that represent three types of customers: retail, trade, and
college.
Use an enumeration
3. Open the CustomerType App class. Then, add a method to this class that
returns a discount percent (. 10 for retail, .30 for trade, and .20 for college)
depending on the CustomerType variable that’s passed to it.
4. Add code to the main method that declares a CustomerType variable, assigns
one of the customer types to it, gets the discount percent for that customer
type, and displays the discount percent. It should display a message like this
to the console:
S. Run the application again to view the results of the toString method.
Chapter 13 How to work with inner classes, enumerations, and documentation 353
Description
• A collection is an object that can hold other objects. Collections are similar to
arrays, but are more flexible to use.
• With Java 5 and later, collections use a feature known as autoboxing to automati¬
cally add and remove the wrapper classes for primitive types whenever necessary.
Collection interfaces
Interface Description
Collection Defines the basic methods available for all collections.
Set Defines a collection that does not allow duplicate elements.
List Defines a collection that maintains the sequence of elements in the list. It accesses
elements by their integer index and typically allows duplicate elements.
Map Defines a map. A map is similar to a collection. However, it holds one or more
key-value pairs instead of storing only values (elements). Each key-value pair
consists of a key that uniquely identifies the value, and a value that stores the data.
Description
• The Java collection framework is interface based, which means that each class
in the collection framework implements one of the interfaces defined by the
framework.
• The collection framework consists of two class hierarchies: Collection and Map. A
collection stores individual objects as elements. A map stores key -value pairs where
you can use a key to retrieve a value (element).
An introduction to generics
Prior to Java 5, the elements of a collection were defined as the Object type.
As a result, you could store any type of object as an element in a collection. At
first, this flexibility might seem like an advantage. But with it comes two disad¬
vantages. First, there’s no way to guarantee that only objects of a certain type are
added to a collection. For example, you can’t limit an ArrayList so it can hold
only Product objects. Second, you must use casting whenever you retrieve an
object from a collection. That’s because an element can be any type of object.
For example, to retrieve a Product object from a collection, you must cast the
object to the Product type.
Java 5 introduced a new feature called generics that addresses these two
problems. The generics feature lets you specify the element type for a collection.
Then, Java can make sure that it only adds objects of the specified type to the
collection. Conversely, Java can automatically cast any objects you retrieve from
the collection to the correct type.
Figure 14-3 shows how the generics feature works. To specify a type when
you declare a collection, you code the type in angle brackets immediately
following the name of the collection class (such as ArrayList or LinkedList).
Prior to Java 7, you had to do this twice: once when you use the collection class
to declare the collection, and again when you use the constructor of the collec¬
tion class to create an instance of the collection. However, Java 7 introduced
a feature that lets you simplify this code as shown by the last example in this
figure.
The first example shows a statement that declares and instantiates an
instance of an array list collection named codes that holds String objects. Here,
<String> is specified following the ArrayList class name to indicate that the
elements of the array list must be String objects.
The second and third examples are similar, but they create collections that
can hold integers and Product objects. Here, the second example uses a wrapper
class (the Integer class) instead of the primitive type (the int type). This allows
the collection to store an array of integer values. That’s necessary because it’s
illegal to declare a collection with a primitive type like this:
ArrayList<int > numbers = new ArrayList<int > ( ); // illegal!
If you’re using Java 7 or later, you can omit the type from the brackets
that follow the constructor as long as the compiler can infer the type from the
context. The fourth example shows how this works. Here, the code accomplishes
the same task as the first example but without duplicating the collection type.
Since this feature results in shorter and simpler code, it’s used throughout the
rest of this chapter.
Chapter 14 How to work with collections, generics, and lambdas 363
Description
• Generics refers to a feature that lets you create typed collections. A typed collection
is a collection that can hold only objects of a certain type. This feature was intro¬
duced with Java 5.
• To declare a variable that refers to a typed collection, you list the type in angle
brackets (<>) following the name of the collection class.
• When you use a constructor for a typed collection, you can specify the type
variable in angle brackets following the constructor name. The type variable can’t
be a primitive type such as int or double, but it can be a wrapper class such as
Integer or Double. It can also be a user-defined class such as Product.
• Beginning with Java 7, you can omit the type from within the brackets that follow
the constructor if the compiler can infer the type from the context. This empty set
of brackets is known as the diamond operator.
• If you do not specify a type for a collection, the collection can hold any type of
object. However, the Java compiler will issue warning messages whenever you
access the collection to warn you that type checking can’t be performed for the
collection.
Description
• The ArrayList class uses an array internally to store the elements in the list.
• The capacity of an array list automatically increases whenever necessary.
• When you create an array list, you can use the default starting capacity of 10
elements, or you can specify the starting capacity.
• If you know the number of elements that your list needs to be able to store, you can
improve the performance of the ArrayList class by specifying a starting capacity
that’s just over that number of elements.
Resulting output
Resulting output
Description
• You can use the methods of the ArrayList class to add elements to an array list and
to get elements from an array list.
Figure 14-5 How to add and get the elements of an array list
368 Section 4 More essential skills as you need them
m/
Resulting output
Resulting output
Resulting output
Description
• You can use the methods of the ArrayList class to replace, remove, and search the
elements of an array list.
Figure 14-6 How to replace, remove, and search the elements of an array list
370 Section 4 More essential skills as you need them
m/
Resulting output
Resulting output
Description
• All primitive types have corresponding wrapper classes. For example, the Integer
class is the wrapper class for the int type, the Double class is the wrapper class for
the double type, and so on.
• To store a primitive type in a collection, you can specify its wrapper class as the
type for the collection. Then, the compiler automatically converts the primitive
value to its wrapper type when adding values to the collection. This feature is
known as autoboxing.
• To get a primitive type from a collection, you don’t need to do anything because the
compiler automatically gets the primitive value from the wrapper class for you.
The console
Description
• This application allows you to enter one or more line items Tor the invoice. When
you’re done, it displays all of the line items that you entered. In addition, it displays
the total amount for the invoice.
• To enter a line item, enter the product code and quantity for the line item. Then,
you can enter “y” to enter another line item, or you and enter “n” to complete the
invoice.
// the constructor
public Invoice() {
lineltems = new ArrayListo();
}
An introduction to lambdas
In the previous chapter, you learned how to use an anonymous class to
implement a method that contains the code that’s executed when an event occurs.
Then, you learned how to pass this anonymous class to another method as a
parameter. Lambda expressions allow you to do something similar, but with a
much cleaner syntax. In particular, lambda expressions allow you to specify
the code that’s executed without having to create the anonymous class and its
method to store this code. In other words, lambda expressions allow you to store
functionality of a method and pass it to another method as a parameter.
This ability to treat functionality as if it were data can result in the benefits
listed in figure 14-1 1 . It can allow you to write methods that are more flexible.
This can greatly reduce code duplication, which can make your code easier to
maintain.
However, lambda expressions do have some drawbacks as summarized in
this figure. As a result, you might not always want to use them. Most of these
drawbacks stem from the fact that the Java virtual machine doesn’t support
lambdas. Instead, the Java compiler rewrites lambdas into “normal” Java code.
This rewriting by the compiler results in three drawbacks. First, lambda
expressions can be difficult to debug because you can’t step through them with
the debugger like normal methods. Second, when a lambda throws an exception,
the stack trace can be difficult to understand. Third, methods that use lambdas
can sometimes be inefficient compared to methods that accomplish the same task
without using lambdas.
A fourth drawback is that lambda expressions can result in code that’s
confusing and difficult to maintain. This is especially true if you use lambda
expressions in situations where they aren’t necessary.
So, when should you avoid using a lambda expression? If you find yourself
needing to perform the same task more than once, you probably want to avoid
using a lambda expression. In that case, you probably want to store the code in a
normal method so that it is reusable.
Chapter 14 How to work with collections; generics; anrf lambdas 379
Lambdas expressions...
• Are anonymous functions that can be passed as arguments to methods.
• Allow you to treat functions like data.
Description
• Like a method, a function has parameters and returns a value. An anonymous
function is a function that doesn’t have a name.
The output
Description
• The filterContactsWithoutPhone method accepts a list of Contact objects, finds all
the contacts in the list that have a null phone number, adds these contacts to a new
list, and returns this list to the caller.
• In the filterContactsWithoutPhone method, the code that filters the list is hard-coded.
As a result, this method is inflexible and fragile.
A functional interface
public interface TestContact {
boolean test (Contact c);
}
Description
• Afunctional intetface can only contain one method.
• A method can specify a functional interface as the type for a parameter. Then,
within the method, you can call the method of the functional interface from the
parameter.
• You can pass a lambda expression to a method that accepts a functional interface
as a parameter. To code a lambda expression, you code the variable name, followed
by the lambda operator (->), followed by an anonymous function. The anonymous
function can use the variable name to call methods from the object type that’s used
by the method.
Description
• The Predicate interface is a functional interface that’s available from the java. util.
function package.
• The Predicate interface uses generics to specify the type of object that’s passed to
its test method
Perspective
Now that you’ve finished this chapter, you should know how to work with
array lists, one of the most commonly used Java collections. This includes
knowing how to use generics to specify the type of object that’s stored by
a collection. This is a good foundation for learning how to work with other
collections.
You should also understand that many collections are available from the
Java API. Each of these collections provides functionality that’s useful in
certain situations. As a result, if the collections presented in this chapter don’t
provide the functionality that your application requires, there’s a good chance
that the Java API already includes a collection that does provide this function¬
ality. To find that collection and to learn how it works, you can start by looking
in the documentation for the java, util package or by searching the Internet.
Finally, you should have a general idea of how lambda expressions work.
As you might expect, there’s plenty more to learn about lambda expressions. To
do that, you can search the Internet for a tutorial or get a more advanced book
about Java programming.
Summary
• A collection is an object that’s designed to store other objects.
• The most commonly used collection class is the ArrayList class. An array
list uses an array internally to store its data.
• The generics feature, which became available with Java 5, lets you specify
the type of elements a collection can store. This feature also lets you create
generic classes that work with variable data types.
• The diamond operator, which became available with Java 7, allows you to
code an empty set of brackets (<>) in the constructor of a typed collection
instead of having to code the type within those brackets.
• A functional interface is an interface that only contains one method.
• A lambda expression (also known as an anonymous function) can be passed
as an argument to a method that accepts a functional interface as a param¬
eter. This allows you to treat functions like data.
Chapter 14 How to work with collections, generics, and lambdas 387
1. Open the project named chl4_exl_Future Value in the ex_starts folder. Then,
review the code for this application and run it to make sure it works correctly.
2. Declare a variable at the beginning of the main method for an array list that
stores strings.
3. After the code that calculates, formats, and displays the results for each
calculation, add code that formats a string with the results of the calculation
and then stores the string in the array list.
4. Add code to print the elements in the array list to the console when the user
exits the application. Then, test the application by making at least 3 future
value calculations.
388 Section 4 More essential skills as you need them
m/
Pros
- Works with older versions of Java.
Cons
- Not thread-safe.
- Not intuitive.
- Not easy to localize for parts of the world that don’t use the Gregorian calendar.
Pros
- Thread-sale.
- Intuitive.
- Easier to localize for parts of the world that don’t use the Gregorian calendar.
Cons
- Doesn’t work with versions of Java prior to Java 8.
Description
• Java 8 introduces a new date/time API that fixes some of the problems with the old
date/time API that was used prior to Java 8,
Description
• These classes represent the local date and time from the observer’s perspective.
• The LocalDateTime class is a combination of the LocalDate and LocalTime classes.
For a LocalDateTime object, you separate the strings for the date and time with a
T. This indicates the start of the time part of the string.
If any of the values are out of range, these methods typically throw a
DateTimeException. For example, if you specify a day of 32, these methods
throw this exception since no month has 32 days. Similarly, if you specify 25
hours or 61 seconds, these methods throw this exception.
All of these classes have several more static methods for creating dates and
times, but the ones presented in figure 15-2 are the most common. For more
information, you can look at the API documentation for these classes.
Description
• The LocalDateTime class supports all of the get methods.
• The LocalDate class only supports the get methods relevant to getting dates.
• The LocalTime class only supports the get methods relevant to getting times.
• LocalDate, LocalTime, and LocalDateTime objects are immutable. As a result,
these get methods do not have corresponding set methods.
Description
• You can use these methods to compare LocalTime, LocalDate, and LocalDateTime
objects.
Description
• To adjust a date/time object, you can use the with methods.
• These methods create a new object from the existing date/time object. In other
words, they don’t alter the existing date/time object.
• The LocalDateTime class supports all of the methods in the table.
• The LocalDate class only supports the methods relevant to dates.
• The LocalTime class only support the methods relevant to times.
• These methods can throw a DateTimeException for arguments that are out of range.
• The withMonth method may change the day if the current day stored in the object
is out of range for the new month.
Description
• To adjust the date or time forward or backward, you can use the plus and minus methods
with the ChronoUnit enumeration to specify a period of time. However, it’s usually
easier to use the shortcut methods such as the plusWeeks or minusWeeks methods.
• Shortcut methods exist for all of the ChronoUnit constants shown in this figure.
• The LocalDateTime class supports all of the methods and ChronoUnit constants.
The LocalDate and LocalTime classes only support the methods and constants that
are relevant to them.
• All of the plus and minus methods return new objects of the same type. In other
words, they do not alter the existing objects.
• You can use method chaining to perform multiple calculations in a single statement.
Code that uses the same style to format both the date and time
DateTimeFormatter dtf = DateTimeFormatter.of Local izedDateTime(
Format Style.MEDIUM);
String currentDateTimeFormatted = dtf.format (currentDateTime);
Code that uses a separate style for the date and time
DateTimeFormatter dtf = DateTimeFormatter.of Local izedDateTime(
FormatStyle.LONG, FormatStyle.SHORT);
String currentDateTimeFormatted = dtf.format (currentDateTime);
Description
• You can use the ofLocalized methods to format a date and time for the locale of the
system that the application is running on.
• You can use the FormatStyle constants to specify the format style for the date and time.
• If you attempt to use the LONG or FULL style to format a time, the compiler
throws a DateTimeException.
• If none of the formats included with the API meets your needs, you can write your
own custom formatters.
public Invoice ( ) {
lineltems = new ArrayListo();
invoiceDate = LocalDateTime.now();
}
Perspective
Now that you’ve finished this chapter, you should understand some of the
differences between the old date/time API that was available prior to Java 8 and
the new date/time API that’s available with Java 8 and later. In addition, you
should be able to use the classes provided by the new date/time API to work
with dates and times.
Summary
• Prior to Java 8, it was common to use classes in the java, util and java.text
packages to work with and format dates and times.
• With Java 8 or later, you can use the classes in the java.time package to work
with and format dates and times. This package has several advantages over
the older classes for working with dates and times.
An introduction to exceptions
All applications can encounter errors when they run. For example, a user
may enter data that’s not appropriate, or a file that your application needs may
get moved or deleted. These types of errors may cause a poorly-coded applica¬
tion to crash and cause the user to lose data. In contrast, when an error occurs in
a well-coded application, the application notifies the user and attempts to recover
from the error. If it can’t recover, it saves as much data as possible, cleans up
resources, and exits the application as smoothly as possible.
In the old days of programming, this was rather difficult to do because
programming languages had no easy way to check for errors. Even worse, they
had no easy way to communicate those errors to other parts of the application
that might need to know about them. To address this problem, most modern
programming languages, including Java, support an error handling mechanism
known as exceptions. Exceptions allow you to write robust code that can handle
errors more easily and reliably. Before you learn how to handle errors, though,
you need to learn about the exception hierarchy and the exception handling
mechanism.
Description
• An exception is an object of the Exception class or any of its subclasses. It repre¬
sents a condition that prevents a method from successfully completing.
• The Exception class is derived from a class named Throwable. Two types of excep¬
tions are derived from the Exception class: checked exceptions and unchecked
exceptions.
• Checked exceptions are checked by the compiler. As a result, you must write code
that handles all checked exceptions before you can compile your code.
• Unchecked exceptions are not checked by the compiler, but they can occur at
runtime. It’s generally considered a good practice to write code that handles
unchecked exceptions. If an unchecked exception occurs and isn’t handled by your
code, your application terminates.
• Like the Exception class, the Error class is also derived from the Throwable class.
However, the Error class identifies internal errors that are rare and can’t usually be
recovered from. As a result, you can usually ignore the Error class.
Description
• When a method encounters a condition it can’t handle, that method should throw an
exception. This allows users of the method to handle the exception in a way that’s
appropriate for their applications. Many methods in the Java API throw exceptions.
• When a method calls another method that throws a checked exception, the method
must either throw the exception to its caller or catch the exception and handle it
directly. Code that catches an exception is known as an exception handler.
• When an exception occurs, the runtime system looks for the appropriate exception
handler. To do that, it looks through the stack trace, or call stack, which lists the
methods that have been called until it finds a method that catches the exception.
A method that catches two types of exceptions and uses a finally clause
public static String readFirstLine( String path) {
Buffer edReader in = null;
try {
in = new Buffer edReader(
new FileReader(path) ); // may throw FileNotFoundException
String line = in.readLine( ); // may throw IOException
return line;
} catch (FileNotFoundException e) {
System.out .println( "File not found.");
return null;
} catch( IOException e) {
System.out .println( "I/O error occurred." );
return null;
} finally {
try {
if (in != null) {
in.close(); // may throw IOException
}
} catch (Exception e) {
System.out .println( "Unable to close file.");
}
}
}
Description
• You can code a try block around any statements that may throw an exception.
• You can code one catch block lor each type of exception that may be thrown in the
try block. You should code the catch clauses in sequence from the most specific
class in the Throwable hierarchy to the least specific class.
• You can code a finally block to free any system resources that are used by objects
created in the try block. The code in the finally block is always executed.
this code checks that this object is not null before it calls its close method. In
addition, the close method may throw an 10Exception, so you need to code a try
statement within the finally block that catches this exception.
When you code try statements, it’s often tempting to create empty catch
clauses for checked exceptions j ust to get your code to compile. However, this
can make debugging difficult because if an exception is thrown, you never find
out about it. Instead, your code doesn’t work correctly and gives no indication
of what went wrong. Furthermore, it’s all too easy to forget to code the excep¬
tion handler later. In that case, the exception never gets handled. Instead, the
empty catch clause catches the exception and ignores it. This is sometimes called
swallowing an exception, or eating an exception, and it’s rarely an acceptable
coding practice.
Description
• The try-with-resources statement is a special type of try statement that declares and
instantiates one or more objects that use system resources and automatically closes
those objects and releases the resources after the try statement finishes executing.
• The try-with-resources statement was introduced with Java 7.
• Any object that implements the java.lang.AutoCloseable interface can be created
using the try-with-resources statement.
• As of Java 7, most of the classes in the Java API that use system resources have
been retrofitted to implement the AutoCloseable interface.
• If an object doesn’t implement the AutoClosable interface, NetBeans warns you if
you attempt to use try-with-resources with it. It also causes a compile-time error.
Description
• The Throwable class provides methods that are available to all exceptions.
• The System.err object works like the System.out object, but it prints data to the
standard error stream instead of the standard output stream.
• It’s generally considered a good practice to remove the printStackTrace method
from production applications or replace it with a better way of logging exceptions.
In this case, the same code is executed for lOException and all of its
subclasses, including the FileNotFoundException and EOFException.
Although this technique doesn’t provide as much flexibility as the multi-catch
block feature, it’s commonly used and works for all versions of Java.
Chapter 16 How to handle exceptions 421
Description
• The multi-catch block allows you to use a single catch block lor multiple excep¬
tions that are at the same level in the inheritance hierarchy.
• The multi-catch block was introduced with Java 7.
Description
• Any method that calls a method that throws a checked exception must either catch
the exception or throw the exception. Otherwise, the application won’t compile.
• To throw a checked exception, you code a throws clause in the method declara¬
tion. The throws clause must name each checked exception that’s thrown up to the
calling method. If you list multiple exceptions, you can separate each exception
with a comma.
• Although you can specify unchecked exceptions in the throws clause, the compiler
doesn’t force you to handle unchecked exceptions.
if (true) {
throw new lOException( "I/O exception test");
}
return firstLine;
} catch (lOException e) {
// code to handle lOException goes here
}
Description
• You use the throw statement to throw an exception. You can throw any object that’s
created from a subclass of the Throwable class.
• You can use the constructors of the Throwable class to create a new exception.
Then, you can throw that exception. To throw an existing exception, you must first
catch it.
Figure 16-8 Flow to use the throw statement
426 Section 4 More essential skills as you need them
m/
Description
• To define a checked exception, inherit the Exception class or any of its subclasses.
• To define an unchecked exception, inherit the RuntimeException class or any of its
subclasses.
• By convention, each exception class should contain a default constructor that
doesn’t accept any arguments and another constructor that accepts a string
argument.
Resulting output
Description
• Exception chaining lets you maintain exception information for exceptions that are
caught when new exceptions are thrown. Exception chaining uses the cause field,
which represents the original exception that caused the current exception to be
thrown.
Perspective
In this chapter, you learned the most important techniques for handling
exceptions in Java. Exceptions can help you write more robust, more error free
code by allowing an error to be propagated up the call stack where it can be
handled better than at the low level where the error occurred. For example, a
getProduct method that retrieves Product objects probably has no idea what
should be done if an error occurs. So this low-level method throws an exception
that’s handled by a higher-level method, which can write the exception to an
error log, display an error message, or even terminate the application. In short,
exception handling usually affects every level of an application’s design.
Summary
• In Java, an exception is an object that’s created from a class that’s derived
from the Exception class or one of its subclasses. When an exception occurs,
a well-coded application notifies its users of the exception and minimizes
any disruptions or data loss that may result from the exception.
• Exceptions derived from the RuntimeException class and its subclasses are
unchecked exceptions because they aren’t checked by the compiler. All other
exceptions are checked exceptions.
• Any method that calls a method that throws a checked exception must either
throw the exception by coding a throws clause or catch it by coding
try/catch/ finally blocks as an exception handler.
• The try-with- resources statement is a special type of try statement that
declares and instantiates one or more objects that use system resources and
automatically closes the objects and releases the resources after the try state¬
ment finishes executing.
• The multi-catch block allows you to use a single catch block for multiple
exceptions that are at the same level in the inheritance hierarchy.
• When coding your own methods, if you encounter a potential error that can’t
be handled within that method, you can code a throw statement that throws
the exception to another method. If you can’t find an appropriate exception
class in the Java API, you can code your own exception class.
• You can create custom exception classes to represent exceptions your
methods might throw. This is often useful to hide the details of how a
method is implemented.
• When you create custom exceptions, you can use exception chaining to save
information about the cause of an exception.
Chapter 16 How to handle exceptions 431
4. Run the application to make sure the finally clause works as expected. To test
what happens if the file is never opened, you can change the name of the file
to cause a FileNotFoundException. To test what happens if the close method
doesn’t work, you can throw an lOException just before the statement that
closes the resource.
Description
• To work with a directory or file, you use a Path object. A Path object can include a
root component as well as directory names and a file name.
Figure 17-1 How to work with directories and files (part 1 of 2)
436 Section 4 More essential skills as you need them
m/
Resulting output
Description
• Java 7 introduced the java.nio.file package (also known as N10.2). This package
provides an improved way to access the default file system and is designed to
replace the functionality that was available from the java.io.File class.
• The java.nio.file package provides support for many features that aren’t provided
by the java.io.File class.
• When coding paths, you can use a front slash to separate directory names. This
works equally well for Windows and other operating systems.
• To identify the name and location of a file, you can use an absolute path name to
specify the entire path for a file. You can also use a relative path name to specify
the path of the file relative to the current working directory ( CWD ). This is usually
but not always the directory that the application was started from.
• Although the java.nio.file package was introduced with Java 7, the java. nio package
was introduced with Java 4.
Figure 17-1 How to work with directories and files (part 2 of 2)
438 Section 4 More essential skills as you need them
m/
j oiSM U r CI 3 I AHC
.J products txt
[' J products.bin
Description
• An input file is a file that is read by an application. An output file is a file that is
written by an application. Input and output operations are often referred to as I/O
operations ox file I/O.
• A stream is the flow of data from one location to another, To write data to a file
from internal storage, you use an output stream. To read from a file into internal
storage, you use an input stream.
• To read and write text files, you use character streams. To read and write binary
files, you use binary streams.
• Streams are not only used with disk devices, but also with input devices like
keyboards and network connections and output devices like PC monitors and
network connections.
Figure 17-2 How files and streams work
440 Section 4 More essential skills as you need them
m/
Resulting output
Description
• The java.io package contains dozens of classes that can be used to work with
different types of streams that have different functionality.
• To get the functionality you need for a stream, you often need to combine, or layer,
two or more streams.
• To make disk processing more efficient, you can use a buffered, stream that adds a
block of internal memory called a buffer to the stream.
• When working with buffers, you often need to flush the buffer. This sends all data
in the buffer to the I/O device. One way to do that is to use a try-with-resources
statement to automatically close the I/O stream after you use it.
only one write or read operation is required to flush or fill the buffer. In contrast,
if the data is written or read one field at a time, 4000 bytes might require
hundreds of I/O operations. For each I/O operation, the disk has to rotate to the
starting disk location. Since this rotation is extremely slow relative to internal
operations, buffering dramatically improves the performance of I/O operations.
Because this figure is only intended to give you an idea of how file I/O
works, you shouldn’t worry if you don’t understand it completely. As you
progress through this chapter, you’ll learn about all of the classes and methods
shown here in more detail.
Description
• The Writer class is an abstract class that’s inherited by all of the classes in the Writer
hierarchy. To learn more about the Writer hierarchy, see the Java API documentation.
• If the output file doesn’t exist when the FileWriter object is created, it’s created automat¬
ically. If it does exist, it’s overwritten by default. If that’s not what you want, you can
specify true for the second argument of the constructor to append data to the file.
• If you specify true for the second argument of the PrintWriter constructor, the
autoflush feature flushes the buffer each time the println method is called.
Description
• To write a character representation of a data type to an output stream, you use the
print and println methods of the PrintWriter class. If you supply an object as an
argument, these methods call the toString method of the object.
• To create a delimited text file, you delimit the records or rows in the file with one
delimiter, such as a new line character, and you delimit the fields or columns of
each record with another delimiter, such as a tab character.
• To flush all data to the file, you can use a try-with-resources statement to automati¬
cally close the stream when you’re done using it. You can also use the flush or close
methods of the stream to manually flush all data to the file.
Description
• The Reader class is an abstract class that’s inherited by all of the classes in the
Reader hierarchy. To learn more about the Reader hierarchy, check the documenta¬
tion lor the Java API. All classes in the java.io package that end with Reader are
members of the Reader hierarchy.
• Although you can read files with the FileReader class alone, the BufferedReader
class improves efficiency and provides better methods for reading character input
streams.
Sample output
Sample output
import java.util.*;
import java.io.*;
import java.nio.file.*;
import murach.business.Product;
line = in.readLine();
}
>
catch(IOExcept ion e) {
System.out .print In( e );
return null;
}
}
return products;
}
The get method returns a Product object lor a product that matches the
specified product code. To search Tor the product, this method loops through
each product in the products list until it finds one with the specified product
code. Finally, it returns that product. If no product has the specified code, this
method returns a null.
The saveAll method accesses the list of products and writes all of the
Product objects to the file. If this operation is successful, it returns a true value.
If an lOException is thrown, this method returns a false value. This indicates that
the save operation wasn’t successful.
The saveAll method starts by creating a buffered output stream that connects
to the products file. Then, this method uses a loop to write each product in the
list to the file. To do that, it uses the FIELD_SEP constant to separate each field
in a product record, and it uses the println method to insert a new line character
at the end of each product record.
The add method starts by calling the add method of the List interface to add
the product to the list of products. Then, it calls the saveAll method to save the
modified list to the products file so that the list and the file contain the same data.
Here, the add method returns the boolean value that’s returned by the saveAll
method. That way, if the saveAll method returns a true value, the add method
also returns a true value.
The delete method works similarly. It starts by calling the getAll method to
return a products list. Then, it calls the remove method of the List interface to
remove the product from the list. Finally, it calls the saveAll method to save the
list to the products file, and it returns the boolean value that’s returned by that
method.
The update method works a little differently. This method updates the data
for an existing product with the data in a new Product object. To start, this
method uses the get method to get the old Product object with the same product
code as the new Product object. Then, it gets the index for the old product and
removes that product from the list. Next, it inserts the new product into the list
where the old product used to be. Finally, it calls the saveAll method to save
the list to the products file, and it returns a value that indicates whether the save
operation was successful.
It’s important to note that this class won’t work correctly for multiple
users. For example, suppose user A and user B read the products file, and user
A modifies that file. Then, suppose user B also modifies the file. At this point,
user B’s changes overwrite user A’s changes. This is known as a concurrency
problem.
One way to reduce concurrency problems would be to read the data from the
file each time the getAll, get, add, update, and delete methods are called. That
way, the data is more likely to be current. However, this would be inefficient,
particularly if the file contained thousands of records, and it still wouldn’t be
thread-safe. The easiest and most professional way to solve this problem is to
use a database as described in chapters 1 9 and 20.
Chapter 17 How to work with file I/O 455
return true;
}
return saveAll ( );
}
}
The console
Figure 17-10 shows the console for the Product Manager application. When
it starts, this application displays a welcome message and a menu of commands.
Then, it prompts the user to enter one of those commands. In this figure, for
example, the user started by entering the list command. This displayed a list of
the products that are stored in the text file.
After displaying the products, the user used the add command to add a
new product to the text file. Then, the user used the del command to delete that
product. Finally, the user entered the exit command to end the application,
The console
Welcome to the Product Manager
COMMAND MENU
list - List all products
add - Add a product
del - Delete a product
help - Show this menu
exit - Exit this application
PRODUCT LIST
java Murach 1 s Java Programming $57-50
jsp Murach's Java Servlets and JSP $57.50
mysql Murach 1 s MySQL $54.50
android Murach 1 s Android Programming $57.50
html5 Murach1 s HTML5 and CSS3 $54.50
oracle Murach1 s Oracle and PL/SQL $54.50
javascript Murach 1 s JavaScript and j Query $54.50
Bye.
Description
• This application allows you to manage the products that are stored in a text file.
When it starts, it displays a list of commands that you can use. Then, it prompts
you to enter one of these commands.
• To view the products, you can use the list command.
• To add or delete a product, you can use the add or del commands.
• To display the list of commands again, you can use the help command.
• To exit the application, you can type the exit command.
import java.util.List;
import murach.business.Product;
import murach.io.Product 10;
if (products == null) {
System.out .print In( "\nError! Unable to get products.\n" );
} else {
Product p;
StringBuilder sb = new StringBuilder( );
for (Product product : products) {
p = product;
sb.append(StringUtil.padWithSpaces(
p.getCode( ) 12 ));
#
sb.append(StringUtil.padWithSpaces(
p.get Descript ion( ) 34 ));
#
sb.append(p.getPriceFormatted ( ));
sb.append ( " \ n" );
}
System.out .println(sb.toString( ));
}
}
ProductlO.add(product );
System.out .println( "\n" + description
+ 11 was added to the database.\n" );
>
public static void deleteProduct ( ) {
String code = Console.getString( "Enter product code to delete: ");
Perspective
In this chapter, you learned how to read and write text files. In addition,
you learned how you can use a class such as the ProductIO class to store the
data for business objects such as Product objects in a text file. This should help
you see how the presentation, business, and database layers of an application
can work together.
As you work with text files, remember that they are only one option tor
storing data. Another option is to store data in a database. Because databases
provide sophisticated features for organizing and managing data, they’re used
for most serious applications. You’ll learn how to work with databases in
chapters 1 9 and 20.
If you need to read and write objects to a binary file, you may want to
consider using a Java feature known as object serialization. This feature
automates the process of reading and writing objects to a binary file. Most
programmers don’t need to write code that performs serialization unless they
are writing low-level code. For example, a programmer who is writing a Java
EE application server might use serialization to read and write objects to a
binary file. However, an application programmer who is using the application
server doesn’t need to write this code. Instead, the application programmer
only needs to provide objects that implement the Serializable interface.
Summary
• A text file stores data as characters. A binary file stores data in a binary
format.
• In a delimited text file, delimiters are used to separate the fields and records
of the file.
• You use character streams to read and write text files. To get the function¬
ality you need, you can layer two or more streams.
• A buffer is a block of memory that is used to store the data in a stream
before it is written to or after it is read from an I/O device. When an output
buffer is full, its data is flushed to the I/O device.
• When you work with I/O operations, you’ll need to catch or throw three
types of checked exceptions: 10Exception, FileNotFoundException, and
EOFException.
• To identify a file when you create a File object, you can use an absolute path
name or a relative path name.
• The java.nio.file package provides classes and interfaces that you can use to
check whether a file or directory exists, to get information about a path, to
create or delete directories and files, and to create a File object.
• You can use the classes in the Writer and Reader hierarchies to work with a
text file.
Chapter 17 How to work with file I/O 461
Here, the first line is a user-friendly message, and the second line contains
details about the exception that was thrown.
9. Run the application to make sure it works correctly.
Test the new exception handling code
1 0. In the ProductIO class, add the following code to the beginning of the getAll
method:
1 1 . Run the application and test the exception handling. At this point, you should
be able to test the exception handling for the list, add, and delete commands.
1 2. In the ProductIO class, comment out the statement that throws the lOExcep¬
tion. Then, run the application to make sure it still works correctly.
How to work with threads
When you run an application in Java, the application runs in one or more
threads. So far in this book, all of the applications have executed within a single
thread. In this chapter, you’ll learn how to develop applications that run in two
or more threads that perform separate tasks. For example, you can use one
thread to retrieve data from a database while another thread makes a compli¬
cated calculation. Then, the application can alternate between the two tasks so
it runs more efficiently.
An introduction to threads
Before you learn how to develop applications that use two or more threads,
you need to understand how threads work and when you would typically use
them. You also need to be familiar with the classes and interfaces you use when
you work with threads, and you need to understand the life cycle of a thread
That’s what you’ll learn in the topics that follow.
thread 1 task 1 (wait for I/O) task 1 (wait for I/O) task 2
time -
Two threads
Description
• A thread is a single sequential flow of control within an application. A thread often
completes a specific task.
• By default, a Java application uses a single thread, called the main thread.
However, some applications can benefit by using two or more threads to allow
different parts of the application to execute simultaneously.
• On a computer that has just one CPU (central processing unit) core, the threads
don’t actually execute simultaneously. Instead, a part of the operating system
called the thread scheduler alternately lets each thread execute. This happens faster
than humans are able to realize, thus giving the appearance that all of the tasks
are running at the same time. As a result, this can make an application work more
efficiently.
• Most modern CPUs have multiple cores and can run multiple threads at the same
time, even though there is only one CPU.
To give you some perspective on this, you should realize that the actual
amount of time that the CPU spends waiting for I/O to complete is much greater
than what’s indicated in figure 18-1. In fact, since each of the blocks that show
task 1 executing are about one half of an inch long, the blocks that show the
CPU waiting for I/O would probably need to be about the length of a football
field to show the wait time accurately. That’s about how much slower disk opera¬
tions are than CPU operations.
The second reason for using threads is to improve the responsiveness of
applications that use graphical user interfaces. For example, when a user clicks
a button, he or she expects the application to respond immediately, even if the
application is busy doing something else. A GUI application that uses Swing as
described in chapters 21 and 22 automatically runs in a thread that handles the
events that occur when the user interacts with the GUI. Then, it updates the GUI
accordingly. However, if the application needs to perform a task that may take a
long time, this task should be performed in a second thread.
The final reason for using multithreading is to allow two or more users
to run server-based applications simultaneously. For example, Java servlets
automatically create one thread for each user. (To learn more about web
programming in Java, you can read, Murach’s Java Servlets and JSP. For now,
you should just realize that each person who uses a servlet runs it in a separate
thread. As a result, when you write servlet code, you must make sure that the
code is thread-safe.)
Description
• After you create a Thread object, you can call its start method so the thread
scheduler can run the thread. Then, you can use the other methods shown above to
manage the thread.
• The advantage of implementing the Runnable interface is that it allows the thread
to inherit a class other than the Thread class.
Thread states
state Description
New The thread has been created (its constructor has been called), but not yet started,
Runnable The thread’s start method has been called and the thread is available to be run by
the thread scheduler, A thread in Runnable state may actually be running, or it
may be waiting in the thread queue for an opportunity to run.
Blocked The thread has been temporarily removed from the Runnable state so it can’t be
executed. This can happen if the thread’s sleep method is called, if the thread
is waiting on I/O, or if the thread requests a lock on an object that’s already
locked. When the condition changes (for example, the I/O operation completes),
the thread is returned to the Runnable state.
Waiting The thread is waiting and allowing other threads to access the object. It remains
in the waiting state until another thread notifies it to stop waiting and re-enter
the Runnable state.
Terminated The thread’s run method has ended,
Description
• All threads have a life cycle that can include five states: New, Runnable, Blocked,
Waiting, and Terminated.
Description
• By default, the threads that you create explicitly are named numerically. If that’s
not what you want, you can specify the name on the constructor of the thread.
• The sleep method throws an InterruptedException. Because this is a checked excep¬
tion, you must throw or catch this exception when you use the sleep method.
Sample output
Sample output
Description
• Asynchronous threads execute independently of each other. Synchronous threads
need to be coordinated if they could access the same field within a class or object at
the same time.
• Concurrency refers to a state when multiple threads use the same class or object at
the same time. Whenever this happens, concurrency problems such as lost updates
may occur.
• When you code a class that multiple threads may use, you need to make sure that
the class is thread-safe. This means that multiple threads can use it safely without
causing concurrency problems.
• The synchronized keyword locks the class or object and guarantees that only one
thread at a time can execute any of its synchronized methods. Any other thread that
attempts to run any synchronized method for the class or object is blocked until the
first thread releases the lock by exiting the synchronized method.
• A thread can run an unsynchronized method even if the class or object is locked by
a synchronized method. This can potentially cause problems if the unsynchronized
method accesses the same field that’s used by a synchronized method.
• It’s a best practice to use synchronized methods whenever two or more threads
might execute the same method, and the method accesses instance variables of the
class or object. This is true even if the method only contains one line of code.
Perspective
In this chapter, you learned the basic skills for working with threads.
Threads are a complex topic, so this chapter could only provide a very brief
introduction. Frankly, threading is one of the most challenging topics in this
book. So don’t be too worried if you don’t understand every detail of how it
works. As you learn more about different types of Java programming, such as
web programming or Android programming, you’ll learn more about working
with threads in those environments.
On that note, there’s more to learn about working with threads when
programming applications that use graphical user interfaces (GUIs). One
important concept is described later in this book at the end of chapter 22.
Summary
• A thread is a single sequential flow of control within an application that
often completes a specific task.
• A multithreaded, application consists of two or more threads whose execu¬
tion can overlap.
• A single core processor can only execute one thread at a time, and the thread
scheduler determines which thread to execute.
• Most modern processors have multiple cores and can run more than one
thread at the same time. In this case, the thread scheduler determines which
threads to run, and which core to run them on.
• Multithreading is typically used to improve the performance of applications
with I/O operations, to improve the responsiveness of GUI operations, and to
allow two or more users to run server-based applications simultaneously.
• You can create a thread by extending the Thread class and then instantiating
the new class. Or, you can implement the Runnable interface and then pass a
reference to the Runnable object to the constructor of the Thread class.
• You can use the methods of the Thread class to start a thread and to control
when a thread runs.
• The synchronized keyword on a method ensures that two or more threads
cannot run the method at the same time.
• Asynchronous threads execute independently of each other.
• Synchronized methods can be used to ensure that two threads don’t run the
same method of an object simultaneously. When a thread calls a synchro¬
nized method, the object that contains that method is locked so other threads
can’t access it.
• It’s generally considered a best practice to synchronize any methods where
there’s potential for two threads to access the same field of a class or object
at the same time.
Chapter 18 How to work with threads 479
1. Open the project named ch 1 8_ex 1 _Co unter in the ex_starts folder. Review the
code for the Main class and note that it prints a message to the console that
indicates when the main thread starts and finishes.
2. Add a class named CounterThread that extends the Thread class.
3. Add an instance variable for a starting value and a constructor that sets that
starting value like this:
private final int startingValue;
4. In the CounterThread class, add a run method that prints every other number
from the starting value to 10 to the console and displays an appropriate
message when it’s finished.
5. In the Main class, add code to create and start two instances of the Counter-
Thread class. The first should use the ODD constant to specify the starting
value, and the second should use the EVEN constant to specify the starting
value.
6. Run the application two or more times to make sure it works correctly. The
output may vary each time you run the application.
7. Depending on the speed of your system, it’s possible that one thread will
finish running before the thread scheduler switches threads. In that case, it
may look like the two threads are running in sequence rather than in parallel.
480 Section 4 More essential skills as you need them
m/
8. Add a Thread,sleep call to CounterThread to make the thread sleep for one
second between each number. See if this changes the order of the output when
you run the application.
9. Run the application two or more times to make sure it works correctly, The
output may vary each time you run the application.
Real-world skills
For most Java applications in the real world, the critical data is stored in
a database. In most cases, this provides many advantages over storing
the data in a file as described in chapter 1 7. That’s why the first two
chapters in this section present the essential database skills that you need
lor developing Java applications. In particular, they describe the essential
database skills that you need to develop the Product Manager application
that’s presented throughout this section.
In addition, most desktop Java applications use a graphical user
interlace (GUI) to interact with the user. That’s why the third and fourth
chapters in this section show how to create a GUI. In particular, they
describe the essential skills you need to create the GUI for the Product
Manager application.
19
How to work
with a MySQL database
You can use Java to work with almost any type of database. For desktop or web
applications, it’s common to use an Oracle or MySQL database. For Android
apps, it’s common to use a SQLite database. The database you end up using
depends on many factors.
Of these databases, MySQL is one of the most popular for Java applica¬
tions. In addition, there’s an open-source version that’s free, easy to install,
and easy to use. As a result, this chapter shows how to create a MySQL
database that can store the data for the Product Manager application that’s
described in the next few chapters. As you learn this, you will also learn some
basic concepts and SQL (Structured Query Language) skills that apply to all
databases.
Description
• A relational database uses tables to store and manipulate data. Each table contains
one or more records, or rows, that contain the data for a single entry. Each row
contains one or more fields, or columns, with each column representing a single
item o f data.
• Most tables contain a primary key that uniquely identifies each row in the table.
• The software that manages a relational database is called a database management
system (DBMS). Four popular database management systems today are Oracle,
Microsoft SQL Server, IBM’s DB2, and MySQL.
Foreign key
Description
• The tables in a relational database are related to each other through their key
columns. For example, the ProductID column is used to relate the Product and
Lineltem tables. The ProductID column in the Lineltem table is called a foreign key
because it identifies a related row in the Product table.
• Three types of relationships can exist between tables. The most common type is a
one-to-many relationship as illustrated above. However, two tables can also have a
one-to-one relationship or a many-to-many relationship.
Description
• A database management system requires a name and data type for each column in a
table. Depending on the data type, the column definition can include other proper¬
ties such as the column’s size.
• Each column definition also specifies whether or not the column can contain a null.
A null indicates that the value of the column is not known.
• A column definition can specify that the column is the primary key. A primary key
column can’t be null.
• A column definition can specify that the column must contain a unique value. A
unique column can be null. However, if this column is not null, it must contain a
unique value.
An introduction to MySQL
MySQL is an open-source database management system (DBMS) that you
can download for free from the MySQL website (www.mysql.com) as described
in the appendixes. It is also available as part of a hosting package from many
Internet Service Providers (ISPs). MySQL Workbench is a free graphical tool
that makes it easy to work with MySQL. As of press time for this book, the
current version of MySQL Workbench is version 6.3, so that’s the version
presented in this chapter. However, with some minor variations, the skills
presented in this chapter should work for earlier and later versions as well.
MySQL is...
• Inexpensive. MySQL is Tree for most uses and relatively inexpensive for other
uses.
• Fast. By many accounts, MySQL is one of the fastest relational databases that’s
currently available.
• Easy to use. Compared to other database management systems, MySQL is easy to
install and use.
• Portable. MySQL runs on most modern operating systems including Windows, OS
X, and Linux.
MySQL provides...
• Support for SQL. Like any modern database product, MySQL supports SQL,
which is the standard language for working with data that’s stored in relational
databases.
• Support for multiple clients. MySQL supports access from multiple clients from a
variety of interfaces and programming languages including Java, PHP, Python, Perl,
and C.
• Connectivity. MySQL can provide access to data via an intranet or the Internet.
• Security. MySQL can protect access to your data so only authorized users can view
the data.
• Referential integrity. With MySQL 5.5 and later, lnnoDB tables are used by
default. These tables support referential integrity, which reduces the chance of data
corruption. Most commercial databases also provide this feature.
• Transaction processing. With version 5.5, MySQL uses lnnoDB tables by default.
These tables provide support for transaction processing, which reduces the chance
of data corruption. Most commercial databases also provide this feature.
MySQL Workbench
9 MySQL Workbench B MM
4b Local instance MySQLSG X
File Edit View Query Database Server Tools Scripting Help
©a o ©si©©© m&
SCHEMAS H t? S ! f3 Limit to 1000 raws mi M
Filter ob l • select * fro# Product
mma
Tables
T H product
▼ fe»l Columns
♦ ProductID
♦ Code
♦ Description
♦ ListPrice
► Indexes
► ® Foreign Keys
Result Grid | Filter Rows: Edit: Export/Import: y & I Wrap Cd Content: JT
► Triggers
Views ProductID Code Description ListPrice
® Stored Procedures 1 java Murachs Java Programming S7.50
Functions Wj'ach s Java
2 jsp Servlets and JSP 57.50
muradi
murachjpa 3 mysq|l Murachs MySQL 54.50
musk 4 android Murach s Aneroid Programming 57.50
muskjpa
my_guitar_shop 5 htmlS Murachs HTML 5 and CSS3 54.50
[5 Action Output *
O 1 09:54:35 select ‘from Product LIMIT 0. 1000 7 row(s) returned 0.000 sec / 0.000 sec
Object Info
Description
• When working with a desktop application, it’s common to use a GUI application
such as MySQL Workbench to work with a MySQL database.
rkbencb
instance My$QL56 X
View Query Database Server Tools
O cJ <F dl o" 11 «-
SCHEMAS
/ 2T & 0 I Si Limit to 1000 raws 0 Q> L3U
Q, Filter objects SELECT ProductID, ListPrice, Description
FROM Product
▼ [3 rnma
ORDER BY ProductID
Tables
▼ Q) product
▼ fjpl Columns
♦ ProductID
♦ Code
♦ Description
♦ ListPrice
► © Indexes
Result Grid \m & Filer Rows: Edl: Expert/Import: Efj] | Wrap Cel Content:
ProductID ListPrice Description
► ® Foreign Keys
► Triggers TIT 57. 50 MuradVs Java Programming
Views 57.50 Muradi's Java Servlets and JSP
® Stored Procedures 54.50 MuradVs MySQL
® Functions
► § murach 57. 50 Muradn's Android Programming
► § murachjpa 54, 50 MuradVs HTML 5 arxj CSS 3
► musk
► § musicjpa 54. 50 MuradYs Orade and PL/SQL
► my_gultar_shop 54. 50 MuradVs JavaScript and jQuery
F @ om
Management Schemas
Schema: mma
[5 Action Output
Time _ Miugi_
Action Duration / Fetch
O 1 10:00:22 SELECT ProductID, ListPrice, Description FROM Prod . 7 row (s) returned 0.000 sec ( 0.000 sec
Object Info
Description
• To open a new SQL tab, press Ctrl+T or click the Create New SQL Tab button in
the SQL editor toolbar.
• To select the current database, double-click it in the Schemas section of the
Navigator window. This displays the selected database in bold.
• To enter a SQL statement, type it into the SQL tab.
• As you enter the text for a statement, the SQL tab applies color to various elements,
such as SQL keywords, to make them easy to identify.
• To execute a SQL statement, press Ctrl+Enter, or click the Execute Current
Statement button in the SQL editor toolbar. If the statement retrieves data, the data
is displayed in a Result grid below the SQL tab.
Description
• You can use the CREATE DATABASE statement to create a database and the
DROP DATABASE statement to delete a database. These are SQL statements.
• You can use the USE command to select the database that you want to work with.
• You can use the CREATE TABLE statement to create a table. When you create a
table, you define each of its columns and you identify its primary key. To define a
column, you must supply the name and the data type, whether it’s automatically
generated for new rows, and so on.
• When you use MySQL, the INSERT statement lets you insert one or more rows
into one table of a database. When you code it, you need to include data for all
columns that aren’t defined with default values or aren’t automatically generated.
• You can use the GRANT statement to create a user, specify a password for that
user, and grant privileges to the user.
Figure 1 9-7 The script that creates the database named mma
498 Section 5 Real-world skills
Result set
Result set
Description ListPrice
y Murach's Android Programming 57.50
Murach's HTML 5 and CSS 3 54.50
Murach's Java Programming 57.50
Murach's Java Servlets and JSP 57.50
Murach's JavaScript and jQuery 54.50
Murach's MySQL 54.50
Murach's Orade and PL/SQL 54.50
Result set
Description ListPrice
i Murach's HTML5 and CSS3 54.50
Murach's JavaScript and jQuery 54.50
Murach's MySQL 54.50
Murach's Orade and PL/SQL 54.50
Description
• A SELECT statement is a SQL DML statement that returns a result set (or result
table) that consists of the specified rows and columns.
• To specify the columns, you use the SELECT clause.
• To specify the table that the data should be retrieved from, you use the FROM
clause.
• To specify the rows, you use the WHERE clause.
• To specify how the result set should be sorted, you use the ORDER BY clause.
An INSERT statement
That doesn’t use a column list
INSERT INTO Product
VALUES ('8', 1 php 1 , 'Murach 1 1 s PHP 1 , ’54.50')
An UPDATE statement
That updates the ListPrice column in one row
UPDATE Product
SET ListPrice = ’57.50’
WHERE Code = ’javascript’
A DELETE statement
That deletes one row from the Product table
DELETE FROM Product
WHERE Code = ’php’
Description
• The INSERT, UPDATE, and DELETE statements modify the data that’s stored in a
database. These statements don’t return a result set. Instead, they return the number
of rows that were affected by the query.
• To identify a numeric or string literal in a SQL statement, you can enclose the
literal in single quotes ('). To include a single quote within a string literal that’s
enclosed in single quotes, you can enter two single quotes.
• On Unix systems, the table and column names are case-sensitive.
Perspective
The primary goal of this chapter is to introduce you to the database
concepts and SQL statements that you’ll need to develop database applications
with Java. The secondary goal of this chapter is to present the basic skills that
you need to use MySQL. If this chapter has succeeded, you should now under¬
stand the SQL statements presented in this chapter, and you should be able to
use MySQL Workbench to run them.
Keep in mind, though, that this chapter has presented j ust a small subset of
SQL skills. In particular, it has only presented the SQL statements you need to
understand the Java code presented in the next chapter. For a complete mastery
of SQL, you’ll probably want to get a book about SQL for the database that
you’re using. If, for example, you’re using MySQL, Murach’s MySQL presents
all of the SQL statements that you’ll need for your applications.
Summary
• MySQL is a relational database management system {RDBMS) that can
manage one or more databases.
• To retrieve and modify the data in one of its databases, MySQL provides
support for Structured. Query Language (SQL), which is the standard
language for working with databases.
• Whenever you use MySQL, its database server must be running. Usually,
this server starts automatically whenever you start your system.
• To work with a MySQL database, you can use a graphical tool called
MySQL Workbench. It makes it easy to enter and run SQL statements.
• A SQL script is a file that stores multiple SQL statements.
• The SQL statements that you use for creating and deleting databases and
tables are part of the Data Definition Language (DDL).
• The SQL statements that you use for retrieving and modifying the data in a
database make up the Data Manipulation Language (DML). These are the
SELECT, INSERT, UPDATE, and DELETE statements.
• The SELECT statement can get data from one or more tables and put it in a
result set, or result table. This is commonly referred to as a query.
• The INSERT, UPDATE, and DELETE statements are used to add one or
more rows to a table, update the data in one or more rows, and delete one or
more rows.
Chapter 19 How to work with a MySQL database 503
// get connection
Connection connection =
DriverManager- get Connect ion(dbURL, username, password);
} catch( SQLExcept ion e) {
for (Throwable t : e) {
System- out -print In(t );
}
}
Description
• Before you can get or modify the data in a database, you need to connect to it. To
do that, you use the getConnection method of the DriverManager class to return a
Connection object.
• When you use the getConnection method of the DriverManager class, you must
supply a URL for the database. In addition, you usually supply a username and a
password, though you might not for an embedded database. This method throws a
SQLException.
• With JDBC 4.0 and later, the SQLException class implements the Iterable interface. As
a result, you can use an enhanced for statement to loop through any nested exceptions.
• With JDBC 4.0 and later, the database driver is loaded automatically. This feature is
known as automatic driver loading.
• Prior to JDBC 4.0, you needed to use the forName method of the Class class to
load the driver. This method throws a ClassNotFoundException.
• Although the connection string for each driver is different, the documentation for
the driver should explain how to write a connection string for that driver.
• Typically, you only need to connect to one database for an application. However,
it’s possible to load multiple database drivers and establish connections to multiple
types of databases.
How to create a result set that contains multiple columns and rows
Statement statement = connection.createStatement ();
-
ResultSet products = statement executeQuery(
"SELECT * FROM Product ");
How to move the cursor to the first row in the result set
boolean productExists = product.next ( );
Description
• To return a result set, you use the createStatement method of a Connection object to
create a Statement object. Then, you use the executeQuery method of the Statement
object to execute a SELECT statement that returns a ResultSet object.
• By default, the createStatement method creates a forward-only, read-only result set.
This means that you can only move the cursor through it from the first row to the
last and that you can’t update it. Although you can pass arguments to the
createStatement method that create other types of result sets, the default is appro¬
priate for most applications.
• When a result set is created, the cursor is positioned before the first row. Then,
you can use the methods of the ResultSet object to move the cursor. To move the
cursor to the next row, for example, you call the next method. If the row is valid,
this method moves the cursor to the next row and returns a true value. Otherwise, it
returns a false value.
• The createStatement, executeQuery, and next methods throw a SQLException. As a
result, any code that uses these methods needs to catch or throw this exception.
Figure 20-3 Flow to return a result set and move the cursor through it
512 Section 5 Real-world skills
Code that uses indexes to return columns from the products result set
int productlD = products -getlnt ( 1);
String code = products -get String(2 );
-
String description = products getString( 3 );
double price = products.getDouble( 4 );
Code that creates a Product object from the products result set
Product p = new Product ( );
p- setld(productlD);
p.setCode( code );
-
p setDescription(description);
p.setPrice(price);
Description
• The getXXX methods can be used to return all eight primitive types. For example,
the getlnt method returns the int type and the getLong method returns the long
type.
• The getXXX methods can also be used to return strings, dates, and times. For
example, the getString method returns an object of the String class, and the
getDate, getTime, and getTimestamp methods return objects of the Date, Time, and
Timestamp classes of the java.sql package.
Description
• The executellpdate method is an older method that works with most JDBC drivers.
Although there are some newer methods that require less SQL code, they may not
work properly with all JDBC drivers.
• The executellpdate method returns an int value that identifies the number of rows
that were affected by the SQL statement.
Warning
• If you build a SQL statement from user input and use a method of the Statement
object to execute that SQL statement, you may be susceptible to a security vulner¬
ability known as a SQL injection attack.
• A SQL injection attack allows a hacker to bypass authentication or to execute SQL
statements against your database that can read sensitive data, modify data, or delete
data.
• To prevent most types of SQL injection attacks, you can use prepared statements as
described in the next figure.
To modify a row
string sql = "UPDATE Product SET "
+ " ProductCode = ?, "
+ " ProductDescription = ?, "
+ " ProductPrice = ?"
+ "WHERE ProductCode = ?";
PreparedStatement ps = connection.prepareStatement ( sql );
ps.set String( 1, product.getCode( ));
ps.setstring( 2, product.getDescript ion( ));
ps.setDouble( 3, product.get Price ( ));
ps.setstring( 4, product.getCode( ));
ps.executeUpdate( );
To insert a row
String sql =
"INSERT INTO Product (ProductCode, ProductDescription, ProductPrice) "
+ "VALUES (?, ?, ?)";
PreparedStatement ps = connection.prepareStatement (sql );
ps.set String( 1, product.getCode( ));
ps.setstring( 2, product.getDescription( ));
ps.setDouble( 3, product.get Price ( ));
ps.executeUpdate( );
To delete a row
string sql = "DELETE FROM Product "
+ "WHERE ProductCode = ?";
PreparedStatement ps = connection.prepareStatement ( sql );
ps.set String( 1, product.getCode( ));
ps.executeUpdate( );
Description
• When you use prepared statements in your Java applications, the database server
only has to check the syntax and prepare an execution plan once for each SQL
statement. This improves the efficiency of the database operations. In addition, it
prevents most types of SQL injection attacks.
• To specify a parameter for a prepared statement, type a question mark (?) in the
SQL statement.
• To supply values for the parameters in a prepared statement, use the set methods
of the PreparedStatement interface. For a complete list of set methods, look up the
PreparedStatement interface of the java.sql package in the documentation for the
Java API.
• To execute a SELECT statement, use the executeQuery method. To execute an
INSERT , UPDATE, or DELETE statement, use the executeUpdate method.
import java.sql.Connection;
import java.sql.Dri verManager;
import java.sql.SQLExcept ion;
private DBUtil() {}
Description
• To make it easier to get and close a connection to a database, you can use a utility
class like the one shown in this figure.
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.Result Set;
import java.sql.SQLException;
import java.ut i1.ArrayLi st;
import java.ut i1.Li st;
import murach.business.Product;
The get method returns a Product object lor a product that matches the
specified product code. To do that, it uses a prepared SQL statement to return
a result set. Then, it calls the next method of the result set to attempt to move
the cursor to the first row in the result set. If successful, this method continues
by reading the columns from the row, closing the result set, creating a Product
object from this data, and returning the Product object.
Unlike the getAll method, the result set used by the get method can’t be
created in the try-with-resources statement. That’s because before the result set
can be opened, the value of the parameter in the prepared statement must be set.
However, the prepared statement can still be created in the try-with-resources
statement, which means that it doesn’t have to be closed explicitly.
If no product row contains a product code that matches the specified code,
this method closes the result set and returns a null to indicate that the product
couldn’t be found. In addition, if a SQLException is thrown anywhere in this
method, this method creates a new exception from the DBException class and
throws this exception to the calling method. That way, the method that calls the
get method can throw or handle this exception.
As you review the get method, note that if the try block throws a
SQLException, the result set isn’t explicitly closed. In most cases, that’s not a
problem because the result set is automatically closed when the prepared state¬
ment that was used to create the result set is closed. If you wanted to close the
result set explicitly, though, you could do that by adding a finally clause to the
try statement.
The add method begins by creating a prepared statement that can be used to
insert values into three columns of the Product table. Then, it sets the values of
the three parameters in the prepared statement to the values stored in the Product
object that’s passed to it. Finally, it calls the executeUpdate method of the
prepared statement. If a SQLException is thrown anywhere in this method, this
code stores that exception in a DBException and throws it to the calling method.
Chapter 20 How to use JDBC to work with databases 523
return p;
} else {
rs.close( );
return null;
}
> catch ( SQLException e) {
throw new DBException(e);
}
}
Figure 20-8 The database class for the Email List application (part 2 of 3)
524 Section 5 Real-world skills
Figure 20-8 The database class for the Email List application (part 3 of 3)
526 Section 5 Real-world skills
Description
• You can use the static methods of the ProductDB class to map Product objects to
the rows of the Product table.
• You can use the DBUtil class to close the database connection when the application exits.
Perspective
Now that you’ve finished this chapter, you should understand how to use
JDBC to store data in a database and to retrieve data from a database. Although
there’s much more to learn about working with databases, those are the essen¬
tial skills. To enhance your database skills, you can learn more about database
management systems like MySQL or Oracle and the SQL that works with
them.
You should also understand that the JDBC API requires the developer to
write a significant amount of low-level code. This provides a good conceptual
background if you are new to Java and databases. In addition, many legacy
applications use JDBC. As a result, you may need to use it when working on
old applications.
However, for new development, you might prefer to use another data access
API such as JPA (Java Persistence API). This API handles much of the object to
database mapping automatically. As a result, it doesn’t require the developer to
write as much code, and the code that the developer does need to write is often
easier to maintain .
Summary
• With JDBC 4.0 (Java 6) and later, the database driver that’s used to connect
the application to a database is loaded automatically. This is known as
automatic driver loading .
• With JDBC 4.0 and later, you can loop through any exceptions that are
nested within the SQLException object.
• A Java application can use one of four driver types to access a database. It’s
considered a best practice to use a type-4 driver if one is available for that
database.
• You can use JDBC to execute SQL statements that select, add, update, or
delete one or more rows in a database. You can also control the location of
the cursor in the result set.
• You can use prepared statements to supply parameters to SQL statements.
Since prepared statements provide better performance and security than
regular statements, you should use them whenever possible.
Chapter 20 How to use JDBC to work with databases 529
11. In the Main class, add code that gets the specified product from the database,
sets the new data in that product, and updates the database with the new data.
If successful, this should display a message like this:
Description
• When creating GUIs with Java, you have several possible libraries that you can use,
Of these libraries, Swing is the most widely used,
Description
• The Swing library is built upon the AWT library. In other words, Swing classes
often inherit AWT classes.
• Most Swing classes begin with the letter J (for Java).
An empty frame
}
-
frame setVisible(true);
Description
• A frame typically defines the main window of an application.
• To set the title of a frame, you can use the constructor of the JFrame class. Or, you
can call the setTitle method of the JFrame object.
• To set the size of a frame, you call the setSize method and send it the height and
width in pixels. Or, you can call the pack method to automatically size the window
so it is just large enough to hold all of its components.
• To let the operating system set the location of a frame, you can call the setLocation-
ByPlatfrom method and send it a true value.
• To exit the application when the user selects the close button, you can set the
default close operation. If you don’t, the application may keep running after the
window closes.
• To set the look and feel to use the default platform look and feel, you call the
setLookAndFeel method of the UIManager class inside a try-catch block.
• To make the frame visible, you call the setVisible method and pass it a true value.
Description
• A panel is an invisible container that’s used to group other components.
• To create a panel, you can create a JPanel object. Then, you can add it to a frame.
• To create a button, you can create a JButton object. Then, you can add it to a frame
or a panel.
• You should add all of the panels and components to the frame before calling
its set Visible method. Otherwise, the user interface may flicker when it’s first
displayed.
Description
• To make a button do something when clicked, you add an action listener by calling
its addActionListener method.
• The addActionListener method accepts an ActionListener object that includes an
actionPerformed method that accepts an ActionEvent object. Within the actionPer-
formed method, you write the code that’s executed when the button is clicked.
• Prior to Java 8, it was common to write anonymous inner classes to handle actions.
However, with Java 8 or later, you can use a lambda expression, which is cleaner
and more concise.
Figure 21 -5 How to handle the event that occurs when a button is clicked
542 Section 5 Real-world skills
Description
• A layout manager determines how your components are placed in the container and
how they behave if the container is resized or if the font size changes,
• By default, a JFrame uses the BorderLayout manager.
• By default, a JPanel uses the FlowLayout manager.
Button 4
Description
• If the components don’t fit on one line, the FlowLayout manager wraps the compo¬
nents to a new line.
• The FlowLayout manager can align components to the left, right, or center. The
default is center.
South
V. J
Description
• A BorderLayout has five areas: NORTH, SOUTH, EAST, WEST, and CENTER.
• The default area is CENTER. As a result, if you don’t specify the area, the compo¬
nent is added to the center.
• The NORTH and SOUTH areas get their preferred height, which usually means
they are tall enough to hold whatever is placed in them. The preferred width is
ignored.
• The WEST and EAST areas get their preferred width, which usually means they are
wide enough to hold whatever is placed in them. The preferred height is ignored.
• The CENTER area gets whatever space is left over and expands or contracts as the
window is resized.
• Each area of a BorderLayout can only hold one component. If you need to add
multiple components to an area, you can add them to a panel and then add the panel
to the area.
JTable terminology
Column
/
| Product Manager .a
Description
• The easiest way to create a custom table model is to extend the AbstractTableModel
class.
• At a minimum, you need to override the getRowCount, getColumnCount, and
getValueAt methods. In addition, it’s common to override the getColumnName
method.
• When you update the database, you can call the fireTableDataChanged method to
refresh all data that’s displayed in the table.
• The AbstractTableModel class contains other methods, such as
fireTableCellUpdated and fireTableRowsInserted, that you can call to update part of
a table. These methods can be much more efficient, especially for a large table. See
the API documentation for more information.
Figure 21 -9 Flow to create a table model
550 Section 5 Real-world skills
import java.util.List;
import javax.swing.table.AbstractTableModel;
import mma.business.Product;
import mma.db.Produc t DB;
import mma.db.DBException;
public ProductTableModel ( ) {
try {
products = ProductDB.getAll ( );
> catch (DBException e) {
System.out .print In( e );
}
}
(ÿOverride
public int getRowCount ( ) {
return products.size();
>
(ÿOverride
public int getColumnCount ( ) {
return COLUMN_NAMES.length;
}
(ÿOverride
public String getColumnName(int columnlndex) {
return COLUMN_NAMES[columnlndex];
}
(ÿOverride
public Object getValueAt (int rowlndex, int columnlndex) {
switch (columnlndex) {
case 0:
return products.get (rowlndex).getCode();
case 1:
return products.get (rowlndex).getDescription( );
case 2:
return products.get (rowlndex).getPriceFormatted ( );
default:
return null;
}
>
Part 2 of figure 21-10 shows two more methods of the table model. When
you write the code for an application, you can call these methods to work with
the data in the table. You’ll see how this works later in this chapter.
The getProduct method returns a Product object for the row at the specified
index. This lets you get the Product object for the row that’s selected by the user,
which is useful if you want to update or delete this product in the database.
The databaseUpdated method updates the old data in the table model with
new data from the database. Then, it calls the fireTableDataChanged method of
the table model. This notifies the JTable widget that the data in the model has
changed. This allows the JTable widget to display the new data. If you modify
the underlying data in the database, you can call this method to synchronize the
data that’s displayed in the table with the data that’s in the database.
Chapter 21 How to develop a GUI with Swing (part 1 ) 553
void databaseUpdated ( ) {
try {
products = ProductDB.getAll ( );
fireTableDataChanged ( );
} catch (DBException e) {
System- out -print In( e );
}
}
}
Description
• When a row represents a business object such as a Product object, you can include
a method that returns an object for the specified row index.
• To synchronize the data in the table with the data in the database, you can include
a method that updates the model with the data from the database and then calls the
fireTableDataChanged method. This causes the table to display the new data that’s
stored in the model.
ListSelectionModel values
Value Description
SINGLE_SELECTION Allows selecting only one row at a time.
SINGLE_INTERVAL_SELECTION Allows selecting multiple rows, but only if
they are contiguous.
MULTIPLE_INTERVAL_SELECTI ON Allows for selection of multiple rows at the
same time, even if they are not contiguous
}
-
Product product = product TableModel get Product (rowlndex);
Description
• Once you have created a model for a table, you can create the table and set the
model in the table. Then, you can use the methods of the table to work with it.
ScrollPaneConstants
Value Description
HORIZONTAL_SCROLLBAR_AS_NEEDED Display the horizontal scrollbar only if the content is
wider than the view port and can't all be displayed at
the same time. This is the default.
HORIZONTAL_SCROLLBAR_NEVER Never display the horizontal scrollbar. It's still
possible to scroll left and right using the left and right
arrow keys on the keyboard.
HORIZONTAL_SCROLLBAR_ALWAYS Always display the horizontal scrollbar, whether it is
needed or not.
VERTIC AL_ SCROLLBAR_AS_NEEDED Display the vertical scrollbar only if the content is
longer than the viewport and can't all be displayed at
the same time. This is the default.
VERTIC AL_ SCROLLBAR_NEVER Never display the vertical scrollbar. It’s still possible
to scroll the content up and down using the up and
down arrow keys and the page up / page down keys
on the keyboard.
VERTICAL SCROLLBAR ALWAYS Always display the vertical scrollbar, whether it is
needed or not.
scrollPane.setVerticalScrollBarPolicy(
ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS );
Description
• You can use a scroll pane to add scrollbars to any component that might not fit in a
window.
• By default, scroll panes only display the scrollbars if they are needed.
Figure 21-12 Flow to work with scroll panes
558 Section 5 Real-world skills
Description
• To show a dialog box that displays a message, you use the static showMessage¬
Dialog method of the JOptionPane class. This method has lour parameters: (1) the
parent container, (2) the message, (3) the title, and (4) the type of dialog.
• Java uses the parent container parameter to determine where to display the dialog.
On Windows, Java typically centers the dialog box on the parent container.
• By default, the dialog box has a single OK button.
• The dialog box is modal. This means that it is always on top of the rest of the appli¬
cation. As a result, users can’t continue until they have responded to the dialog.
• The appearance of the icons displayed by the dialogs varies depending on the look
and feel that the application is using. In addition, these icons may vary depending
on the locale.
No
Description
• To display a dialog box that lets the user confirm or cancel an operation, you can
use the static showConfirmDialog method of the JOptionPane class.
• The first three parameters of the showConfirmDialog method work the same as the
showMessageDialog method shown in the previous figure.
• The fourth parameter determines the buttons that are displayed.
• By default, the showConfirmDialog method displays a question icon. However, you
can specify another type of icon by supplying the fifth parameter.
• To wrap a long message to a second line, you can use the line break character (\n).
Part 2 of figure 21-14 shows how to use the return value of the
showConfirmDialog method to determine which button the user selected. This
method can return any of the values listed in this figure. Of course, the possible
return values depend on the type of dialog. For example, a dialog box of the
YES_NO_OPTION returns the YES_OPTION or the NO_OPTION. In other
words, it never returns the CANCEL_OPTION or the OK_OPTION. However,
all dialog types can return the CLOSED_OPTION that indicates that the user
closed the dialog box without selecting any of the buttons.
The code example uses a switch statement to determine which button the
user selected. To do that, this switch statement provides one case for each
possible return value: the YES_OPT!ON, the NO_OPTION, and the
CLOSE_OPTION. Then, it prints a different message to the console depending
on which option the user selected. Alternately, it’s possible to use an if/else state¬
ment instead of a switch statement. However, as a general rule, switch statements
are more efficient. In addition, for code like this, they’re easier to read.
Remember that the dialogs produced by JOptionPane are blocking. This
means that they halt the thread and prevent it from continuing until the user has
responded to the dialog. As result, the switch statement doesn’t run until the user
selects one of the dialog buttons or closes the dialog.
Chapter 21 How to develop a GUI with Swing (part 1 ) 563
switch (option) {
case JOptionPane.YES_OPTION:
System.out .println( "You clicked the Yes button.");
break;
case JOptionPane.NO_OPTION:
System.out .println( "You clicked the No button.");
break;
case JOptionPane.CLOSED_OPTION:
System.out .println( "You closed the dialog.");
break;
}
Description
• When the user selects an option from a dialog box, the showConfirmDialog method
closes the dialog box and returns an int value for the option.
• To determine the option selected by the user, it’s common to use a switch state¬
ment. However, it’s also possible to use an if/else statement.
OK
Description
• The main window for the Product Manager application is a frame that displays a
panel that contains three buttons, as well as a table that contains the data for several
products,
• If the user selects the row for a product and clicks the Delete button, the application
displays a dialog box that allows the user to confirm the deletion.
• If the user selects the Add or Edit buttons, the application displays a dialog box
that indicates that these features haven’t been implemented yet. You’ll learn how to
implement these features in the next chapter.
Figure 21-15 The user interface for the Product Manager application
566 Section 5 Real-world skills
import java.awt.BorderLayout;
javax swi ng.JBut 1on;
import
-
javax swing.JFrame;
import
import
-
javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swi ng.JTabl e;
import javax.swing.ListSelect ionModel;
import javax.swing.UIManager;
import javax.swing.Unsupport edLookAndFeelExcept ion;
import mma.business.Product;
import mma.db.Product DB;
import mma.db.DBException;
public ProductManagerFrame( ) {
try {
UIManager.setLookAndFeel (
UIManager.get SystemLookAndFeelClassName( ));
} catch (ClassNotFoundException | Instant iationExcept ion
IllegalAccessException | UnsupportedLookAndFeelException e) {
System.out .print In( e );
}
setTitle( "Product Manager" );
setSize(768, 384);
setLocationByPlatf orm( true );
setDef aultCloseOperat ion(JFrame.EXIT_ON_CLOSE);
After creating these three buttons, this code adds these three buttons to the
panel. Finally, the last statement in the buildButtonPanel method returns the
panel.
The next three methods are the event handler methods for the action
listeners. For now, the methods for the Add and Edit buttons just display a dialog
box with a message indicating the feature hasn’t been implemented yet. In the
next chapter, you’ll learn how to add code to these methods so the Add and Edit
buttons can be used to add new products or to edit existing products.
However, the method for the Delete button contains code that deletes the
selected product from the database. To start, this code uses the getSelectedRow
method of the JTable widget to get the index for the selected row. Then, this code
checks whether this index is equal to - 1 . If so, it displays a message dialog that
indicates that the user must select a product before clicking the Delete button.
Otherwise, it displays a dialog that contains Yes and No buttons that allow the
user to confirm the operation. If the user clicks the Yes button, this code uses the
delete method of the ProductDB class described in the previous chapter to delete
the product. Then, it calls the fireDatabaseUpdatedEvent method that’s coded
later in this class. In turn, this method calls the databaseUpdated method of the
table model to update the data that’s displayed by the JTable widget.
The code that calls the methods of the JOptionPane class specifies
the keyword named this as the first argument of the method. This tells the
JOptionPane class that the current object (the ProductManagerFrame object) is
the parent for the dialog box.
The buildProductTable method creates a ProductTableModel object and
assigns it to the productTableModel instance variable. Remember that the
constructor for ProductTableModel class makes a call to the ProductDB class
to get all of the records. As a result, this creates a model that contains a list of
products that corresponds with the products in the database.
After creating the model, this code creates a new JTable widget and sets its
model. To do that, it passes the productTableModel variable to the constructor of
the JTable class.
After creating the JTable widget, the next line of code sets the selection
mode of the table to a value of SlNGLE_SELECT!ON. As a result, the user can
only select one row at a time.
Because this table is displayed in a JScrollPane widget, this code also sets
the border of the table to null. This makes sure that the Product Manager appli¬
cation doesn’t display two borders: one for the table and one for the scroll pane.
Finally, this code returns the table. Remember that the constructor of this
class calls the buildProductTable method to get this table. Then, it adds this table
to a scroll pane, and it adds the scroll pane to the center area of the frame.
Chapter 21 How to develop a GUI with Swing (part 1 ) 569
return panel;
}
Perspective
In this chapter, you learned some essential skills for developing a GUI with
Swing, the most widely used GUI toolkit for Java. In particular, you learned
how to create the main window of an application. You learned how to add
buttons. You learned how to handle the events that occur when these buttons
are clicked. You learned how to work with a table that displays data from a
database. And you learned how to work with built-in dialog boxes. In the next
chapter, you’ll learn how to create data entry forms that allow you to add and
update data in a database.
Summary
• Swing is the most commonly used GUI toolkit for Java.
• An element of a GUI is called a component or a widget.
• Swing provides pluggable look and feels that you can change.
• A component that can contain other components is called a container. Three
commonly used containers are frames, panels, and scroll panes.
• A J Frame widget usually serves as the main window of your application.
• A JPanel widget is an invisible component that you can use to group other
components.
• A JButton widget displays a button.
• To handle the event that occurs when the user clicks a JButton widget, you
can use the addActionListener method to add an action listener, or event
listener.
• An event handler is a method that responds to GUI events such as a button
click.
• A layout manager lays out the components in a container and controls how
they respond to events such as resizing the window.
• The BorderLayout and Flow Layout managers are two of the most commonly
used layout managers.
• A JTable widget displays tabular data, such as tables from a database.
• A table model provides tabular data for a JTable widget. The easiest way to
create a table model is to extend the AbstractTableModel class.
• A JScrollPane adds scrollbars to a component such as a JTable widget so
that the user can scroll through the component if it doesn’t all fit in the
container.
• You can use the methods of the JOptionPane class to displays a dialog box
that contains an informational message or a dialog box that confirms an
operation.
Chapter 21 How to develop a GUI with Swing (part 1 ) 571
Description
• A JLabel component defines a label, which is a non-editable widget that typically
displays text that labels other components such as text fields.
• Since you rarely need to call any methods from a JLabel object, it’s a common
practice to call the constructor of the JLabel class from within an add method. This
does not create a variable that refers to the JLabel object.
• A JLabel object can also display an image. However, that’s not covered in this
book.
Description
• A JTextField component defines a text field that displays text to the user and allows
the user to enter text. This type of component is also known as a text box.
Price:
\
-
The package that contains the layout manager classes
java awt -
Three classes for working with the GridBagLayout manager
Class Description
GridBagLayout Creates a layout manager that can lay out components in a grid,
GridBagConstraints Specifies how the GridBagLayout manager lays out its components. This
object controls horizontal and vertical space, whether components resize
or not, how they resize, and several other aspects of component behavior,
Insets Specifies the amount of padding that the GridBagConstraints object
applies between a component and the edge of the container,
Description
• The GridBagLayout manager is more complicated than the layout managers
presented in the previous chapter. However, it’s also the most powerful and flexible
layout manager in Swing.
• To lay out components in a grid, you can use the GridBagConstraints class with the
GridBagLayout class as shown in the next figure.
• To specify the padding between components, you can use the Insets class with the
GridBagConstraints class as shown in figure 22-5.
Code: I
Description :
Price:
Tlis label spans both columns.
Description
• You can reuse the same GridBagConstraints object for multiple widgets. However,
you must reset any values you don’t want to use in the next widget.
you don’t reset values, you may end up accidentally reusing the values that were
set for a previous component, which may cause strange layout behavior. As a
result, you need to make sure to reset all values, or you need to create a new
GridBagConstraint object for each component.
// the rest of the code that adds the labels and text boxes
Description:
Price:
This label spans both columns.
Description
• If you forget the order of the parameters for the constructor of the Insets class, it
may help to remember that they start at the top and go counterclockwise.
Description
• When a window is resized horizontally, components (especially text fields) can
sometimes collapse to a size of zero. This is a common problem.
- -
public NameDialog( java awt Frame parent) {
super(parent, "Name Dialog", true);
this setDef aultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
-
-
this set Layout (new FlowLayout ( ));
}
-
this setvisible(true);
Description
• A modal dialog prevents the user from interacting with other parts of the applica¬
tion until they have responded to the dialog.
• On most operating systems, a JDialog component is displayed on top of its parent
frame, has fewer window controls than a JFrame (for example, no maximize or
minimize buttons), and does not get its own entry in the taskbar.
Figure 22-7 Flow to create a custom dialog
588 Section 5 Real-world skills
At first glance, it might seem there aren’t that many differences between a
JFrame component and a JDialog component. However, on closer inspection,
there are few important differences. First, a dialog is designed to have a parent
window. As a result, a dialog is displayed on top of its parent window, even if
the dialog is not the active window. Second, on most operating systems, a dialog
has fewer window controls. On Windows, for example, a dialog has a close
button but no minimize, maximize, or restore buttons. Third, on most operating
systems, a dialog doesn’t get an entry in the taskbar or window list. As a result,
you can’t switch directly to the dialog using window switch commands. Instead,
you need to switch to the window that owns the dialog. Fourth, as described
earlier, a dialog can be modal.
Description
• Within the dialog class, you can code a constructor that allows the main window to
set data in the dialog .
• Within the class lor the main window, you can code a method that allows the dialog
to return set data to the main window.
• To close a dialog, you can call its dispose method. This closes the dialog object and
trees any resources that it’s using.
Figure 22-8 How to pass data between a dialog and its parent frame
590 Section 5 Real-world skills
Add Product
Add Edit
Code
java
jsp
r - Edit Product
i
Code: java|
mysql Description: MuradVs Java Programming
android
htmIS Price: 57.5
orade
javascript
Description
• The Product Manager application uses the same dialog to add a new product or to
edit an existing product. The only difference in appearance is the title of the dialog
and the text that’s displayed on the first button.
• When you add or edit a product, the Product form uses built-in dialogs to display
validation messages if the fields for the product are missing or not valid.
import java.awt.BorderLayout;
import java.awt .Dimension;
import java.awt.FlowLayout;
import java.awt.GridBagConstraint s;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JText Field;
import javax.swing.Wi ndowConst ants;
import mma.business.Product;
import mma.db.DBException;
import mma.db.Product DB;
public Product Form( java.awt .Frame parent, String title, boolean modal) {
super(parent, title, modal);
init Components( );
}
setDef aultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
The next two lines of code create Dimension objects and assign them a
width of 1 00 pixels and 300 pixels respectively, with both having a height of
20 pixels. Then, the code sets the preferred size and minimum size of the code
and price text fields to the shorter Dimension object. It also sets the preferred
and minimum size of the description text field to the longer Dimension object.
In both cases, this prevents the pitfall described earlier in this chapter where the
text fields collapse to a width of zero if the user resizes the dialog.
The next section of the initComponents method creates the two buttons. To
start, it sets the text of the first button to “Cancel” and adds an action listener to
it that calls a method named cancelButtonActionPerformed that’s shown later
in this class. Then, it sets the text of the second button to “Add” and adds an
action listener to it that calls a method named confirmButtonActionPerformed.
However, if the user is editing an existing product instead of adding one, the
setText method call here is overridden by the setText method call in the second
constructor as discussed on the previous page.
The next section creates a new JPanel to store the text fields and their
corresponding labels. To start, this code sets the layout manager for the panel to
the GridBagLayout manager. Then, it adds the text fields and labels for the form
to the panel. To make working with the GridBagConstraints object easier, the
calls to the panel’s add method use a helper method called getConstraints that’s
shown later in this class. This method takes three parameters: An x coordinate
for the grid row, a y coordinate for the grid column, and an anchor value.
The next section creates another JPanel for the buttons. To start, this code
sets the layout manager to a FlowLayout manager with right alignment. Then, it
adds the confirm and cancel buttons to the layout.
The last section adds the panel that contains the labels and text fields to the
center area of the dialog’s BorderLayout manager. Then, it adds the panel that
contains the buttons to the south area of the dialog’s BorderLayout manager.
Like a JFrame component, a JDialog component uses the BorderLayout manager
by default. As a result, it isn’t necessary to explicitly set the layout. Finally, the
last statement uses the pack method to size the dialog by packing it so it’s just
large enough to hold all of the components,
Note that none of this code sets the location of this form or makes this form
visible. As a result, the parent frame must do that. For example, the main frame
of the Product Manager application could display the Add Product form like this:
ProductForm productForm = new Product Form(this, "Add Product", true);
productForm.setLocationRelativeTo( this );
productForm- setVisible(true);
This displays a modal version of this form in the middle of the main window.
The getConstraints method creates and returns a GridBagConstraints
object with the specified parameters. This method begins by creating a new
GridBagConstraints object. Then, it sets the insets field to a new Insets object
that has five pixels of spacing on the top, left, and right, but no spacing on the
bottom. Next, it sets the gridx, gridy, and anchor fields of the GridBagConstraints
object to the corresponding parameters. Finally, it returns the new
GridBagConstraints object.
Chapter 22 How to develop a GUI with Swing (part 2) 595
-
confirmButton setText ( "Add" );
confirmButton.addActionListener((ActionEvent) -> {
confirmButtonAct ionPerf ormed ( );
});
/ / JButton panel
JPanel buttonPanel = new JPanel ( );
buttonPanel.setLayout (new FlowLayout (FlowLayout .RIGHT));
buttonPanel.add (confirmButton);
buttonPanel.add (cancelButton);
The next two methods in the class are the event handlers for the buttons. The
first event handler is called if the user presses the cancel button. The statement
within this method calls the dispose method of the dialog to close the dialog and
free its resources.
The second event handler is called if the user presses the confirm button. To
start, it uses an if statement that calls the validateData method shown later in this
class. This method makes sure the user entered all required data and that all of
the data is valid. If so, the event handler continues by calling the setData method
shown later in this class. This method gets the data from the form and sets that
data in the product instance variable.
The second if statement in the event handler checks whether the application
is editing an existing product or adding a new one. To do that, it checks the text
of the confirm button. If the text of the confirm button is “Add”, this code calls
the doAdd method shown later in this class. This method adds a new product to
the database. However, if the text of the button is not “Add”, this code calls the
doEdit method shown later in this class. This method updates an existing product
in the database.
The validateData method makes sure that the user has entered data for all
three text fields and that the user has entered a valid number for the product
price. To start, this code gets String objects for the product code, description, and
price variables by calling the getText methods on the corresponding text fields.
Then, this code uses an if statement to check whether all three fields in the form
contain values. If they don’t, the variables defined earlier are null or empty. In
that case, the code uses the JOptionPane class to display a dialog that contains a
message that asks the user to fill in all fields. Then, it returns a value of false.
This code also verifies that the price the user entered is a valid number. To
do this, it codes a statement that attempts to convert the price string to a double
value within a try statement. If this statement isn’t able to convert the string to a
double value, it throws a NumberFormatException, which causes the catch block
to be executed.
The catch block uses the JOptionPane class to display a dialog that contains
a message that informs the user that the data entered in the price field is not a
valid price. Then, it attempts to move the focus to the text field for the price.
However, this statement might not be able to move the focus. As a result, you
shouldn’t count on it working. Finally, the catch block returns a value of false.
If the user has entered data for all three fields, and the price is a valid
number, the validateData method returns a value of true. This indicates that the
data in the form is valid.
The setData method begins by getting the data contained in the form’s text
fields by calling their getText methods. Once again, to get a double value for the
price, this code needs to convert the String object returned by the getText method
to a double value. Then, this method sets this data in the instance variable for the
Product object by using its set methods.
For this method, the code doesn’t catch the NumberFormatException that
may be thrown by the parseDouble method because the validateData method
shown earlier has already made sure that the user has entered a valid number for
the price.
Chapter 22 How to develop a GUI with Swing (part 2) 597
The next two methods, doEdit and doAdd, are almost identical, except
that the doEdit method calls the update method of the ProductDB class, and
the doAdd method calls the add method of the ProductDB class. Then, these
methods both call the dispose method to close the dialog and free its resources.
Next, they call the fireDataBaseUpdatedEvent method.
The fireDatabaseUpdatedEvent notifies the main window that a new record
has been added to the database or that an existing record has been updated. In
turn, the main window notifies the table model that the table data needs to be
updated to reflect the changes made to the database as shown in the previous
chapter. To do this, the code begins by getting a reference to the parent window
of the dialog by calling the getOwner method. However, this method returns a
Window object. As a result, this code must cast it to the ProductManagerFrame
type before it can call its fireDatabaseUpdatedEvent method.
Chapter 22 How to develop a GUI with Swing (part 2) 599
A common problem
The first code example calls a method that could potentially take a long time
to complete. Because this method was called in response to the user pressing a
print button in the GUI, it runs on a special thread known as the event dispatch
thread, or EDT. All actions that are a result of an event run on the EDT, as do all
Swing operations that update the display, and respond to events.
Unfortunately, this means that the printProductList method also runs on the
EDT, which results in it becoming blocked until the method returns. As a result,
it can’t process other events, or redraw the screen if required. This causes the
application to become unresponsive to any other user events. In addition, the
display can become corrupt if it needs to be repainted, such as if it is resized, or
minimized and then restored.
At first, you might think you can solve this problem by running the print-
ProductList method on a new thread using the techniques shown in the second
code example. Unfortunately, it’s unsafe to perform any GUI operations outside
of the EDT, so this code causes a new problem, which is that this code runs the
JOptionPane dialog on a new thread rather than on the EDT, which can result in
display corruption.
Code that keeps the GUI responsive but shouldn’t update the GUI
private void doPrintButton( ) {
Thread printThread = new Thread() {
// This method runs on a background thread (not the EDT).
// As a result, the GUI remains responsive.
// However, it isn't safe to update the GUI from this thread.
(ÿOverride
public void run() {
print ProductList (); // This method may take a long time to run.
JOptionPane.showMessageDialog( ProductManagerFrame.this,
"Product list has been printed."); // NOT safe!
}
};
printThread.start ( );
}
Code that keeps the GUI responsive and can update the GUI
private void doPrintButton( ) {
SwingWorker worker = new SwingWorker() {
// This method runs on a background thread (not the EDT) .
// As a result, the GUI remains responsive.
@Override
protected Object doInBackground () throws Exception {
printProductList ( ); // This method may take a long time to run.
return null;
}
@Override
// This method runs on the EDT after the background thread finishes.
// As a result, itTs safe to update the GUI from this method.
protected void done() {
JOptionPane.showMessageDialog( ProductManagerFrame.this,
"Product list has been printed."); // Safe!
}
};
worker.execute ( );
}
Description
• Any code that runs in response to a Swing event runs on a special thread called the
event dispatch thread or EDT. All code that updates the GUI should run on this thread.
• If you run a task that takes a long time on the EDT, the GUI becomes unresponsive.
• If you use the techniques shown in chapter 18 to start a new thread, the GUI remains
responsive. However, you can’t safely update the GUI from this new thread.
• To allow the GUI to remain responsive while a long-running task runs and to be able
to update the GUI when that task finishes, you can use the SwingWorker class.
Perspective
In this chapter, you learned all of the remaining skills you need to know to
complete the Product Manager application. You learned how to use the JLabel
and JTextField classes to create labels and text fields for data entry forms. You
learned how to work with the GridBagLayout manager to create professional
looking forms. You learned how to use the JDialog class to create a modal data
entry form. And you learned how to pass data back and forth between two
windows in an application.
There’s still plenty more to learn about working with Swing. For example,
you may want to learn about other types of controls such as check boxes, radio
buttons, combo boxes, and lists. You may want to learn how to display photo¬
graphs or other graphics in Swing. You may want to learn about other layout
managers. You may want to learn more about using the SwingWorker class to
create threads in Swing. Or, you may want to learn how to use a GUI builder
tool that’s available from your IDE. Whatever you decide to learn next about
Swing, the skills presented in the last two chapters are a solid foundation that
you can build on.
Summary
• You can use the JLabel class to create labels that label other components on a form.
• You can use the JTextField class to create text fields, also known as text
boxes that allow a user to enter data.
• You can use the GridBagLayout manager to create professional looking
form layouts that lay out the components in a grid. This class has two helper
classes: GridBagConstraints and Insets.
• You can use the JDialog class to create a dialog that stays on top of its parent
window.
• A dialog can be modal, which means it prevents users from interacting with
any other part of the application until they have responded to the dialog.
However, you should only use modal dialogs when the application cannot
complete an operation until the user responds to the dialog.
• Any code that runs in response to a Swing event runs on a special thread
called the event dispatch thread or EDT.
• To prevent the GUI from becoming unresponsive during long running tasks,
as well as make sure GUI updates happen safely on the EDT, you can use
the SwingWorker class.
Chapter 22 How to develop a GUI with Swing (part 2) 605
7. Add code to the initComponents method that initializes the frame and its
components. This method should:
• Create the four text fields.
• Modify the text fields for the area and perimeter so the user can’t edit
them.
• Set the minimum and preferred dimension for all four fields.
• Create the two buttons.
• Create a panel that uses the GridBagLayo ut manager. Then, add the
four labels and text fields to this panel. To do that, you can use the
getConstraints method. Finally, add this panel to the center of the frame.
• Create a panel that uses the FlowLayout manager with right alignment.
Then, add the two buttons to this panel. Finally, add this panel to the
bottom of the frame.
• Pack the frame to set its size.
8. Run the application. This should display a frame that looks like the frame
shown above. However, if you click on one of the buttons, it should not
perform an action.
Handle the events that occur when the user clicks the buttons
9. Add action listeners to both of the buttons. These action listeners should call
the computeButtonClicked and resetButtonClicked methods.
1 0. Implement the computeButtonClicked method. This method should get the
text that the user entered into the text fields for the length and width and
attempt to convert this text to double values.
• If the user enters an invalid length or width, this method should use a
dialog to display a user-friendly error message. Then, the user can try
again.
• If the user enters a valid length and width, this method should calculate
the area and perimeter and set the corresponding text fields. To do that,
you can use the Rectangle class.
1 1 . Implement the resetButtonClicked method. This method should set all four
text fields to empty strings.
Appendix A
How to set up Windows
for this book
This appendix shows how to install and configure the software that we recom¬
mend for developing Java applications on a Windows system. For the first 1 8
chapters of this book, you only need to install the Java Development Kit (JDK),
the NetBeans IDE, and the source code for this book. However, for the last four
chapters in this book, you need to install MySQL and MySQL Workbench, and
yo u need to create the database for this book.
As you read this appendix, please remember that most websites are
updated constantly. As a result, some of the procedures in this appendix may
have changed since this book was published. Nevertheless, these procedures
should still be good guides to installing the software. And if there are signifi¬
cant changes, we will post updates on our website ( www.m urach .comb