Packages and projects
In the last lesson a program grew to two files. Here it is again: Main calls Greeter.greet, and
javac compiles both files.
public class Main {
public static void main(String[] args) {
System.out.println(Greeter.greet("Ada"));
}
}
The editor helps with programs of several files. Type a dot after a name, such as Greeter., and it
suggests what can follow. Hold Ctrl (⌘ on a Mac) and click a name, or press F12 on it, to jump to where
it is defined, even when that is in the other file.
Why packages
Every class has a name, and two classes cannot share one. That gets hard as programs grow: a bank
program may want an Account for money, while its login code wants an Account for user names. Java's
own library has the same problem: there is a List for lists of values and another List that draws a
list on the screen.
A package is a family name for classes. The money Account can live in the package app.model and
the login one in app.login; their full names, app.model.Account and app.login.Account, differ. The
List you will use most is java.util.List.
Packages are folders. A class in the package app.model is written in the folder app/model, and its
file starts with package app.model;. A class that uses it from another package names it in an
import line at the top of its file.
A package in a folder
This block is a small project: a folder with sub-folders. The editor's file tree shows them; click a
file to open it. Main is in the package app, Account in
app.model.
package app;
import app.model.Account;
public class Main {
public static void main(String[] args) {
Account a = new Account("Ada", 10);
a.deposit(5);
System.out.println(a);
}
}
Read the command that Run prints:
$ javac -d out -encoding UTF-8 -Xmaxerrs 50 app/Main.java app/model/Account.java && java -cp out app.Main
javac gets every .java file of the folder, with its path. -d out puts the compiled classes in
out, in folders that follow the packages (out/app/model/Account.class). java -cp out app.Main then
starts the class by its full name. There is nothing else to set up: no build tool, just these two
commands.
public matters now. Main can call deposit only because Account and deposit are public; without
it they are visible inside their own package only. balance is protected: visible in the package and in
classes that extend Account, as in the next exercise.
Main uses a class Savings that does not exist yet. Select the folder model in the tree, click
+ File and name the file Savings.java; the editor fills in package app.model; and the class.
Make Savings extend Account, give it a constructor Savings(String owner, int balance) that calls
super(owner, balance), and a method addInterest() that deposits 5 % of the balance (balance / 20).
The program should then print Grace: 105.
package app;
import app.model.Savings;
public class Main {
public static void main(String[] args) {
Savings s = new Savings("Grace", 100);
s.addInterest();
System.out.println(s);
}
}
Until Savings.java exists, javac reports cannot find symbol in app/Main.java; the editor marks the
line and opens the file. If you write package app; in a file of the folder app/model, javac
compiles it but Main cannot find the class where its import says: the package and the folder must
agree.
The terminal sees the same folder. Choose Open in the terminal in the ⋯ menu (or open the Terminal tab and
type cd ~/06-projects/bank), then ls app/model, or the javac command Run printed in the output: it builds the same
way. Files you make there show up in the tree
when you click back into the editor.
One last difference: the editor's suggestions come from this page, which reads your code as you type;
errors come from javac when you Run, as they always have.