Object-Oriented Programming Fundamentals: Classes, Objects, Methods, and Strings
Class Declarations and Object Instantiation
Public Class Rules and File Naming:
Every class declaration prefixed with the keyword
publicmust be saved in a source code file having the exact same name as the class, followed by the.javafile extension (e.g.,GradeBookmust be saved asGradeBook.java).The keyword
publicis an access modifier that makes the class accessible to code outside its file.
Execution and Driver Classes:
Executable Java applications require a
mainmethod, which is automatically called by the Java Virtual Machine (JVM) upon starting the program.A class lacking a
mainmethod cannot be directly executed as an application; attempting to execute it results in a runtime error:java.lang.NoSuchMethodError: main.To test classes designed without a
mainmethod, a separate driver class containing amainmethod is declared to instantiate objects and invoke their methods.
Static vs. Instance Methods:
A
staticmethod (such asmain) can be invoked without first instantiating an object of the class in which it is declared.Instance methods belong to objects; invoking an instance method requires creating an object of the class and executing the call via a reference variable.
Class Instance Creation Expressions:
Keyword
newcreates a new object instance of the specified class and requests memory from the operating system.The syntax requires parentheses after the class name (e.g.,
new GradeBook()), which triggers a call to the class's constructor to perform initial data setup.Declaring a variable of a class type creates a reference variable capable of holding the location of a class object in memory.
Method Invocation Syntax:
Instance methods are called using the reference variable name, followed by the dot separator (
.), the method name, and parentheses enclosing any required arguments (e.g.,myGradeBook.displayMessage()).
GradeBook Class Example (Basic Declaration):
// Fig. 3.1: GradeBook.java
// Class declaration with one method.
public class GradeBook
{
// display a welcome message to the GradeBook user
public void displayMessage()
{
System.out.println( "Welcome to the Grade Book!" );
} // end method displayMessage
} // end class GradeBook
GradeBookTest Driver Class Example:
// Fig. 3.2: GradeBookTest.java
// Creating a GradeBook object and calling its displayMessage method.
public class GradeBookTest
{
// main method begins program execution
public static void main( String[] args )
{
// create a GradeBook object and assign it to myGradeBook
GradeBook myGradeBook = new GradeBook();
// call myGradeBook's displayMessage method
myGradeBook.displayMessage();
} // end main
} // end class GradeBookTest
Method Structure, Parameters, and Scanner Input
Method Header Breakdown:
A method header consists of the access modifier (
public), return type (voidor a specific data type), method identifier, and a parameter list contained within parentheses.Method naming convention: lowerCamelCase (starts with a lowercase letter, and subsequent combined words begin with an uppercase letter).
The
voidreturn type indicates that the method performs a task but returns no data to its caller upon completion.Empty parentheses
()signify that the method requires no additional information to complete its operation.
Parameters and Arguments:
Parameters are variables declared in a comma-separated parameter list within the method header. Each parameter declaration must explicitly specify both a data type and an identifier.
Arguments are the concrete values supplied to a method when it is called.
Requirement: The number of arguments in a method call must exactly match the number of parameters in the method header, and the argument data types must be consistent with the specified parameter types.
Reading Text Input with
Scanner.nextLine():The
nextLine()method of theScannerclass reads characters typed at the command line until a newline character is encountered (when the user pressesEnter).It returns a
Stringcontaining the full line of characters typed, excluding the newline character itself (which is discarded).
GradeBook Class with Method Parameter Example:
// Fig. 3.4: GradeBook.java
// Class declaration with a method that has a parameter.
public class GradeBook
{
// display a welcome message to the GradeBook user
public void displayMessage( String courseName )
{
System.out.printf( "Welcome to the grade book for
%s!
",
courseName );
} // end method displayMessage
} // end class GradeBook
Passing Arguments via Scanner Example:
// Fig. 3.5: GradeBookTest.java
// Create GradeBook object and pass a String to its displayMessage method.
import java.util.Scanner; // program uses Scanner
public class GradeBookTest
{
// main method begins program execution
public static void main( String[] args )
{
// create Scanner to obtain input from command window
Scanner input = new Scanner( System.in );
// create a GradeBook object and assign it to myGradeBook
GradeBook myGradeBook = new GradeBook();
// prompt for and input course name
System.out.println( "Please enter the course name:" );
String nameOfCourse = input.nextLine(); // read a line of text
System.out.println(); // outputs a blank line
// call myGradeBook's displayMessage method
// and pass nameOfCourse as an argument
myGradeBook.displayMessage( nameOfCourse );
} // end main
} // end class GradeBookTest
Packages and Import Declarations
Package Structures:
Classes in Java are grouped logically into packages.
The
java.langpackage contains essential system classes, includingSystemandString. This package is implicitly imported into every Java program, allowing immediate access to its classes without animportstatement.Classes not located in
java.lang(such asjava.util.Scanner) must be explicitly imported using animportdeclaration before they can be referenced.
The Default Package:
Classes compiled in the exact same directory on disk without an explicit package statement automatically belong to the default package.
Classes in the same default package can reference one another directly without needing
importstatements.
Instance Variables, Encapsulation, and Accessor/Mutator Methods
Instance Variables (Fields):
Instance variables are declared inside a class declaration but outside the body boundaries of any method declarations.
Every object instance created from a class allocates and maintains its own distinct copy of these variables in memory.
Encapsulation and Data Hiding:
Declaring instance variables with the
privateaccess modifier enforces data hiding (information hiding).privatevariables and methods are accessible only to methods declared within that specific class.Encapsulation prevents external client code from modifying an object's internal state directly or accidentally.
Set Methods (Mutators) and Get Methods (Accessors):
Classes provide
publicmethods to allow controlled external reading and writing ofprivatefields.A
setmethod (mutator) receives an argument, validates it if necessary, and assigns it to the instance variable. Its return type is usuallyvoid.A
getmethod (accessor) reads the value of an instance variable and returns it to the caller. Its return type matches the field's data type.
Field Default Values:
Unlike local variables declared inside method bodies (which must be manually initialized before use), instance variables are automatically assigned default initial values upon object creation.
Reference types (such as
String) default tonull.Numeric primitive types default to
0or0.0.Boolean primitive types default to
false.
Internal Method Calls:
Methods contained within the same class can invoke each other directly using only the method name, without using dot notation or reference variables.
GradeBook Class with Instance Variable, Getters, and Setters:

// Fig. 3.7: GradeBook.java
// GradeBook class that contains a courseName instance variable
// and methods to set and get its value.
public class GradeBook
{
private String courseName; // course name for this GradeBook
// method to set the course name
public void setCourseName( String name )
{
courseName = name; // store the course name
} // end method setCourseName
// method to retrieve the course name
public String getCourseName()
{
return courseName;
} // end method getCourseName
// display a welcome message to the GradeBook user
public void displayMessage()
{
// calls getCourseName to get the name of
// the course this GradeBook represents
System.out.printf( "Welcome to the grade book for
%s!
",
getCourseName() );
} // end method displayMessage
} // end class GradeBook
Manipulating GradeBook Instance Variable Example:
// Fig. 3.8: GradeBookTest.java
// Creating and manipulating a GradeBook object.
import java.util.Scanner;
public class GradeBookTest
{
public static void main( String[] args )
{
Scanner input = new Scanner( System.in );
GradeBook myGradeBook = new GradeBook();
// display initial value of courseName (outputs null)
System.out.printf( "Initial course name is: %s
",
myGradeBook.getCourseName() );
// prompt for and read course name
System.out.println( "Please enter the course name:" );
String theName = input.nextLine();
myGradeBook.setCourseName( theName );
System.out.println();
// display welcome message including updated course name
myGradeBook.displayMessage();
} // end main
} // end class GradeBookTest
Primitive Types vs. Reference Types
Primitive Types:
Java defines eight primitive data types:
boolean,byte,char,short,int,long,float, anddouble.Primitive-type variables store exactly one raw value of their declared type at any given moment directly in memory.
Reference Types:
All non-primitive data types are reference types (e.g., class types, array types).
A reference-type variable stores the memory address location pointing to where an object resides.
Reference-type instance variables default to
nullwhen uninitialized, signifying that the variable points to no location in memory.Calling a method on a reference variable is formally termed sending a message to the target object.
Constructors and Custom Initialization
Constructor Syntax and Properties:
A constructor is a specialized block invoked automatically during object allocation via
newto initialize the object's instance variables.Must have the exact same identifier name as the class in which it is declared.
Cannot return any value and must not declare a return type (not even
void).Normally declared with
publicvisibility.
Default Constructor Mechanics:
If a class contains no explicit constructor declarations, the Java compiler automatically generates a parameterless default constructor.
The default constructor initializes all instance variables to their default primitive or reference values.
Critical Rule: If a programmer explicitly declares any constructor (parameterized or parameterless) in a class, the compiler will not generate a default constructor. In that scenario, calling a parameterless constructor without explicitly defining one causes a compilation error.
GradeBook Class with Constructor Example:

// Fig. 3.10: GradeBook.java
// GradeBook class with a constructor to initialize the course name.
public class GradeBook
{
private String courseName; // course name for this GradeBook
// constructor initializes courseName with String argument
public GradeBook( String name )
{
courseName = name; // initializes courseName
} // end constructor
public void setCourseName( String name )
{
courseName = name;
} // end method setCourseName
public String getCourseName()
{
return courseName;
} // end method getCourseName
public void displayMessage()
{
System.out.printf( "Welcome to the grade book for
%s!
",
getCourseName() );
} // end method displayMessage
} // end class GradeBook
Instantiating Objects using Constructors Example:
// Fig. 3.11: GradeBookTest.java
// GradeBook constructor used to specify the course name at the
// time each GradeBook object is created.
public class GradeBookTest
{
public static void main( String[] args )
{
// create GradeBook objects with specific initial course names
GradeBook gradeBook1 = new GradeBook(
"CS101 Introduction to Java Programming" );
GradeBook gradeBook2 = new GradeBook(
"CS102 Data Structures in Java" );
// display initial value of courseName for each GradeBook
System.out.printf( "gradeBook1 course name is: %s
",
gradeBook1.getCourseName() );
System.out.printf( "gradeBook2 course name is: %s
",
gradeBook2.getCourseName() );
} // end main
} // end class GradeBookTest
Floating-Point Numbers and Type double
Precision Characteristics:
Floating-point numbers contain decimal digits (e.g., , , ).
float: Represents single-precision floating-point numbers requiring 32 bits of memory, providing up to significant decimal digits.double: Represents double-precision floating-point numbers requiring 64 bits of memory (twicefloat), providing up to significant decimal digits.
Formatted Output (
System.out.printf):The
%fformat specifier outputs values of typefloatordouble.Precision syntax
%.2fspecifies formatting the output to exactly two decimal places (rounded to the hundredths position).
Scanner Operations:
Method
Scanner.nextDouble()parses and returns adoublevalue typed by the user.
Account Class Example (Input Validation and Floating-Point Math):
// Fig. 3.13: Account.java
// Account class with a constructor to validate and
// initialize instance variable balance of type double.
public class Account
{
private double balance; // instance variable that stores the balance
// constructor
public Account( double initialBalance )
{
// validate that initialBalance is greater than 0.0;
// if it is not, balance is initialized to the default value 0.0
if ( initialBalance > 0.0 )
balance = initialBalance;
} // end Account constructor
// credit (add) an amount to the account
public void credit( double amount )
{
balance = balance + amount; // add amount to balance
} // end method credit
// return the account balance
public double getBalance()
{
return balance;
} // end method getBalance
} // end class Account
AccountTest Application Example:
// Fig. 3.14: AccountTest.java
// Inputting and outputting floating-point numbers with Account objects.
import java.util.Scanner;
public class AccountTest
{
public static void main( String[] args )
{
Account account1 = new Account( 50.00 ); // create Account object
Account account2 = new Account( -7.53 ); // create Account object
// display initial balance of each object
System.out.printf( "account1 balance: $%.2f
", account1.getBalance() );
System.out.printf( "account2 balance: $%.2f
", account2.getBalance() );
Scanner input = new Scanner( System.in );
double depositAmount; // deposit amount read from user
System.out.print( "Enter deposit amount for account1: " );
depositAmount = input.nextDouble(); // obtain user input
System.out.printf( "
adding %.2f to account1 balance
", depositAmount );
account1.credit( depositAmount ); // add to account1 balance
// display balances
System.out.printf( "account1 balance: $%.2f
", account1.getBalance() );
System.out.printf( "account2 balance: $%.2f
", account2.getBalance() );
System.out.print( "Enter deposit amount for account2: " );
depositAmount = input.nextDouble(); // obtain user input
System.out.printf( "
adding %.2f to account2 balance
", depositAmount );
account2.credit( depositAmount ); // add to account2 balance
// display balances
System.out.printf( "account1 balance: $%.2f
", account1.getBalance() );
System.out.printf( "account2 balance: $%.2f
", account2.getBalance() );
} // end main
} // end class AccountTest
Copy Constructors
Concept and Purpose:
A copy constructor creates a new object as an exact duplicate of an existing object of the same class.
It serves as a simple alternative to the default Java cloning mechanism.
Inefficient Object Copying Syntax:
Manually extracting every field via getters to construct a new instance is verbose:
Student s2 = new Student(s1.getId(), s1.getfName(), s1.getlName());
Copy Constructor Syntax and Implementation:
A copy constructor takes a reference to an object of the same class type as its single parameter:
public Student( Student other )
{
this.id = other.id;
this.fName = other.fName;
this.lName = other.lName;
}
Instantiation using Copy Constructor:
Student s2 = new Student( s1 );
Deep Copy Requirement:
Copy constructors must perform a deep copy for mutable reference fields to ensure the new object and original object are fully detached, avoiding shared memory references.
Standard Object Methods: toString() and equals()
The
toString()Method:Formats and returns a
Stringrepresentation containing the data state of an object.Replaces custom message output methods to standardize object-to-string conversions.
public String toString()
{
return String.format( "id= %d, First Name = %s Last Name= %s", id, fName, lName );
}
Implicit Execution: When an object reference is passed to
System.out.println(s1), the compiler automatically callss1.toString(). Therefore,System.out.println(s1.toString())andSystem.out.println(s1)produce identical output.The
equals()Method:
Compares two objects for logical data equality and returns a
booleanresult (trueorfalse).
public boolean equals( Student other )
{
return id == other.id &&
fName.equals( other.fName ) &&
lName.equals( other.lName );
}
Execution syntax:
s1.equals(s2).
Class Design Exercises
Student Class Specifications:
Private Attributes:
id: int,fName: String,lName: String.Constructors:
Student(int)Student(int, String, String)Public Methods:
getId(): int,setId(int): void,getfName(): String,setfName(String): void,getlName(): String,setlName(String): void,DisplayMessage(): String(ortoString()).

Date Class Specifications:
Private Attributes:
day: int,month: int,year: int.Constructors:
Date(Date)(Copy Constructor)Date(int)Date(int, int)Date(int, int, int)Public Methods:
getDay(): int,setDay(int): void,getMonth(): int,setMonth(int): void,getYear(): int,setYear(int): void,toString(): String,equals(Date): boolean.
