Classes, fields, methods, constructors, and objects are the building blocks of object-based Java applications. This Java tutorial teaches you how to declare classes, describe attributes via fields, describe behaviors via methods, initialize objects via constructors, and instantiate objects from classes and access their members. You’ll also learn about setters and getters, method overloading, and setting access levels for fields, constructors, and methods.
What you’ll learn in this Java tutorial
- How to declare a class
- Using fields to describe attributes
- Using methods to describe behaviors
- Using constructors to initialize objects
- How to work with Java objects
How to declare a class
A class is a template for manufacturing objects. You declare a class by specifying the class
keyword followed by a non-reserved identifier that names it. A pair of matching open and close brace characters ({
and }
) follow and delimit the class’s body. This syntax appears below:
class identifier { // class body }
By convention, the first letter of a class’s name is uppercased and subsequent characters are lowercased (for example, Employee
). If a name consists of multiple words, the first letter of each word is uppercased (such as SavingsAccount
). This naming convention is called CamelCasing.
The following example declares a class named Book
:
class Book { // class body }
A class’s body is populated with fields, methods, and constructors. Combining these language features into classes is known as encapsulation. This capability lets us program at a higher level of abstraction (classes and objects) rather than focusing separately on data structures and functionality.
Utility classes
A class can be designed to have nothing to do with object manufacturing. Instead, it exists as a placeholder for class fields and/or class methods. Such a class is known as a utility class. An example of a utility class is the Java standard class library’s Math
class.
Multi-class applications and main()
A Java application is implemented by one or more classes. Small applications can be accommodated by a single class, but larger applications often require multiple classes. In that case one of the classes is designated as the main class and contains the main()
entry-point method. For example, Listing 1 presents an application built using three classes: A
, B
, and C
; C
is the main class.
Listing 1. A Java application with multiple classes
class A { } class B { } class C { public static void main(String[] args) { System.out.println("Application C entry point"); } }
You could declare these three classes in a single source file, such as D.java
. You would then compile this source file as follows:
javac D.java
The compiler generates three class files: A.class
, B.class
, and C.class
. Run this application via the following command:
java C
You should observe the following output:
Application C entry point
Alternatively, you could declare each class in its own source file. By convention, the source file’s name matches the class name. You would declare A
in A.java
, for instance. You could then compile these source files separately:
javac A.java javac B.java javac C.java
To save time, you could compile all three source files at once by replacing the file name with an asterisk (but keep the .java
file extension):
javac *.java
Either way, you would run the application via the following command:
java C
When designing multi-class applications, you will designate one of these classes as the main class and locate the main()
method in it. However, there is nothing to prevent you from declaring main()
methods in the other classes, perhaps for testing purposes. This technique is shown in Listing 2.
Listing 2. Declaring more than one main()
method
class A { public static void main(String[] args) { System.out.println("Testing class A"); } } class B { public static void main(String[] args) { System.out.println("Testing class B"); } } class C { public static void main(String[] args) { System.out.println("Application C entry point"); } }
After compiling the source code, you would execute the following commands to test the helper classes A
and B
, and to run the application class C
:
java A java B java C
You would then observe the following lines of output, one line per java
command:
Testing class A Testing class B Application C entry point
Using fields to describe attributes
A class models a real-world entity in terms of state (attributes). For example, a vehicle has a color and a checking account has a balance. A class can also include non-entity state. Regardless, state is stored in variables that are known as fields. A field declaration has the following syntax:
[static] type identifier [ = expression ] ;
A field declaration optionally begins with keyword static
(for a non-entity attribute) and continues with a type
that’s followed by a non-reserved identifier
that names the field. The field can be explicitly initialized by specifying =
followed by an expression
with a compatible type. A semicolon terminates the declaration.
The following example declares a pair of fields in Book
:
class Book { String title; int pubYear; // publication year }
The title
and pubYear
field declarations are identical to the variable declarations I presented in Java 101: Elementary Java language features. These fields are known as instance fields because each object contains its own copy of them.
The title
and pubYear
fields store values for a specific book. However, you might want to store state that is independent of any particular book. For example, you might want to record the total number of Book
objects created. Here’s how you would do it:
class Book { // ... static int count; }
This example declares a count
integer field that stores the number of Book
objects created. The declaration begins with the static
keyword to indicate that there is only one copy of this field in memory. Each Book
object can access this copy, and no object has its own copy. For this reason, count
is known as a class field.
Initialization
The previous fields were not assigned values. When you don’t explicitly initialize a field, it’s implicitly initialized with all of its bits set to zero. You interpret this default value as false
(for boolean
), '\u0000'
(for char
), 0
(for int
), 0L
(for long
), 0.0F
(for float
), 0.0
(for double
), or null
(for a reference type).
However, it is also possible to explicitly initialize a field when the field is declared. For example, you could specify static int count = 0;
(which isn’t necessary because count
defaults to 0), String logfile = "log.txt";
, static int ID = 1;
, or even double sinPIDiv2 = Math.sin(Math.PI / 2);
.
Although you can initialize an instance field through direct assignment, it’s more common to perform this initialization in a constructor, which I’ll demonstrate later. In contrast, a class field (especially a class constant) is typically initialized through direct assignment of an expression to the field.
Lifetime and scope
An instance field is born when its object is created and dies when the object is garbage collected. A class field is born when the class is loaded and dies when the class is unloaded or when the application ends. This property is known as lifetime.
Instance and class fields are accessible from their declarations to the end of their declaring classes. Furthermore, they are accessible to external code in an object context only (for instance fields) or object and class contexts (for class fields) when given suitable access levels. This property is known as scope.
Up next: Using methods to describe behaviors