Classes, Part 2: CS 310 Lecture notes
Outline
Scope
Packages and class path.
Comments and Javadoc.
Source Program Structure
Java source comprises one or more source files.
A source file is your basic text file.
The filename should have a .java
extension.
Each source file contains one or more class definitions (among other
things).
Each class in a source file compiles in to a separate .class
file.
Executable Structure
The JVM builds an executable from .class
files.
.class
files are loaded at runtime as needed.
This is known as lazy link and load.
This is an amazingly powerful and dangerous feature.
Unfortunately, we won’t be pursuing it in this class.
Compilation
The javac
compiler also deals with .class
files.
It needs them for type checking, for example.
The compiler manages source-.class
file consistency automatically.
Newer source files are compiled to update older (or nonexistent)
.class
files.
Development Structure
What kind of development structure works well with Java?
The trick here is there are two set of files: the source and the
.class
files.
But this is no different from the source-object (.o
)
file distinction
in C-C++.
One possibility is a monolithic structure: all files in one place.
Monolithic Problems
Monoliths are not well structured, and so don’t scale well and are
difficult to deal with.
Break monoliths up into interacting pieces.
The result is a set of mini-monoliths.
But each new monolith is smaller and functionally consistent.
Packages
A package is
a named group
of .class
files.
Every .class
file is a member of exactly one package.
A source file declares package membership with a package
statement:
package package-name ;
Every .class
file created from the source file belongs to the
declared package.
Accessing Classes
Class Access
You tell the compiler (and the JVM) the package holding the class.
Package qualification indicates class package membership.
<package-name >.<class-name >
board.TetrisBoard board;
The TetrisBoard .class
file in the board package.
Almost every class reference has to be package qualified.
Scope
Can a class access any other class in any other package?
Scope refers to the extent over which a feature exists and can
be accessed.
An existent and accessible feature is called in-scope .
A non-existent or inaccessible feature is called
out-of-scope .
Scopes So Far
Packages, classes, and methods are the scopes seen so far.
There are others to come.
The features introduced so far are packages, classes, methods, and
field variables.
There are others to come.
The General Questions
Can feature X in scope Y be accessed from scope Z ?
How can scope Z be prohibited from accessing feature X in
scope Y ?
This is an important question.
The combinatorics of these questions are complex.
Package Scope and Classes
By default, each class in package X can access any class in
package X .
Accessed by using just the class name.
Package qualification optional.
The compiler defaults to searching the containing package for other
classes.
By default, classes not in package X cannot access any class in
package X .
This is the default package scope .
Package Scope Example.
$ ls
A B
$ ls A
C1.java
$ ls B
C2.java
$
Package Scope Example..
$ cat A/C1.java
package A;
class C1 { }
$ cat B/C2.java
package B;
class C2 { }
class C3 {
B.C2 c2;
C2 c3;
A.C1 c1;
}
$
Package Scope Example...
$ javac B/C2.java
B/C2.java:8: A.C1 is not public in A;
cannot be accessed from outside package
A.C1 c1;
^
1 error
$
Package Scope Example....
$ cat A/C1.java
package A;
class C1 { }
$ cat B/C2.java
package B;
class C2 { }
class C3 {
B.C2 c2;
C2 c3;
A.C1 c1;
}
$
Widening Package Scope
Default package scope is too restrictive.
Cross-package accesses are essential.
The public scope for a class (or just public class )
allows access to the class from any package.
A public class starts with the public
keyword.
Public scope is a per-class scope, not per-package.
Public Class Naming
The name of the source file containing a public class must be the same
as the public-class name.
$ cat t.java
public class T { }
$ javac t.java
t.java:1: class T is public,
should be declared in a file named T.java
public class T { }
^
1 error
$
Only one public class per source file.
Public Scope Example.
$ ls
A B
$ ls A
C1.java
$ ls B
C2.java
$
Public Scope Example..
$ cat A/C1.java
package A;
public class C1 { }
$ cat B/C2.java
package B;
class C2 { }
class C3 {
B.C2 c2;
C2 c3;
A.C1 c1;
}
$
Public Scope Example...
$ javac B/C2.java
$
Observations
A class has either public or package scope.
All or nothing access is clumsy.
Package scope is global within the package.
Every class in the package can access every other class in the
package.
Problems with this suggest design errors.
In particular, the package’s too big.
The Default Package
Every .class
file is a member of some package.
$ cat A/C1.java
class C1 { }
$
package
statements are optional. What package is C1
in?
Classes not explicitly placed in a package fall into the nameless
default package .
Abbreviating Package Qualification
Every non-local class access has to be package qualified, which is a
pain.
The import
statement explicitly locates a class.
import
package-qualified-class ;
Imported classes don’t need package qualification.
Identically named classes from different packages still need package
qualification.
Import Example
$ cat B/C2.java
import A.C1;
class C2 { }
class C3 {
C2 c2;
C2 c3;
C1 c1;
}
$ javac B/C2.java
$
Global Imports
Import statements of the form
import
package .*;
import every public class from the given package.
There’s some documentation value to importing individual classes.
With a good IDE it doesn’t much matter.
*
imports could lead to unnecessary name clashes.
Mapping Packages
What is a package in the real world?
A package maps naturally to directory in a file system.
Mapping to directories is not required, but is the most conventional
and convenient.
Package tetris
maps to the directory tetris
.
This mapping is most natural, but not required.
!! Warning !! Warning !!
As the general semanticists remind: the map is not the territory.
Do not confuse directories and packages.
They are different but related things.
In particular, not every class in a directory is part of the same
package.
javac
does not check
to see that a source file in a package is being compiled in the proper
directory for the package.
Package Mismapping Example
$ cat A/C1.java
package B;
class C1 { }
$ javac -Xlint A/C1.java
$ ls A
C1.class C1.java
$
Package Mapping Example.
$ ls
A
$ ls A
C1.java
C2.java
$
Package Mapping Example..
$ cat A/C1.java
package A;
class C1 { }
$ cat A/C2.java
class C2 { C1 c1; }
$
Package Mapping Example...
$ javac A/C2.java
A/C2.java:1: cannot find symbol
symbol : class C1
location: class C2
class C2 { C1 c1; }
^
1 error
$
Even though they share the A
directory, both packages are
separate.
Package Mapping Example....
However,
$ cat A/C2.java
class C2 { A.C1 c1; }
$ javac -Xlint -classpath .. A/C2.java
$
This can’t be reversed: C1 can’t access C2.
Only default package entities can access default package entities.
Why ?
Hierarchical Packages
Packages nest to form a tree structure.
Package levels are separated by a dot.
package tetris;
package tetris.player.computer;
Package hierarchies map naturally to file-system hierarchies.
The package tetris.player.computer
corresponds
tetris/player/computer
(on Unixoid systems).
Imports and Nesting
Import statements deal with .class
files, not nested packages.
No Really, Where are the Packages?
Knowing that package X is in directory X isn’t too helpful.
Because where’s directory X ?
The classpath describes locations where package directories may
be found.
It lists parent directories that may contain package directories.
The -classpath
Option
javac
and java
have the -classpath
command-line option
(also -cp
for java
) to set the classpath.
The default classpath is the current directory (.
).
javac
always searches .
; java
only by default.
The classpath is a colon separated list of directories.
On Unix; check for other systems.
Classpath Example.
$ ls
A B
$ cat A/Ca.java
package A;
public class Ca { }
$ cd B
$ cat Cb.java
class Cb { A.Ca ca; }
$
Classpath Example..
$ javac Cb.java
Cb.java:1: package A does not exist
class Cb { A.Ca ca; }
^
1 error
$
Huh? Why doesn’t package A
exist?
Classpath Example...
Classpath defaults to .
The search for packages starts in directory B
.
Classpath needs to point to B
’s parent to find A
.
Classpath Example....
$ javac -classpath .. Cb.java
$
The CLASSPATH
Environment
Typing “-classpath
blah ” all the time is a pain.
Unless maybe if you use make or ant.
You can set the CLASSPATH
environment variable instead.
javac
and java
use the contents of CLASSPATH
if
-classpath
isn’t given.
Don’t forget .
for java
if you need it.
Cumulative Packages
A package may appear in several class-path directories.
/usr/java: java.lang
/usr/local/java: java.lang
The total package is
the union
of the individual packages.
Cumulative Package Search
Class search is sequential through the class path until the class is
found.
This is a security problem.
/evil-doer/java: java.security.cert Certificate
/usr/java: java.security.cert Certificate
Tracing Package Search
The -verbose:class
JVM option produces output describing class
loading.
It produces a lot of information.
It writes to std-out
rather than std-err
.
Example
$ java -verbose:class fact
[Loaded java.lang.Object from shared objects file]
[ blah blah blah ]
[Loaded java.math.BigInteger from shared objects file]
[Loaded java.math.MutableBigInteger from shared objects file]
1! = 1
2! = 2
[ and so on ]
Method Scope
Method scope is independent of class scope.
By default, methods have package scope.
Any class in the same package can access the method.
Methods with public scope can be accessed from any class in any
package.
Public-scope methods have the public
modifier.
Method Scope Example.
$ cat A/Ca.java
package A;
public class Ca {
public void yes() { }
void no() { }
}
$ cat B/Cb.java
import A.Ca;
class Cb {
void blue() {
Ca ca = new Ca();
ca.yes();
ca.no();
}
}
$
Method Scope Example..
$ javac B/Cb.java
B/Cb.java:7: no() is not public in A.Ca;
cannot be accessed from outside package
ca.no();
^
1 error
$
Private Method Scope
A method m
with private scope can only be accessed by
features in the same class as m
.
Right now, the only sensible features are other methods.
No access from other classes in the same package.
Private-scope methods have the private
modifier.
Instance-Variable Scope
An instance variable can have public, package, or private scope.
By default, instance variables have package scope.
Public or private scope is indicated by the public
or
private
modifier.
Access rules are the same as for methods.
Class and Instance Methods
By default, methods are called on class instances.
classInstance .
method (
args ...)
A method manipulates the instance’s state, among other things.
If there’s no class instance, there’s no method.
But what about constructors? Where’s the instance there?
Class Methods
A constructor is an example of a class method , a method called
without reference to an instance.
There’s no this
inside a class method.
A method becomes a class method by using the static
modifier.
static double sin(double x) { ... }
Static and access are independent.
static public, static private
Class Method Access
Class methods are accessed using the name of the containing class:
ClassName .
staticMethod (
args ...)
And package if necessary.
Static import s let you drop the class-name prefix.
import static
class .
staticMethod ;
import static
class .*;
Class vs. Instance Methods
Class methods can directly access only other class methods.
A class method can access instance methods via a class instance.
Instance methods can directly access class methods.
Going through the class name is fine too.
Method-Access Example
class blob {
static void cm1() { }
void im2() {
cm1(); this.cm1();
}
static void cm3() {
cm1(); blob.cm1();
im2();
blob b = new blob();
b.im2(); b.cm1();
}
}
Java Programs
Java programs (as opposed to applets) start executing in the main
method of the form
public static void
main(String args[]) { ... }
Beware the sticky static problem.
The main()
static spreads throughout the class.
Have a main class that does nothing but set-up and run the program.
Example.
Example..
$ javac -Xlint fact.java
fact.java:29: non-static method
fact(java.math.BigInteger)
cannot be referenced from a static context
System.err.println(i + "! = " + fact(i));
^
1 error
$
Example...
Class and Instance Variables
As with methods, so with variables.
A variable becomes a class variable by using the static
modifier.
static public double pi = 3.1415;
Static and scope are independent.
Class variables should be private or immutable.
Class and instance methods can access class variables independent of
scope.
Comments
Comments can either be single line or multi-line.
// Ignore to end of line.
/*
Ignore until next star-slash.
*/
Multi-line comments do not nest.
Javadoc comments are multi-line comments of the form
/**
blah blah blah
*/
Javadoc
javadoc
is a JDK documentation tool.
It extracts javadoc comments from Java source and formats them as
HTML pages.
Javadoc Comments
Javadoc comments is text with HTML tags and @
-keywords.
javadoc
parses @
-keywords, passes along HTML.
Be careful mixing HTML and @
-keywords.
A feature’s javadoc comment immediately precedes the feature.
Javadoc can document packages, classes, methods, and variables.
Class Comments
A class comment should immediately precede the related class.
Useful @
-keywords for classes include @author
, @version
,
and @deprecated
.
Always document a deprecated feature's replacement.
By default, only public classes are documented.
Document them all, pick subsets with javadoc options.
Method Comments
A method comment immediately precede the related method.
Useful @
-keywords for methods include @param
, @returns
,
and @throws
.
javadoc
performs sanity checks on these keywords.
By default, only public and protected methods are documented.
Field-Variable Comments
A field-variable comment immediately precedes the related variable.
By default, only public and protected variables are documented.
Example
/** The card’s rank.
@invariant 0 ≤ rank < 13
*/
private int rank;
Other Comment Types
Javadoc also provides package and overview (framework, subsystem)
documentation.
These comments require separate HTML files.
package.html
and overview.html
File placement depends on directory structure.
package.html
goes in the package directory.
overview.html
goes in some ancestor directory.
Running Javadoc
javadoc
’s a complicated program, but simple invocations usually
do.
Make sure you have a separate documentation directory.
javadoc
generates a lot of files.
Use the -d
command-line option, or run javadoc
in the
documentation directory.
Javadoc Quirks
javadoc
is a chatty program.
javadoc
warnings are useful but hard to see.
Use the -quiet
command-line option to cut the chatter.
By default, javadoc
documents only public or protected features.
Use the -private
or -package
command-line options to
document more features.
Javadoc Example
Generalizing Javadoc
Doclet generalizes javadoc
.
Create new document components and document formats.
The trick: generate documentation that’s Java code.
Boilerplate-code generation.
Used a lot in J2EE systems.
Summary
Scope sets an entity’s extent and visibility.
public
, package
(default), and private
.
Classes, methods, and field variables.
Packages group related class files.
Packages sort of map onto directories.
The class-path maps onto packages.
Javadoc is a cumbersome swiss-army knife.