OCP Oracle Certified Professional Java SE 17 Developer Study Guide. Jeanne Boyarsky
The output is what you might expect:
Bronx Zoo
The program correctly identifies the first two “words” as the arguments. Spaces are used to separate the arguments. If you want spaces inside an argument, you need to use quotes as in this example:
javac Zoo.java java Zoo "San Diego" Zoo
Now we have a space in the output:
San Diego Zoo
Finally, what happens if you don't pass in enough arguments?
javac Zoo.java java Zoo Zoo
Reading args[0]
goes fine, and Zoo
is printed out. Then Java panics. There's no second argument! What to do? Java prints out an exception telling you it has no idea what to do with this argument at position 1. (You learn about exceptions in Chapter 11, “Exceptions and Localization.”)
Zoo Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 1 out of bounds for length 1 at Zoo.main(Zoo.java:4)
To review, the JDK contains a compiler. Java class files run on the JVM and therefore run on any machine with Java rather than just the machine or operating system they happened to have been compiled on.
Single-File Source-Code
If you get tired of typing both javac
and java
every time you want to try a code example, there's a shortcut. You can instead run
java Zoo.java Bronx Zoo
There is a key difference here. When compiling first, you omitted the .java
extension when running java
. When skipping the explicit compilation step, you include this extension. This feature is called launching single-file source-code programs and is useful for testing or for small programs. The name cleverly tells you that it is designed for when your program is one file.
Understanding Package Declarations and Imports
Java comes with thousands of built-in classes, and there are countless more from developers like you. With all those classes, Java needs a way to organize them. It handles this in a way similar to a file cabinet. You put all your pieces of paper in folders. Java puts classes in packages. These are logical groupings for classes.
We wouldn't put you in front of a file cabinet and tell you to find a specific paper. Instead, we'd tell you which folder to look in. Java works the same way. It needs you to tell it which packages to look in to find code.
Suppose you try to compile this code:
public class NumberPicker { public static void main(String[] args) { Random r = new Random(); // DOES NOT COMPILE System.out.println(r.nextInt(10)); } }
The Java compiler helpfully gives you an error that looks like this:
error: cannot find symbol
This error could mean you made a typo in the name of the class. You double-check and discover that you didn't. The other cause of this error is omitting a needed import statement. A statement is an instruction, and import
statements tell Java which packages to look in for classes. Since you didn't tell Java where to look for Random
, it has no clue.
Trying this again with the import
allows the code to compile.
import java.util.Random; // import tells us where to find Random public class NumberPicker { public static void main(String[] args) { Random r = new Random(); System.out.println(r.nextInt(10)); // a number 0-9 } }
Now the code runs; it prints out a random number between 0
and 9
. Just like arrays, Java likes to begin counting with 0
.
static
import. It allows you to make static
members of a class known, often so you can use variables and method names without having to keep specifying the class name.
Packages
As you saw in the previous example, Java classes are grouped into packages. The import
statement tells the compiler which package to look in to find a class. This is similar to how mailing a letter works. Imagine you are mailing a letter to 123 Main Street, Apartment 9. The mail carrier first brings the letter to 123 Main Street. Then the carrier looks for the mailbox for apartment number 9. The address is like the package name in Java. The apartment number is like the class name in Java. Just as the mail carrier only looks at apartment numbers in the building, Java only looks for class names in the package.
Package names are hierarchical like the mail as well. The postal service starts with the top level, looking at your country first. You start reading a package name at the beginning too. For example, if it begins with java
, this means it came with the JDK. If it starts with something else, it likely shows where it came from using the website name in reverse. For example, com.wiley.javabook
tells us the code is associated with the wiley.com
website or organization. After the website name, you can add whatever you want. For example, com.wiley.java.my.name
also came from wiley.com
. Java calls more detailed packages child packages. The package com.wiley.javabook
is a child package of com.wiley
. You can tell because it's longer and thus more specific.
You'll see package names on the exam that don't follow this convention. Don't be surprised to see package names like a.b.c
. The rule for package names is that they are mostly letters or numbers separated by periods (.
). Technically, you're allowed a couple of other characters between the periods (.
). You can even use package names of websites you don't own if you want to, such as com.wiley
, although people reading your code might be confused! The rules are the same as for variable names, which you see later in this chapter. The exam may try to trick you with invalid variable names. Luckily, it doesn't try to trick you by giving invalid package names.
In the following sections, we look at imports with wildcards, naming conflicts with imports, how to create a package of your own, and how the exam formats code.
Wildcards
Classes in the same package are often imported together. You can use a shortcut to import
all the classes in a package.
import java.util.*; // imports java.util.Random among other things public class NumberPicker { public static void main(String[] args) { Random r = new Random(); System.out.println(r.nextInt(10)); } }
In this example, we imported java.util.Random
and a pile of other classes. The *
is a wildcard that matches all classes in the package. Every class in the java.util
package is available to this program when Java compiles it. The import
statement doesn't bring in child packages, fields, or methods; it imports only classes directly under the package. Let's say you wanted to use the class AtomicInteger
(you learn about that one in Chapter 13, “Concurrency”) in the java.util.concurrent.atomic
package. Which import or imports support this?
import java.util.*; import java.util.concurrent.*; import java.util.concurrent.atomic.*;
Only the last import allows the class to be recognized because child packages are not included with the first two.
You might think