0% found this document useful (0 votes)
1 views

Advanced Programming Language 2 Lecture 0 – Course Introduction (3)

The document outlines the course structure for an advanced programming language class focused on Java, covering topics such as basic programming, object-oriented programming, exception handling, multithreading, and GUI applications. It includes information on textbooks, grading policies, project requirements, academic integrity, and Java setup instructions. Additionally, it explains the Java Development Kit (JDK), Java Virtual Machine (JVM), and the execution process of Java code.

Uploaded by

Martin Nashaat
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
1 views

Advanced Programming Language 2 Lecture 0 – Course Introduction (3)

The document outlines the course structure for an advanced programming language class focused on Java, covering topics such as basic programming, object-oriented programming, exception handling, multithreading, and GUI applications. It includes information on textbooks, grading policies, project requirements, academic integrity, and Java setup instructions. Additionally, it explains the Java Development Kit (JDK), Java Virtual Machine (JVM), and the execution process of Java code.

Uploaded by

Martin Nashaat
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 563

Advanced Programming Language

Dr. Ahmed Hesham Mostafa


Dr. Mohamed Atia
Lecture 0 – Course Introduction & Plan
Course Aims and Objectives
• Learn the basic programming with java (Java Architecture, Tokens, Data types, Operators, Conditional and Looping
statements)
• Understand the Object-oriented programming with java using object-oriented concepts
• Learn the advanced java programming using exception handling, multithreading, file handling, and graphical
applications
• Lean basic concepts about Arrays and methods in java
• Classes and Objects - Creating Classes and Objects, Constructors, Method overloading, "this" Reference, Garbage
Collection
• Inheritance - Implementing Inheritance, Method overriding, "final" Keyword, Abstract Classes and Methods,
Dynamic Binding
• Leann the Exception Handling
• Learn how to use Java collections
• GUI Applications with Java Swing
• Learn basic Network programming with java
• Learn basic multithreading concepts
Textbooks
• Paul Deitel, Harvey Deitel, Java: How to Program, , Early Objects, 11th Edition.
• Cay S. Horstmann, Big Java: Late Objects
• Introduction to Java Programming and Data Structures, Comprehensive Version 12th
Edition, by Y. Liang (Author), Y. Daniel Liang
• Java documentation https://docs.oracle.com/javase
Data Types, Methods, 1D array and 2D array, Scanner, Methods, Operators,
Java basics If statement, loops.

OOP Classes, objects, Inheritance, Encapsulation, Abstraction, Polymorphism

Files Handling IO Text and Binary files

Exceptions Handling Exceptions

Topic JavaSwing Graphical User Interface Elements based JAvaSwing

covered Event Driven


programming
Mouse Listeners, Actions, Window listener

Collections ArrayList, List, Vecto , HashSet ,…..etc

DB JDBC - Java Database Connectivity


Threads and shared objects
Threads
Network Sockets Programming
Programming
Grade Policy

• Final 50
• Midterm 20
• Practical Quizzes 20
• Project 15
• Note total semester work grade is 50
• If the student gets a mark above 50, he will only
get 50.
Section
• Get involved with the story.
Practice.. Practice.. Practice..
Course Project Policy

01 02 03
Project groups: Each Project Must be GUI can be
group will be 4 to 5 implemented based implemented using
students. om MVC concept Swing or
Javafx[Bounce]
Academic Integrity

You can discuss ideas and methodology for the homework


(assignments / sheets) with other students in the course, but you
must write your solutions completely independently.

We will be code-checking to assess similar submissions or submissions


that use code from other sources.
Java Setting up

• Integrated Development Environment (IDE): IDE provides a sophisticated GUI and editor, with
integrated facilities for compiling, running, and debugging programs
• Java 2 Standard Edition SDK (Software Development Kit): //What we need..
• SDK includes everything you need to compile and run Java.
• SDK tools are used for compiling and running Java programs on a variety of platforms
• The Java compiler (javac) translates Java source into bytecode.
• The Java interpreter (java) translates and executes Java bytecode. Java interpreters are
available for many different computer systems.
• Java 2 Enterprise Edition (J2EE) → for large-scale systems
• Java 2 Micro Edition (J2ME) → for mobile phones
• Java 2 Standard Edition (J2SE) – Our Course -
Java Setting up
• We can work with Netbeans/Eclipse/ IntelliJ
• https://netbeans.org/downloads/
• https://eclipse.org/downloads/
• JDK
http://www.oracle.com/technetwork/java/javase/dow
nloads/index.html
• Java documentation https://docs.oracle.com/javase
Java Setting up For JavaFX
• Install first the JDK and We will use Zulu JDK-fx
• Java Download | Java 7, Java 8, Java 11, Java 13, Java 15, Java 17, Java
19 - Linux, Windows & macOS (azul.com)
• IntelliJ IDEA Community Edition
• Download IntelliJ IDEA: The Capable & Ergonomic Java IDE by
JetBrains
• We will use Scene Builder for GUI (Drag & Drop)
• Scene Builder - Gluon (gluonhq.com)
Video for
Configuration
• https://youtu.be/LTgClBqDank
What Is JDK?

• JDK, or Java Development


Kit, consists of tools that we
use JDK to develop and run
Java code. Before
developing and running Java
code, you should install it on
your computer or system.
• The picture represents the
structure of JDK
What Is JDK?
• The Java Development Kit (JDK) is a software development
environment used for developing Java applications and applets.
• It includes the Java Runtime Environment (JRE), an interpreter/loader
(Java), a compiler (javac), an archiver (jar), a documentation
generator (Javadoc), and other tools needed in Java development.
What Is JDK?
As you see, JDK consists of JRE and Java development tools.
JRE or Java Runtime Environment is a package that provides an environment to only run
(not develop) the Java program(or application)on your machine. It is only used to run Java
programs.
JDT or Java Development tools consist of many tools like compilers, debuggers, and other
development tools.

The most important part of JDK and JRE is JVM ( Java Virtual Machine) and its
responsibility is the execution of code line-by-line. It's also known as an Interpreter. In the
following, we will get more acquainted with it.
Java Virtual Machine (JVM)
• The Java Virtual Machine is a specification that provides a runtime
environment in which java bytecode can be executed. It means JVM
creates a platform to run Java bytecode(.class file) and converting into
different languages (native machine language) which the computer
hardware can understand. Actually, there is nothing to install as JVM.
When the JRE is installed, it will deploy the code to create a JVM for
the particular platform. JVMs are available for many hardware and
software platforms.
How does Java Code Compile And Run?
Java (JRE)

(JVM)
javac

[ JIT ]
How does Java Code Compile And Run?

• Step 1: Writing the source and save it with extinction .java


• Step 2: compile the code in the command prompt by using the command
line or atomically with IDE javac filename.java).
• This invokes the Java Compiler. The compiler checks the code for syntax
errors and any other compile time errors and if no error is found the
compiler converts the java code into an intermediate code(filename.
class file) known as bytecode.
• This intermediate code is platform-independent (you can take this
bytecode from a machine running windows and use it in any other machine
running Linux or macOS etc).
• Also, this bytecode is an intermediate code, hence it is only understandable
by the JVM (Java Virtual Machine ) and not the user or even the hardware
/OS layer.
How does Java Code Compile And Run?

• Step 3: This is the start of the Run Time phase, where the bytecode is
loaded into the JVM by the class loader(another inbuilt program inside the
JVM).
• Step 4: Now the bytecode verifier checks the bytecode for its integrity and
if no issues are found passes it to the interpreter. For example, if in the
program, we use a variable that has not been declared, or if the run-time
stack overflows, it will throw an Exception and the compiling process will
stop.
• Step 5: Since java is both compiled and interpreted language, now the java
interpreter and Just in time Compiler (JIT) inside the JVM convert the
bytecode into executable machine code and passed it to the OS/Hardware
i.e. the CPU to execute.
Just in time Compiler (JIT)
• The JIT compiler allows Java to be both a compiled and
interpreted language. It combines the performance advantage
of a compiled language with the flexibility of an interpreted
language.
• While the JVM interprets bytecode, the JIT analyses execution
and dynamically compiles frequently executed bytecode to
machine code. This prevents the JVM from having to interpret
the same bytecode over and over.
How the JIT Compiler Works in Java
• The source code you write (.java) is compiled by javac to
bytecode. When your program executes, the JVM starts
interpreting this bytecode.
• The interpreter translates the bytecode into machine code and
feeds it to the CPU for processing.
• While this happens, the JIT profiles and analyses the code
execution. It tracks the most frequently called methods and
dynamically compiles these to machine code at runtime.
JVM(Java Virtual Machine)
• JVM(Java Virtual Machine) runs Java applications as a run-
time engine. JVM is the one that calls the main method present
in a Java code. JVM is a part of JRE(Java Runtime Environment).
• Java applications are called WORA (Write Once Run
Anywhere). This means a programmer can develop Java code
on one system and expect it to run on any other Java-enabled
system without any adjustment. This is all possible because of
JVM.
What is a JVM in Java?
• There are three main mechanisms inside the JVM as shown in the
above diagram.
• ClassLoader
• Memory Area
• Execution Engine
Next Lecture
What is a
JVM
in Java ?
Class
Loader
• The first class to be loaded
into memory is usually the
class that contains the
main() method.
• There are three phases in
the class loading process:
loading, linking, and
initialization.
Class Loader - Loading
• Bootstrap Class Loader - This is the root class loader. It is the superclass of
Extension Class Loader and loads the standard Java packages like java.lang,
java.net, java.util, java.io, and so on. These packages are present inside the
rt.jar file and other core libraries present in the $JAVA_HOME/jre/lib
directory.
• Extension Class Loader - This is the subclass of the Bootstrap Class Loader
and the superclass of the Application Class Loader. This loads the
extensions of standard Java libraries which are present in the
$JAVA_HOME/jre/lib/ext directory.
• Application Class Loader - This is the final class loader and the subclass of
Extension Class Loader. It loads the files present on the classpath. By
default, the classpath is set to the current directory of the application. The
classpath can also be modified by adding the -classpath or -cp command
line option.
Class Loader - Loading
• The JVM uses the ClassLoader.loadClass() method for loading the
class into memory.
• If a parent class loader is unable to find a class, it delegates the work
to a child class loader. If the last child class loader isn't able to load
the class either, it throws NoClassDefFoundError or
ClassNotFoundException.
Class Loader - Linking - Verification
• After a class is loaded into memory, it undergoes the linking process.
Linking a class or interface involves combining the different elements
and dependencies of the program together.
• Linking includes the following steps:
• Verification: This phase checks the structural correctness of the .class
file by checking it against a set of constraints or rules. If verification
fails for some reason, we get a VerifyException.
• For example, if the code has been built using Java 11, but is being run
on a system that has Java 8 installed, the verification phase will fail.
Class Loader - Linking - Preparation
• Preparation: After a Java virtual machine has loaded a class and
performed whatever verification it chooses to do up front, the class is
ready for preparation. During the preparation phase, the Java virtual
machine allocates memory for the class variables and sets them to
default initial values. The class variables are not initialized to their
proper initial values until the initialization phase. (No Java code is
executed during the preparation step.) During preparation, the Java
virtual machine sets the newly allocated memory for the class
variables to a default value determined by the type of the variable.
Class Loader - Linking - Resolution
• Resolution
• Resolution involves replacing symbolic references in the bytecode with
actual references to memory locations. In the class file, references to other
classes, methods, or fields are stored symbolically (using names or
constants), and during resolution, these are mapped to actual addresses in
memory.
• The JVM resolves symbolic references like class names, field names, and
method signatures into direct references that point to actual memory
addresses.
• It links classes with their superclasses and interfaces.
• The symbolic references are replaced with concrete references, allowing
the JVM to call methods and access fields directly.
Class Loader - Initialization
• Initialization involves executing the initialization method of the class
or interface (known as <clinit>).
• This can include calling the class's constructor, executing the static
block, and assigning values to all the static variables. This is the final
stage of class loading.
Runtime Data Area
• There are five components inside the runtime data area:

Runtime Data Area - method area
• method area is shared among all Java Virtual Machine threads. The
method area is analogous to the storage area for compiled code of a
conventional language or analogous to the "text" segment in an
operating system process. It stores per-class structures such as the
run-time constant pool, field and method data, and the code for
methods and constructors, including the special methods used in
class and instance initialization and interface initialization.
• In the method area, all class level information like class name,
immediate parent class name, methods and variables information etc.
are stored, including static variables. There is only one method area
per JVM, and it is a shared resource.
Runtime Data Area - heap area
• The Java Virtual Machine has a heap that is shared among all
Java Virtual Machine threads. The heap is the run-time data
area from which memory for all class instances and arrays is
allocated.
• All the objects and their corresponding instance variables are
stored here.
• Note: Since the Method and Heap areas share the same memory
for multiple threads, the data stored here is not thread safe.
Runtime Data Area - Stack area
• Stack area: For every thread, JVM creates one run-time stack
which is stored here. Every block of this stack is called
activation record/stack frame which stores methods calls. All
local variables of that method are stored in their corresponding
frame. After a thread terminates, its run-time stack will be
destroyed by JVM. It is not a shared resource.
• Note: Since the Stack Area is not shared, it is inherently thread
safe.

Runtime Data Area
• PC Registers: Store address of current execution instruction of
a thread. Obviously, each thread has separate PC Registers.
• Native method stacks: The JVM contains stacks that
support native methods. These methods are written in a language
other than the Java, such as C and C++. For every new thread, a
separate native method stack is also allocated..
Execution Engine
• Once the bytecode has been loaded into the main memory, and
details are available in the runtime data area, the next step is to
run the program. The Execution Engine handles this by executing
the code present in each class.
Execution Engine
• Interpreter
• The interpreter reads and executes the bytecode instructions line by line.
Due to the line by line execution, the interpreter is comparatively slower.
• Another disadvantage of the interpreter is that when a method is called
multiple times, every time a new interpretation is required.
• JIT Compiler
• The JIT Compiler overcomes the disadvantage of the interpreter. The
Execution Engine first uses the interpreter to execute the byte code, but
when it finds some repeated code, it uses the JIT compiler.
• The JIT compiler then compiles the entire bytecode and changes it to native
machine code. This native machine code is used directly for repeated
method calls, which improves the performance of the system.
Execution Engine
• The JIT Compiler has the following components:
1.Intermediate Code Generator - generates intermediate code
2.Code Optimizer - optimizes the intermediate code for better
performance
3.Target Code Generator - converts intermediate code to native
machine code
4.Profiler - finds the hotspots (code that is executed repeatedly)
Execution Engine
• An interpreter will fetch the value of sum
from memory for each iteration in the loop,
add the value of i to it, and write it back to
memory. This is a costly operation because
it is accessing the memory each time it
enters the loop.
• However, the JIT compiler will recognize
that this code has a HotSpot, and will
perform optimizations on it. It will store a
local copy of sum in the PC register for the
thread and will keep adding the value of i to
it in the loop. Once the loop is complete, it
will write the value of sum back to memory.
Garbage Collector
• Garbage collection makes Java memory efficient because because it
removes the unreferenced objects from heap memory and makes
free space for new objects. It involves two phases:
• Mark - in this step, the GC identifies the unused objects in memory
• Sweep - in this step, the GC removes the objects identified during the
previous phase
• Garbage Collections is done automatically by the JVM at regular
intervals and does not need to be handled separately. It can also be
triggered by calling System.gc(), but the execution is not guaranteed.
Java Native Interface (JNI)
• At times, it is necessary to use native (non-Java) code (for example, C/C++). This
can be in cases where we need to interact with hardware, or to overcome the
memory management and performance constraints in Java. Java supports the
execution of native code via the Java Native Interface (JNI).
• JNI acts as a bridge for permitting the supporting packages for other
programming languages such as C, C++, and so on. This is especially helpful in
cases where you need to write code that is not entirely supported by Java, like
some platform specific features that can only be written in C.
• You can use the native keyword to indicate that the method implementation
will be provided by a native library. You will also need to invoke
System.loadLibrary() to load the shared native library into memory, and make
its functions available to Java.
Native Method Libraries
• Native Method Libraries are libraries that are written in other
programming languages, such as C, C++, and assembly.
• These libraries are usually present in the form of .dll or .so files. These
native libraries can be loaded through JNI.
References
• Java: How To Program, Early Objects, 11th edition
• Setup IntelliJ IDEA (2021) for JavaFX & SceneBuilder and Create Your First JavaFX Application – YouTube
• Introduction to Java Programming and Data Structures, Comprehensive Version 12th Edition, by
Y. Liang (Author), Y. Daniel Liang
• Java documentation https://docs.oracle.com/javase
• https://www.youtube.com/watch?v=LTgClBqDank&feature=youtu.be
• Understanding Java Virtual Machine (JVM) Architecture | by Jalitha Dewapura | Java For Beginners | Medium
• JVM Tutorial - Java Virtual Machine Architecture Explained for Beginners (freecodecamp.org)
• How JVM Works - JVM Architecture – GeeksforGeeks
• Chapter 2. The Structure of the Java Virtual Machine (oracle.com)
• JVM Internals (jamesdbloom.com)
Usage of native in Java - Stack Overflow
Java Type Loading, Linking, and Initialization (artima.com)
Thanks
Advanced Programming Language
Dr. Ahmed Hesham Mostafa
Dr. Mohamed Atia
Lectures 1 – Java Basics
• Class name
• Main method
Java • Statements
Program • Statement terminator
Components • Reserved words
• Comments
• Blocks

2
Class Name
• Every Java program must have at least one class.
• Each class has a name.
• By convention, class names start with an uppercase letter.
• In this example, the class name is Welcome.

// This program prints Welcome to Java!


public class Welcome {
public static void main(String[] args) {
System.out.println("Welcome to Java!");
}
}

3
Main Method
• Line 2 defines the main method.
• In order to run a class, the class must contain a method named main.
• The program is executed from the main method.

// This program prints Welcome to Java!


public class Welcome {
public static void main(String[] args) {
System.out.println("Welcome to Java!");
}
}

4
Statement
• A statement represents an action or a sequence of actions.
• The statement System.out.println("Welcome to Java!") in the program
displays the greeting "Welcome to Java!“.

// This program prints Welcome to Java!


public class Welcome {
public static void main(String[] args) {
System.out.println("Welcome to Java!");
}
}

5
Statement Terminator
Every statement in Java ends with a semicolon (;).

// This program prints Welcome to Java!


public class Welcome {
public static void main(String[] args) {
System.out.println("Welcome to Java!");
}
}

6
Keywords
• Keywords are words that have a specific meaning to the compiler and
cannot be used for other purposes in the program.
• For example, when the compiler sees the word class, it understands
that the word after class is the name for the class.

// This program prints Welcome to Java!


public class Welcome {
public static void main(String[] args) {
System.out.println("Welcome to Java!");
}
}

7
Blocks
• A pair of braces in a program forms a block that groups
components of a program.

public class Test {


public static void main(String[] args) { Class block
System.out.println("Welcome to Java!"); Method block
}
}

8
Special Symbols

Character Name Description

{} Opening and closing Denotes a block to enclose statements.


braces
() Opening and closing Used with methods.
parentheses
[] Opening and closing Denotes an array.
brackets
// Double slashes Precedes a comment line.

" " Opening and closing Enclosing a string (i.e., sequence of characters).
quotation marks
; Semicolon Marks the end of a statement.

9
Reading Input from the Console
• 1. Import Scanner class
import java.util.Scanner;
• 2. Create a Scanner object
Scanner input = new Scanner(System.in);
• 3. Use the methods next(), nextByte(), nextShort(), nextInt(), nextLong(),
nextFloat(), nextDouble(), or nextBoolean() to obtain to a string, byte, short, int,
long, float, double, or boolean value. For example,
System.out.print("Enter a double value: ");
Scanner input = new Scanner(System.in);
double d = input.nextDouble();

10
Methods for Scanner Objects

11
import java.util.Scanner;
Example public class Main {
public static void main(String[] args) {
Scanner myObj = new Scanner(System.in);
System.out.println("Enter name, age and salary:");
String name = myObj.nextLine();
int age = myObj.nextInt();
double salary = myObj.nextDouble();
System.out.println("Name: " + name);
System.out.println("Age: " + age);
System.out.println("Salary: " + salary);
}
}
Example
Output
An identifier is a sequence of characters that consists of
letters, digits, underscores (_), and dollar signs ($).

An identifier must start with a letter, an underscore (_),


or a dollar sign ($). It cannot start with a digit.

An identifier cannot be a reserved word. (See Appendix


Identifiers A, “Java Keywords,” for a list of reserved words).

An identifier cannot be true, false, or null.

An identifier can be of any length.

14
Data types
Java is a strongly typed language

• This means that every variable and expression has a type when the program is compiled and
that you cannot arbitrarily assign values of one type to another.

There are two categories of type in Java:

• Primitive Data Types store data values.


• Non- Primitive Data Types do not themselves store data values but are used to refer to
objects. such as Strings, Arrays, and Classes

Data type sizes in Java are fixed

• to ensure portability across implementations of the language.

15
Primitive Data Types
Data types
Declaration and initialization:
• we can reserve memory locations for storing values of any primitive type. Those
memory locations can then be made to contain values that are legal for the particular
type. This involves two steps.
1) Declaration: Create a variable of the type you want to use.
2) Initialization: This refers to when you first store something useful in a variable's
memory location.

-Case sensitive
Do not
-use Reserved words
-start with number

17
• Constants “you can not change the value”
Data types

18
Data types
Casting
• There are occasions where we want to be able to convert from one type to another. This
can be done either:
• Automatically: Java does it for us.
• By casting: we have to specify a type conversion.
• By writing the desired type of an expression in parentheses in front of the
expression; for example, write (int) in front of an expression if we wanted it to be
converted to an int.
• Note that the fractional parts of a float data type are lost if casting to an integral type.
Ex. Casting a double to an int. Example: Casting an int to a char
c will have the value
60, which is the 61st
character in the
Unicode set. This
turns out to be the
character '<'.
intVal will have the value of 2
19
Example
public class Main { Output
public static void main(String[] args) {
double doubleVal=2.8;
int intVal= (int) doubleVal;
System.out.println("intVal = "+intVal);

int a=35,b=12,d=13;
char valC=(char)(a+b+d);
System.out.println("valC = "+valC);
}
}
Data types
• When is a cast required?
• A cast is required if the type you are assigning (on the right-hand side of an
equals sign) occupies a larger space in memory than the type you are
assigning to (on the left-hand side of an equals sign).
• If you have not specified a cast in a case where a cast is required, the compiler
will produce a compilation error with the message that there is a 'possible
loss of precision.

Not Allowed assign smaller


integer with big Double
Strings
• A string is a sequence of characters.
• For example, a string could be used to store a person's name
• Strings are represented using the reference type called String
Strings
The length method
• For example: name.length()
• This evaluates to the number of characters in the string referenced by name.
• If this string were "Roderick", the length method would return the value 8.
• The empty string has a length of zero.
String concatenation (+)
• The concatenation operator, +, will automatically turn any arguments
into strings before carrying out a concatenation.

23
Strings
More string methods

24
Example
public class Main {
public static void main(String[] args) {

String txt = "Hello World My Friend";


System.out.println("The txt length : " + txt.length());
System.out.println(txt.toUpperCase());
System.out.println(txt.toLowerCase());
System.out.println("World locate at : "+txt.indexOf("World"));
}
}
Reading a String from the Console
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.println("Enter First String: ");
String First = input.nextLine();
System.out.println("Enter Second String: ");
String Second = input.next();
System.out.println("First String is : "+First);
System.out.println("First Second is : "+Second);
}
}

26
Reading a Character from the
Console
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.println("Enter a character: ");
String s = input.nextLine();
char ch = s.charAt(0);
System.out.println("The character entered is " + ch);
}
}

27
Comparing Strings
Method Description

equals(s1) Returns true if this string is equal to string s1 .


equalsIgnoreCase(s1) Returns true if this string is equal to string s1 ; it is case insensitive.
compareTo(s1) Returns an integer greater than 0 , equal to 0 , or less than 0 to indicate whether
this string is greater than, equal to, or less than s1 .
compareToIgnoreCase(s1) Same as compareTo except that the comparison is case insensitive.
startsWith(prefix) Returns true if this string starts with the specified prefix.
endsWith(suffix) Returns true if this string ends with the specified suffix.

Note : the == operator is used to compare two object references to see whether they refer to the same instance.

28
Obtaining Substrings
Method Description

substring(beginIndex) Returns this string’s substring that begins with the character at the specified
beginIndex and extends to the end of the string, as shown in Figure 4.2.

substring(beginIndex, Returns this string’s substring that begins at the specified beginIndex and
endIndex) extends to the character at index endIndex – 1, as shown in Figure 9.6.
Note that the character at endIndex is not part of the substring.

29
Finding a Character or a Substring in a
String
Method Description

indexOf(ch) Returns the index of the first occurrence of ch in the string. Returns -1 if not
matched.
indexOf(ch, fromIndex) Returns the index of the first occurrence of ch after fromIndex in the string.
Returns -1 if not matched.
indexOf(s) Returns the index of the first occurrence of string s in this string. Returns -1 if
not matched.
indexOf(s, fromIndex) Returns the index of the first occurrence of string s in this string after
fromIndex. Returns -1 if not matched.
lastIndexOf(ch) Returns the index of the last occurrence of ch in the string. Returns -1 if not
matched.
lastIndexOf(ch, Returns the index of the last occurrence of ch before fromIndex in this
fromIndex) string. Returns -1 if not matched.
lastIndexOf(s) Returns the index of the last occurrence of string s. Returns -1 if not matched.
lastIndexOf(s, Returns the index of the last occurrence of string s before fromIndex.
fromIndex) Returns -1 if not matched.
30
Finding a Character or a Substring in a
String
int k = s.indexOf(' ');
String firstName = s.substring(0, k);
String lastName = s.substring(k + 1);

31
public class Main {
Example public static void main(String[] args) {
String mes="welcome to java";
System.out.println(mes.substring(11));
System.out.println(mes.substring(0,11));
int k = mes.indexOf(' ');
String first = mes.substring(0, k);
String last = mes.substring(k + 1);
System.out.println("First ="+first);
System.out.println("last ="+last);
}
}
Conversion between Strings and
Numbers
public class Main {
public static void main(String[] args) {
String intString ="5";
int intValue = Integer.parseInt(intString);
String doubleString ="5.0";
double doubleValue = Double.parseDouble(doubleString);
System.out.println("intValue= "+intValue);
System.out.println("doubleValue= "+doubleValue);
}
}

33
public class Main {
public static void main(String[] args) {
Example String str1 = “Cat";
String str2 = “Cat";
String str3 = new String(str1);
String str4 = “CAT";
System.out.println("str1.equals(str2): "+str1.equals(str2));
System.out.println("str1==str2 : "+(str1==str2));
System.out.println("str1==str3 : "+(str1==str3));
System.out.println("str1.equalsIgnoreCase(str4) : "+str1.equalsIgnoreCase(str4));
System.out.println("str1.compareTo(str2) : "+str1.compareTo(str2));
System.out.println("str1.compareTo(str3) : "+str1.compareTo(str4));
}
}

4
String Pool
• String str1 = “Cat";
String str2 = “Cat";
String str3 = new String(str1);
• So, the question here is why str1==str2 is true while str1==str3 is false
• This is because String Pool in java Heap memory (part of JVM)
• String pool helps in saving a lot of space for Java Runtime although it takes
more time to create the String. When we use double quotes to create a
String, it first looks for a String with the same value in the String pool, if
found it just returns the reference else it creates a new String in the pool
and then returns the reference.
• However, using new operator, we force String class to create a new String
object in heap space.
String Pool
Java Strings are immutable
• The string is immutable means
once we created a string variable
we cannot modify it.
• Objects in Java are created in heap
memory. So String objects are also
created in the heap. But here the
thing is, there is a special memory
area to store strings in Java,
known as String Constant Pool.
Assume we create a String variable
as below.
• String str1 = "Java";
• This is how it is stored inside the
memory.
Java Strings are immutable
• References are stored in a memory area called stack. So “str ”will be
placed in the stack and “Java” will be stored in the string constant
pool. And str1 refers to the string object Java.

• Now, what will happen if we add the str2 variable with the same
value “Java”. Will it create another object as “Java” to refer to the
str2?

• String str1 = "Java";


• String str2 = "Java";
Java Strings are immutable
• Not actually. str2 will also be
referring to the same string
object “Java” inside the heap
memory.
• No matter how many variables
are created with the same string
object that is already contained
in the string constant pool, it
will always refer to the same
String object.
Java Strings are immutable
• Then how about this code
• String str1 = "Java";
String str2 = "Java";
Str1 = "Python";
• A new String object “Python”
will be created and str1 will be
referred to it. str2 is still refering
to “Java”.
Java Strings are immutable
• Just think about this. The string
“Java” was not replaced by the
new string “Python”. So, here it
is changing the reference, not
the actual object. That’s why
strings are immutable. Once we
created a string object, we
cannot change it.
Java Strings are immutable
• Then how about this code
• String str = "Java";
str.concat(" Python")
System.out.println(str);
• A new string object “Java
Python” will be created in the
string constant pool. But
Nothing has happened to the
“Java” string object and
still str is referring to that. So
the output will be “Java” not
“Java Python”.
Java Strings are immutable
• We can have mutable strings with the aid of StringBuffer and
StringBuilder in Java.
• The biggest benefit is that the same string object will be shared for
multiple references. This allows for saving a lot of memory which
makes efficient memory usage.
StringBuffer

public class Main {


public static void main(String[] args) {
StringBuffer sb = new StringBuffer("Hello ");
sb.append("Java"); // now original string is changed
System.out.println(sb); }
}

• The StringBuffer class in java is same as String class except it is


mutable i.e. it can be changed.
StringBuilder
public class Main {
public static void main(String[] args) {
StringBuilder str = new StringBuilder(" Hello ");
str.append("Java"); // now original string is changed
System.out.println(str); }
}

• The StringBuilder class in java is same as String class except it is


mutable i.e. it can be changed.
StringBuffer VS StringBuilder

StringBuffer StringBuilder
Thread Safe Not Thread Safe
Synchronized Not Synchronized
Since Java 1.0 Since Java 1.5
Slower Faster
Operators
• Arithmetic operators
Operators
• Relational operators
Operators
Logical operators

Example:
• The variable eitherPositive is assigned the value true,
because a > 0 is true and therefore the whole expression is
true (even though b > 0 is false).
• The variable bothNegative is assigned the value false
because a < 0 is false, and
• therefore the whole expression is false. Even though b < 0
is true.

49
Augmented Assignment Operators

50
Increment and
Decrement Operators

51
Conditional processing
• The flow control structures determine the way in which a Java program is executed, allowing different
segments of code to be executed under different circumstances.

• If the logical_expression within the parentheses evaluates to true, then any statements in the following
code block are executed. If the logical_expression is false, then any statements in the body of the if
statement are not executed.
Example:

52
Conditional processing

if (number % 2 == 0) Equivalent
even = true; boolean even
else = number % 2 == 0;
even = false;
(a) (b)

Equivalent if (even)
if (even == true)
System.out.println( System.out.println(
"It is even."); "It is even.");
(a) (b)

53
Multiple Alternative if Statements

if (score >= 90.0) if (score >= 90.0)


System.out.print("A"); System.out.print("A");
else else if (score >= 80.0)
if (score >= 80.0) Equivalent System.out.print("B");
System.out.print("B"); else if (score >= 70.0)
else System.out.print("C");
if (score >= 70.0) else if (score >= 60.0)
System.out.print("C"); System.out.print("D");
else else
if (score >= 60.0) System.out.print("F");
System.out.print("D"); This is better
else
System.out.print("F");

(a) (b)
54
Multiple Alternative if Statements
The else clause matches the most recent if clause in the same block.

55
Conditional Operators
if (x > 0)
y=1
else
y = -1;

is equivalent to

y = (x > 0) ? 1 : -1;
(boolean-expression) ? expression1 : expression2

56
Conditional Operator
public class Main {
public static void main(String[] args) {
int num=5;
if (num % 2 == 0)
System.out.println(num + " is even");
else
System.out.println(num + " is odd");
System.out.println((num % 2 == 0)? num + " is even" : num + " is odd");
}
}

57
switch Statements
switch (status) {
case 0: stmat;
break;
case 1: stmat;
break;
case 2: stmat;
break;
case 3: stmat;
break;
default: System.out.println("Errors: invalid status");
System.exit(1);
}
58
switch Statement Rules
The switch expression must yield a value of
char, byte, short, or int type It also works switch (switch-expression) {
with enumerated types (discussed in Enum
Types), the String class, and a few special case value1: statement(s)1;
classes that wrap certain primitive types: break;
Character, Byte, Short, and Integer and must
always be enclosed in parentheses. case value2: statement(s)2;
break;

The value1, ..., and valueN must have the same case valueN: statement(s)N;
data type as the value of the switch expression. break;
The resulting statements in the case statement are
default: statement(s)-for-default;
executed when the value in the case statement
matches the value of the switch expression. Note }
that value1, ..., and valueN are constant
expressions, meaning that they cannot contain
variables in the expression, such as 1 + x.

59
switch Statement Rules

The keyword break is optional, but it switch (switch-expression) {


should be used at the end of each case value1: statement(s)1;
case in order to terminate the break;
remainder of the switch statement. If
the break statement is not present, case value2: statement(s)2;
the next case statement will be break;
executed. …
case valueN: statement(s)N;
The default case, which is optional, break;
can be used to perform actions when default: statement(s)-for-default;
none of the specified cases matches }
the switch expression.
When the value in a case statement matches the value
of the switch-expression, the statements starting from
this case are executed until either a break statement or
the end of the switch statement is reached.

60
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Example
System.out.println("Enter Daya : ");
Scanner inp=new Scanner(System.in);
int day= inp.nextInt();
switch (day) {
case 1:System.out.println("1");
case 2:System.out.println("2");
case 3:System.out.println("3");
case 4:System.out.println("4");
case 5: System.out.println("Weekday"); break;
case 0:System.out.println("0");
case 6: System.out.println("Weekend");
}
}
}
Repetitive processing
• Java allow sections of code to be executed repeatedly while some
condition is satisfied → iteration!

Example:

62
Repetitive processing

Examples:

Can you figure out how


this loop is executed??

63
Example
public class Main {
public static void main(String[] args) {
int sum = 0;
int n = 1000;
for (int i = 1; i <= n; ++i) { Sum = 500500
sum += i;
}
System.out.println("Sum = " + sum);
}
}
Repetitive processing
• The initial action in a for loop can be a list of zero or more comma-
separated expressions.
• The action-after-each-iteration in a for loop can be a list of zero or
more comma-separated statements.
• But the control statement in for loop is only one statement
• Therefore, the following two for loops are correct. They are rarely
used in practice, however.
• for (int i = 1; i < 100; System.out.println(i++));
• for (int i = 0, j = 0; (i + j < 10); i++, j++) {
// Do something}
65
public class Main { public class Main {
public static void main(String[] args) { public static void main(String[] args) {
for(int i=1;i<10;System.out.println(i++));
}
for(int i=0,j=0;(i+j<5);i++,j++){
} System.out.println("i= "+i+" and j= "+j);
}
}
}
Repetitive processing
• If the loop-continuation condition in a for loop is omitted, it is
implicitly true.
• Thus the statement given below in (a), which is an infinite loop, is
correct. Nevertheless, it is better to use the equivalent loop in (b) to
avoid confusion:

for ( ; ; ) { Equivalent while (true) {


// Do something // Do something
} }
(a) (b)

67
import java.util.Scanner;
public class Main {
public static void main(String[] args) { Example
int sum = 0;
Scanner input = new Scanner(System.in); Enter a number
System.out.println("Enter a number"); 25
int number = input.nextInt(); Enter a number
9
while (number >= 0) { Enter a number
sum += number; 5
System.out.println("Enter a number"); Enter a number
-3
number = input.nextInt(); Sum = 39
}
System.out.println("Sum = " + sum);
input.close();
}
}
Example
public class Main {
public static void main(String[] args) {
int i = 1, n = 5;
do { 1

System.out.println(i); 2
3
4
i++; 5

} while(i <= n);


}
}
Programming Errors

Syntax Errors
• Detected by the compiler

Runtime Errors
• Causes the program to abort

Logic Errors
• Produces incorrect result

70
Syntax Errors

public class ShowSyntaxErrors {


public static main(String[] args) {
System.out.println("Welcome to Java);
}
}

//miss the right “ double quotation

71
Runtime Errors

public class ShowRuntimeErrors {


public static void main(String[] args) {
System.out.println(1 / 0);
}
} Exception in thread "main" java.lang.ArithmeticException: / by zero
at Main.main(Main.java:3)

Division on zero

72
Logic Errors

public class Main {


public static void main(String[] args) {
System.out.println("Celsius 35 is Fahrenheit degree ");
System.out.println((9 / 5) * 35 + 32);
}
} Integer division will give wrong
total value

If replaced with → System.out.println((9.0 / 5.0) * 35 + 32);

73
Common Error : Undeclared/Uninitialized
Variables and Unused Variables

public class Main {


public static void main(String[] args) {
double a;
double x= 6*a;
}
}

74
Common Error : Integer Overflow

int value = 2147483647 + 1;


// value will actually be -2147483648
Int is 4 byte so max number can be represented by
int is [(2^31) -1]= 2147483647

75
Common Error : Round-off Errors
public class Main {
public static void main(String[] args) {
System.out.println(1.0 - 0.1 - 0.1 - 0.1 - 0.1 - 0.1);
System.out.println(1.0 - 0.9);

}
}

76
Common Error : Round-off Errors
• A round-off error, also called a rounding error, is the difference
between the calculated approximation of a number and its exact
mathematical value.
• For example, 1/3 is approximately 0.333 if you keep three decimal
places, and is 0.3333333 if you keep seven decimal places.
• Since the number of digits that can be stored in a variable is limited,
round-off errors are inevitable.
• Calculations involving floating-point numbers are approximated
because these numbers are not stored with complete accuracy.
Common Error : Unintended Integer
Division
int number1 = 1; int number1 = 1;
int number2 = 2; int number2 = 2;
double average = (number1 + number2) / 2; double average = (number1 + number2) / 2.0;
System.out.println(average); System.out.println(average);

(a) (b)

• Java uses the same divide operator, namely /, to perform both integer and
floating-point division.
• When two operands are integers, the / operator performs an integer division.
The result of the operation is an integer. The fractional part is dropped.
• To force two integers to perform a floating-point division, make one of the
integers into a floating-point number.
78
Common Errors
• Adding a semicolon at the end of an if clause is a common mistake.
if (radius >= 0); Wrong
{
area = radius*radius*PI;
System.out.println("The area for the circle of radius " + radius + " is " + area);
}
• This mistake is hard to find, because it is not a compilation error or a runtime
error, it is a logic error.
• This error often occurs when you use the next-line block style.

79
public class Main {
public static void main(String[] args) {
Common Errors
double radius=-1,area,PI= 3.14;
if (radius >= 0);
{
area = radius*radius*PI;
System.out.println("The area for the circle of radius " + radius + " is " + area);
} }
}
Common Errors
Adding a semicolon at the end of the for clause before the loop body is
a common mistake, as shown below (similar to previous example:

Logic
Error

for (int i=0; i<10; i++);


{
System.out.println("i is " + i);
}

81
public class Main { Common Errors
public static void main(String[] args) {
int i=0;
for (i=0; i<10; i++);
{
System.out.println("i is " + i);
}
}
}

public class Main {


public static void main(String[] args) {
for (int i=0; i<10; i++); What is the Output from this
{ code?
System.out.println("i is " + i);
}
}
}
Common Errors
• Similarly, the following loop is also wrong:
int i=0;
while (i < 10); Logic Error
{
System.out.println("i is " + i); What is the Output from this
code?
i++;
}
• In the case of the do loop, the following semicolon is needed to
end the loop.
int i=0;
do {
System.out.println("i is " + i);
i++;
} while (i<10); Correct

83
Common Pitfall : Redundant Input
Objects
Scanner input = new Scanner(System.in);
System.out.print("Enter an integer: ");
int v1 = input.nextInt();
Scanner input1 = new Scanner(System.in);
System.out.print("Enter a double value: ");
double v2 = input1.nextDouble();
The code is not good. It creates two input objects unnecessarily
and may lead to some errors. 84
Thanks
MCQ Questions
• Solve Ch 1,2,3,4,5
• https://media.pearsoncmg.com/ph/esm/ecs_liang_ijp_12/cw/#selfte
st
References
• Java: How To Program, Early Objects, 11th edition
• Cay S. Horstmann, Big Java: Late Objects
• Setup IntelliJ IDEA (2021) for JavaFX & SceneBuilder and Create Your First JavaFX Application –
YouTube
• Introduction to Java Programming and Data Structures, Comprehensive Version 12th Edition, by
Y. Liang (Author), Y. Daniel Liang
• Java documentation https://docs.oracle.com/javase
• https://www.youtube.com/watch?v=LTgClBqDank&feature=youtu.be
• https://medium.com/java-for-beginners/understanding-java-virtual-machine-jvm-architecture-
e68d1c611026
• https://medium.com/@mohamedathan3/architecture-of-java-virtual-machine-c628c6b034f4
References
• https://medium.com/javarevisited/how-java-code-compiled-and-run-e4702fb83ffa
• https://simplesnippets.tech/execution-process-of-java-program-in-detail-working-of-just-it-
time-compiler-jit-in-detail/
• JVM Architecture - MindScripts Tech
• compilation - Is Java a Compiled or an Interpreted programming language ? - Stack Overflow
• What is Java String Pool? | DigitalOcean
• https://blog.devgenius.io/java-string-is-immutable-what-does-it-actually-mean-6c7e9194a007
• StringBuffer class in Java – GeeksforGeeks
• StringBuilder Class in Java with Examples – GeeksforGeeks
• String vs StringBuffer vs StringBuilder | DigitalOcean
Advanced Programming Language
Dr. Ahmed Hesham Mostafa
Dr. Mohamed Atia
Lecture 2 – Java Basics
Single Array

Keywords Multiple Dimensions array

Methods

2
Defining Methods

A method is a collection of statements that are grouped


together to perform an operation.
Define a method Invoke a method

int z = max(x, y);


public static int max(int num1, int num2) {
actual parameters
int result; (arguments)

if (num1 > num2)


result = num1;
else
result = num2;

return result;
}

3
Defining Methods

A method is a collection of statements that are grouped


together to perform an operation.
Define a method Invoke a method

return value method formal


modifier type name parameters
int z = max(x, y);
method
public static int max(int num1, int num2) {
header
actual parameters
int result; (arguments)
method
body parameter list
if (num1 > num2)
result = num1;
else
method
result = num2; signature

return result; return value


}

4
Method Signature

Method signature is the combination of the method name and the parameter list.

Define a method Invoke a method

return value method formal


modifier type name parameters
int z = max(x, y);
method
public static int max(int num1, int num2) {
header
actual parameters
int result; (arguments)
method
body parameter list
if (num1 > num2)
result = num1;
else
method
result = num2; signature

return result; return value


}

5
Formal Parameters

The variables defined in the method header are known as formal


parameters.

Define a method Invoke a method

return value method formal


modifier type name parameters
int z = max(x, y);
method
public static int max(int num1, int num2) {
header
actual parameters
int result; (arguments)
method
body parameter list
if (num1 > num2)
result = num1;
else
method
result = num2; signature

return result; return value


}

6
Actual Parameters

When a method is invoked, you pass a value to the parameter. This value is referred
to as actual parameter or argument.

Define a method Invoke a method

return value method formal


modifier type name parameters
int z = max(x, y);
method
public static int max(int num1, int num2) {
header
actual parameters
int result; (arguments)
method
body parameter list
if (num1 > num2)
result = num1;
else
method
result = num2; signature

return result; return value


}

7
Return Value Type
A method may return a value. The returnValueType is the data type of the value the
method returns. If the method does not return a value, the returnValueType is the
keyword void. For example, the returnValueType in the main method is void.

Define a method Invoke a method

return value method formal


modifier type name parameters
int z = max(x, y);
method
public static int max(int num1, int num2) {
header
actual parameters
int result; (arguments)
method
body parameter list
if (num1 > num2)
result = num1;
else
method
result = num2; signature

return result; return value


}

8
Call Stacks

9
Caution
A return statement is required for a value-returning method. The method shown
below in (a) is logically correct, but it has a compilation error because the Java
compiler thinks it possible that this method does not return any value.

public static int sign(int n) { public static int sign(int n) {


if (n > 0) Should be if (n > 0)
return 1; return 1;
else if (n == 0) else if (n == 0)
return 0; return 0;
else if (n < 0) else
return –1; return –1;
} }
(a) (b)

To fix this problem, delete if (n < 0) in (a), so that the compiler will see a return
statement to be reached regardless of how the if statement is evaluated.

10
Single Arrays
Arrays
• way of creating an array is as follows:
int[] holder = new int[5];
Here, we have only stated that there should be room for five integers to be stored. We can
initialize these elements (they will default to the value 0) using assignment to individual
locations:
holder[0]= 1;
holder[1]= 1;
holder[2]= 1;
holder[3]= 1;
holder[4]= 1;
• This is equivalent to the following:
int[] myArray = {1,1,1,1,1};

12
Arrays

Assigning values to individual elements


• Example of changing the value stored in holder's second location to 10:
holder [1]= 10;

Changing an array reference


• As with strings (and it is true of all references), we can make an array reference variable refer to a
different object.
int[] holder2 = {1, 2, 3};
holder = holder2;

13
Arrays

The array instance variable length


• Arrays have an instance variable length, which gives the capacity of the array. The expression:
holder.length
represents the number of locations in the array holder.

• Note that length is an instance variable associated with arrays, while length() is a
method associated with strings.

14
Default Values
• When an array is created, its elements are assigned the
default value of :
• 0 for the numeric primitive data types
• '\u0000' for char types
• false for boolean types.

15
Indexed Variables
• The array elements are accessed through the index.
• The array indices are 0-based, i.e., it starts from 0 to
arrayRefVar.length-1.
• Each element in the array is represented using the following
syntax, known as an indexed variable: arrayRefVar[index];

16
Declaring, creating, initializing Using
the Shorthand Notation

double[] myList = {1.9, 2.9, 3.4, 3.5};


This shorthand notation is equivalent to the following statements:
double[] myList = new double[4];
myList[0] = 1.9;
myList[1] = 2.9;
myList[2] = 3.4;
myList[3] = 3.5;

17
Caution
•Using the shorthand notation, you have to
declare, create, and initialize the array all in
one statement.
• Splitting it would cause a syntax error. For
example, the following is wrong:
double[] myList;

myList = {1.9, 2.9, 3.4, 3.5};

18
Initializing arrays with input values
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
double[] myList = new double[3]; Enter 3 values:
Scanner input = new Scanner(System.in); 5
System.out.println("Enter " + myList.length + " values: "); 6
for (int i = 0; i < myList.length; i++) { 9
myList[i] = input.nextDouble(); mylist[0]=5.0
} mylist[1]=6.0
for (int i = 0; i < myList.length; i++) { mylist[2]=9.0
System.out.println("mylist["+i+"]="+myList[i]);
}
}
}

19
Initializing arrays with random values
public class Main {
public static void main(String[] args) {
mylist[0]=99
int[] myList = new int[3]; mylist[1]=71
for (int i = 0; i < myList.length; i++) { mylist[2]=71
myList[i] = (int)(Math.random() * 100);
}
for (int i = 0; i < myList.length; i++) {
System.out.println("mylist["+i+"]="+myList[i]);
}
}
}

20
Note : The random Method
• Generates a random double value greater than or equal to 0.0 and less than 1.0
• (0 <= Math.random() < 1.0).

Examples:

Returns a random integer


(int)(Math.random() * 10) between 0 and 9.

Returns a random integer


50 + (int)(Math.random() * 50)
between 50 and 99.

In general,

a + Math.random() * b Returns a random number between


a and a + b, excluding a + b.

21
Shifting Elements
public class Main {
public static void main(String[] args) {
int[] myList = new int[4];
for (int i = 0; i < myList.length; i++) { Before Shifting:
myList[i] = (int)(Math.random() * 100);
} mylist[0]=71
System.out.println("Before Shifting:"); mylist[1]=88
for (int i = 0; i < myList.length; i++) { mylist[2]=21
System.out.println("mylist["+i+"]="+myList[i]);
} mylist[3]=11
int temp=myList[0];
for (int i = 1; i < myList.length; i++) { After Shifting:
myList[i-1]=myList[i];
} mylist[0]=88
myList[myList.length-1]=temp; mylist[1]=21
System.out.println("After Shifting:"); mylist[2]=11
for (int i = 0; i < myList.length; i++) {
System.out.println("mylist["+i+"]="+myList[i]); mylist[3]=71
}
}
} 22
Enhanced for Loop (for-each
loop)
• JDK 1.5 introduced a new for loop that enables you to traverse the complete
array sequentially without using an index variable. For example, the following
code displays all elements in the array myList:

for (double value: myList)


System.out.println(value);
• In general, the syntax is

for (elementType value: arrayRefVar) {


// Process the value
}

• You still have to use an index variable if you wish to traverse the array in a
different order or change the elements in the array.
23
public class Main { Enhanced for
Loop (for-each
public static void main(String[] args) {
int[] marks = { 125, 132, 95, 116, 110 };
int highest_marks = maximum(marks);
System.out.println("The highest score is " + highest_marks); loop)
}
public static int maximum(int[] numbers)
{
int maxSoFar = numbers[0];
// for each loop The highest score is 132
for (int num : numbers)
{
if (num > maxSoFar)
{
maxSoFar = num;
}
}
return maxSoFar;
}}
Copying Arrays
• Often, in a program, you need to duplicate an array or a part of an
array. In such cases you could attempt to use the assignment
statement (=), as follows: list2 = list1;

25
Copying Arrays
• Using a loop:
int[] sourceArray = {2, 3, 1, 5, 10};
int[] targetArray = new int[sourceArray.length];

for (int i = 0; i < sourceArrays.length; i++)


targetArray[i] = sourceArray[i];

26
The arraycopy Utility
arraycopy(sourceArray, src_pos, targetArray,
tar_pos, length);

Example:
System.arraycopy(sourceArray, 0, targetArray, 0,
sourceArray.length);

27
public class Main {
public static void main(String[] args) {
int[] sourceArray = {2, 3, 1, 5, 10};
int[] targetArray = {8,9,11,13}; source array
int[] temparray=new int[sourceArray.length]; 8 9 11 13
sourceArray=targetArray; target array
System.out.println("source array"); 8 9 11 13
for (int i:sourceArray) { address sourceArray = [I@1d81eb93
System.out.print(i+" "); address targetArray = [I@1d81eb93
} address temparray = [I@7291c18f
System.arraycopy(sourceArray, 0, temparray, 0, sourceArray.length);
System.out.println();
System.out.println("target array");
for (int i:sourceArray) {
System.out.print(i+" ");
}
System.out.println();
System.out.println("address sourceArray = "+sourceArray);
System.out.println("address targetArray = "+targetArray);
System.out.println("address temparray = "+temparray);
}
}
Passing Arrays to Methods
public static void printArray(int[] array) {
for (int i = 0; i < array.length; i++) {
System.out.print(array[i] + " ");
}
}

Invoke the method

int[] list = {3, 1, 2, 6, 4, 2};


printArray(list);

Invoke the method


printArray(new int[]{3, 1, 2, 6, 4, 2});

Anonymous array

29
Anonymous Array
• The statement
printArray(new int[]{3, 1, 2, 6, 4, 2});
• creates an array using the following syntax:
new dataType[]{literal0, literal1, ..., literalk};
• There is no explicit reference variable for the array. Such
array is called an anonymous array.

30
Pass By Value
• Java uses pass by value to pass arguments to a method. There are
important differences between passing a value of variables of primitive
data types and passing arrays.
• For a parameter of a primitive type value, the actual value is passed.
Changing the value of the local parameter inside the method does not
affect the value of the variable outside the method.
• For a parameter of an array type, the value of the parameter contains a
reference to an array; this reference is passed to the method. Any changes
to the array that occur inside the method body will affect the original array
that was passed as the argument.

31
Simple Example
public class Main {
public static void main(String[] args) {

int x = 1; // x represents an int value


int[] y = new int[10]; // y represents an array of int values
y[0]=2222;
x is 1
m(x, y); // Invoke m with arguments x and y
y[0] is 5555
System.out.println("x is " + x);
System.out.println("y[0] is " + y[0]);
}
public static void m(int number, int[] numbers) {
number = 1001; // Assign a new value to number
numbers[0] = 5555; // Assign a new value to numbers[0]
}
}

32
Returning an Array from a Method
public static int[] reverse(int[] list) {
int[] result = new int[list.length];

for (int i = 0, j = result.length - 1;


i < list.length; i++, j--) {
result[j] = list[i];
}

return result;
}

int[] list1 = {1, 2, 3, 4, 5, 6};


int[] list2 = reverse(list1);

33
Variable-Length Arguments
You can pass a variable number of arguments of the same type to a
method.
public class Main {
public static void printMax(double... numbers) {
if (numbers.length == 0) {
System.out.println("No argument passed");
return; The max value is 56.5
} The max value is 3.0
double result = numbers[0];
for (int i = 1; i < numbers.length; i++)
if (numbers[i] > result)
result = numbers[i];
System.out.println("The max value is " + result);
}
public static void main(String[] args) {
printMax(34, 3, 3, 2, 56.5);
printMax(new double[]{1, 2, 3}); }
}
34
Linear Search
• The linear search approach compares the key element, key,
sequentially with each element in the array list.
• The method continues to do so until the key matches an element in
the list or the list is exhausted without a match being found.
• If a match is made, the linear search returns the index of the element
in the array that matches the key.
• If no match is found, the search returns -1.

35
Linear Search Implementation
public class Main {
public static int linearSearch(int[] list, int key) {
for (int i = 0; i < list.length; i++)
if (key == list[i])
return i;
return -1;
}
public static void main(String[] args) {
int[] list = {1, 4, 4, 2, 5, -3, 6, 2};
System.out.println(linearSearch(list, 4)); 1
System.out.println(linearSearch(list, -4)); -1
System.out.println(linearSearch(list, -3)); 5
}
}

36
The Arrays.sort Method

Since sorting is frequently used in programming, Java provides several overloaded sort
methods for sorting an array of int, double, char, short, long, and float in the java.util.Arrays
class. For example, the following code sorts an array of numbers and an array of characters.

double[] numbers = {6.0, 4.4, 1.9, 2.9, 3.4, 3.5};


java.util.Arrays.sort(numbers);

char[] chars = {'a', 'A', '4', 'F', 'D', 'P'};


java.util.Arrays.sort(chars);

37
Main Method Is Just a Regular Method

You can call a regular method by passing actual parameters. Can you
pass arguments to main? Of course, yes. For example, the main
method in class B is invoked by a method in A, as shown below:

public class A { class B {


public static void main(String[] args) { public static void main(String[] args) {
String[] strings = {"New York", for (int i = 0; i < args.length; i++)
"Boston", "Atlanta"}; System.out.println(args[i]);
B.main(strings); }
} }
}

38
class B {
public static void main(String[] args) {
for (int i = 0; i < args.length; i++)
System.out.println(args[i]);
}
} New York
Boston
public class Main { Atlanta
public static void main(String[] args) {
String[] strings = {"New York",
"Boston", "Atlanta"};
B.main(strings);
}
}
Two-dimensional Arrays
Declare/Create Two-dimensional Arrays
// Declare array ref var
dataType[][] refVar;

// Create array and assign its reference to variable


refVar = new dataType[10][10];

// Combine declaration and creation in one statement


dataType[][] refVar = new dataType[10][10];

// Alternative syntax
dataType refVar[][] = new dataType[10][10];
41
Declaring Variables of Two-
dimensional Arrays and Creating
Two-dimensional Arrays

• int[][] matrix = new int[10][10];


or
• int matrix[][] = new int[10][10];
• matrix[0][0] = 3;

42
Two-dimensional Array Illustration

matrix.length? 5 array.length? 4
matrix[0].length? 5 array[0].length? 3

43
Declaring, Creating, and Initializing Using
Shorthand Notations

You can also use an array initializer to declare, create and


initialize a two-dimensional array. For example,

int[][] array = {
int[][] array = new int[4][3];
{1, 2, 3}, array[0][0] = 1; array[0][1] = 2; array[0][2] = 3;
{4, 5, 6}, Same as array[1][0] = 4; array[1][1] = 5; array[1][2] = 6;
{7, 8, 9}, array[2][0] = 7; array[2][1] = 8; array[2][2] = 9;
{10, 11, 12} array[3][0] = 10; array[3][1] = 11; array[3][2] = 12;
};

44
Lengths of Two-dimensional Arrays

int[][] x = new int[3][4];

45
Lengths of Two-dimensional Arrays,
cont.

int[][] array = { array.length


{1, 2, 3}, array[0].length
{4, 5, 6}, array[1].length
{7, 8, 9}, array[2].length
{10, 11, 12} array[3].length
};

array[4].length ArrayIndexOutOfBoundsException

46
Ragged Arrays
Each row in a two-dimensional array is itself an array. So, the rows can
have different lengths. Such an array is known as a ragged array. For
example,
int[][] triangleArray = {
{1, 2, 3, 4, 5},
triangleArray.length is 5
{2, 3, 4, 5}, triangleArray[0].length is 5
{3, 4, 5}, triangleArray[1].length is 4
triangleArray[2].length is 3
{4, 5}, triangleArray[3].length is 2
{5} triangleArray[4].length is 1
};
47
Ragged Arrays, cont.

48
Printing arrays
public class Main {
public static void main(String[] args) {
int[][] triangleArray = {
{1, 2, 3, 4, 5}, 12345
2345
{2, 3, 4, 5},
345
{3, 4, 5}, 45
{4, 5}, 5
{5}
};
for (int row = 0; row < triangleArray.length; row++) {
for (int column = 0; column < triangleArray[row].length; column++) {
System.out.print(triangleArray[row][column] + " ");
}
System.out.println();
}
}
}
49
Summing all elements
public class Main {
public static void main(String[] args) {
int[][] triangleArray = {
{1, 2, 3, 4, 5},
{2, 3, 4, 5},
{3, 4, 5},
{4, 5}, total = 55
{5}
};
int total = 0;
for (int row = 0; row < triangleArray.length; row++) {
for (int column = 0; column < triangleArray[row].length; column++) {
total += triangleArray[row][column];
}
}
System.out.println("total = "+total);
}
} 50
Problem: Grading Multiple-Choice
Test
Students’ answer Objective: write a
program that grades
multiple-choice test.

51
public class Main {
public static void main(String[] args) {
// Students' answers to the questions
Problem: Grading Multiple-Choice
char[][] answers = {
{'A', 'B', 'A', 'C', 'C', 'D', 'E', 'E', 'A', 'D'},
Test
{'D', 'B', 'A', 'B', 'C', 'A', 'E', 'E', 'A', 'D'},
{'E', 'D', 'D', 'A', 'C', 'B', 'E', 'E', 'A', 'D'},
{'C', 'B', 'A', 'E', 'D', 'C', 'E', 'E', 'A', 'D'},
{'A', 'B', 'D', 'C', 'C', 'D', 'E', 'E', 'A', 'D'},
{'B', 'B', 'E', 'C', 'C', 'D', 'E', 'E', 'A', 'D'},
{'B', 'B', 'A', 'C', 'C', 'D', 'E', 'E', 'A', 'D'},
Student 0's correct count is 7
{'E', 'B', 'E', 'C', 'C', 'D', 'E', 'E', 'A', 'D'}};
Student 1's correct count is 6
// Key to the questions
Student 2's correct count is 5
char[] keys = {'D', 'B', 'D', 'C', 'C', 'D', 'A', 'E', 'A', 'D'};
Student 3's correct count is 4
// Grade all answers
Student 4's correct count is 8
for (int i = 0; i < answers.length; i++) {
Student 5's correct count is 7
// Grade one student
Student 6's correct count is 7
int correctCount = 0;
Student 7's correct count is 7
for (int j = 0; j < answers[i].length; j++) {
if (answers[i][j] == keys[j])
correctCount++;
}
System.out.println("Student " + i + "'s correct count is " +correctCount);
} }}
Problem: Finding Two Points
Nearest to Each Other

PassTwoDimensionalArray

PassTwoDimensionalArray
53
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.print("Enter the number of points: "); // Display result
int numberOfPoints = input.nextInt();
System.out.println("The closest two points are " +
// Create an array to store points
double[][] points = new double[numberOfPoints][2]; "(" + points[p1][0] + ", " + points[p1][1] + ") and (" +
System.out.print("Enter " + numberOfPoints + " points: "); points[p2][0] + ", " + points[p2][1] + ")");
for (int i = 0; i < points.length; i++) { }
points[i][0] = input.nextDouble();
points[i][1] = input.nextDouble(); public static double distance(
} double x1, double y1, double x2, double y2) {
// p1 and p2 are the indices in the points array return Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
int p1 = 0, p2 = 1; // Initial two points
}
double shortestDistance = distance(points[p1][0], points[p1][1],
points[p2][0], points[p2][1]); // Initialize shortestDistance }
// Compute distance for every two points Enter the number of points: 4
for (int i = 0; i < points.length; i++) { Enter 4 points:
for (int j = i + 1; j < points.length; j++) { 12
double distance = distance(points[i][0], points[i][1], 22
points[j][0], points[j][1]); // Find distance
35
if (shortestDistance > distance) {
p1 = i; // Update p1 21
p2 = j; // Update p2 The closest two points are (1.0, 2.0) and (2.0, 2.0)
shortestDistance = distance; // Update shortestDistance
} } }
Multidimensional Arrays
Multidimensional Arrays
• Occasionally, you will need to represent n-dimensional data
structures. In Java, you can create n-dimensional arrays for any
integer n.
• The way to declare two-dimensional array variables and create two-
dimensional arrays can be generalized to declare n-dimensional array
variables and create n-dimensional arrays for n >= 3.

56
Multidimensional Arrays
double[][][] scores = {
{{7.5, 20.5}, {9.0, 22.5}, {15, 33.5}, {13, 21.5}, {15, 2.5}},
{{4.5, 21.5}, {9.0, 22.5}, {15, 34.5}, {12, 20.5}, {14, 9.5}},
{{6.5, 30.5}, {9.4, 10.5}, {11, 33.5}, {11, 23.5}, {10, 2.5}},
{{6.5, 23.5}, {9.4, 32.5}, {13, 34.5}, {11, 20.5}, {16, 7.5}},
{{8.5, 26.5}, {9.4, 52.5}, {13, 36.5}, {13, 24.5}, {16, 2.5}},
{{9.5, 20.5}, {9.4, 42.5}, {13, 31.5}, {12, 20.5}, {16, 6.5}}
};

Which student Which exam Multiple-choice or essay

scores[ i ] [ j ] [ k ]
57
Problem: Calculating Total Scores
• Objective: write a program that calculates the total score for students in a class.
Suppose the scores are stored in a three-dimensional array named scores.
• The first index in scores refers to a student, the second refers to an exam, and
the third refers to the part of the exam.
• Suppose there are 7 students, 5 exams, and each exam has two parts--the
multiple-choice part and the programming part.
• So, scores[i][j][0] represents the score on the multiple-choice part for the i’s
student on the j’s exam.
• Your program displays the total score for each student.

58
public class Main {
public static void main(String[] args) {
double[][][] scores = {
{{7.5, 20.5}, {9.0, 22.5}, {15, 33.5}, {13, 21.5}, {15, 2.5}},
{{4.5, 21.5}, {9.0, 22.5}, {15, 34.5}, {12, 20.5}, {14, 9.5}},
{{6.5, 30.5}, {9.4, 10.5}, {11, 33.5}, {11, 23.5}, {10, 2.5}},
{{6.5, 23.5}, {9.4, 32.5}, {13, 34.5}, {11, 20.5}, {16, 7.5}},
{{8.5, 26.5}, {9.4, 52.5}, {13, 36.5}, {13, 24.5}, {16, 2.5}}, Student 0's score is 160.0
Student 1's score is 163.0
{{9.5, 20.5}, {9.4, 42.5}, {13, 31.5}, {12, 20.5}, {16, 6.5}},
Student 2's score is 148.4
{{1.5, 29.5}, {6.4, 22.5}, {14, 30.5}, {10, 30.5}, {16, 6.0}}}; Student 3's score is 174.4
// Calculate and display total score for each student Student 4's score is 202.4
for (int i = 0; i < scores.length; i++) { Student 5's score is 181.4
double totalScore = 0; Student 6's score is 166.9
for (int j = 0; j < scores[i].length; j++)
for (int k = 0; k < scores[i][j].length; k++)
totalScore += scores[i][j][k];

System.out.println("Student " + i + "'s score is " +


totalScore);
} }
}
Thanks
References
• Java: How To Program, Early Objects, 11th edition
• Cay S. Horstmann, Big Java: Late Objects

• Introduction to Java Programming and Data Structures, Comprehensive Version 12th


Edition, by Y. Liang (Author), Y. Daniel Liang
• Java documentation https://docs.oracle.com/javase
• https://www.youtube.com/watch?v=LTgClBqDank&feature=youtu.be
• Listing 7.3 Animation by Y. Daniel Liang (pearsoncmg.com)
• Linear Search Animation by Y. Daniel Liang (pearsoncmg.com)
• Introduction to Java Programming and Data Structures, 12E, Y. Daniel Liang - VarArgsDemo.java (pearsoncmg.com)
• Introduction to Java Programming and Data Structures, 12E, Y. Daniel Liang - CountLettersInArray.java (pearsoncmg.com)
References
• Introduction to Java Programming and Data Structures, 12E, Y. Daniel Liang - TestPassArray.java
(pearsoncmg.com)
• Introduction to Java Programming and Data Structures, 12E, Y. Daniel Liang - TestMax.java (pearsoncmg.com)
• Introduction to Java Programming and Data Structures, 12E, Y. Daniel Liang - Weather.java (pearsoncmg.com)
• Introduction to Java Programming and Data Structures, 12E, Y. Daniel Liang - TotalScore.java
(pearsoncmg.com)
• Introduction to Java Programming and Data Structures, 12E, Y. Daniel Liang - GradeExam.java
(pearsoncmg.com)
• Introduction to Java Programming and Data Structures, 12E, Y. Daniel Liang - CheckSudokuSolution.java
(pearsoncmg.com)
• Binary Search Animation by Y. Daniel Liang (pearsoncmg.com)
Advanced Programming Language
Dr. Ahmed Hesham Mostafa
Dr. Mohamed Atia
Lecture 3 – OOP Part 1
OO Programming Concepts
• Object-oriented programming (OOP) involves programming using
objects.
• An object represents an entity in the real world that can be uniquely
identified. For example, a student, a desk, a circle, a button, and even
a loan can all be viewed as objects.
• An object has a unique identity, state, and behavior.
• The state of an object consists of a set of data fields (also known as
properties) with their current values.
• The behavior of an object is defined by a set of methods.
Objects
• An object has both a state and behavior. The state defines the object,
and the behavior defines what the object does.
Class Name: Circle A class template

Data Fields:
radius is _______

Methods:
getArea

Circle Object 1 Circle Object 2 Circle Object 3 Three objects of


the Circle class
Data Fields: Data Fields: Data Fields:
radius is 10 radius is 25 radius is 125
Classes
• Classes are constructs that define objects of the same type.
• A Java class uses variables to define data fields and methods to
define behaviors.
• Additionally, a class provides a special type of method, known as
constructors, which are invoked to construct objects from the class.
Why classes not struct
• Struct data variables and methods are defined as public by default.
• Class data variables and method are defined as private by default (in C++).
• Classes can have relationship between each other.
• Classes can have concepts like overloading, inheritance, and polymorphism.
• Classes have a new access levels for its’ members called protected, default.
• Classes Provide public interface, while hiding the implementation details
(Encapsulation)
• Class: when implementation is hidden, any change do not affect
programmers that use the object.
Defining classes and constructing objects
• A class is a definition of a category of objects.
• A class defines:
• the items of data that make up the state of an object (reference variables), including their
type: for example, whether they are integers, strings, or types defined by other classes;
• the 'behavior' of objects of the class, by which we mean the methods that can be invoked on
objects of the class.
• Class members: The instance variables and methods of a class or object are
known collectively as its members.
• Classes are like templates or blueprints for objects. They do not make objects!
• There are usually three steps to using an object:
1. Define a class.
2. Construct an object.
3. Store an object reference.
Example
(1) Define a class
Class name starts
with capital letter

class header

state

constructors

methods
Example (cont.)
2.Construct an object
3.Store an object reference.

Store an object reference: storing a reference to a


User object. The general statement is:
ClassName objectName;
In the above example, the declaration creates a Construct an object. We call this
reference variable, “john” of the type “User” invoking a constructor

After execution →

The keyword null represents a reference that does not point at any object.
Reference variables and assignment
• If we write:

• If we make the userID variable


• in this object reference the string "Bridgend"
Reference variables and assignment (cont.)
• If we write:
Classes
class Circle {
/** The radius of this circle */
double radius = 1.0; Data field

/** Construct a circle object */


Circle() {
}
Constructors
/** Construct a circle object */
Circle(double newRadius) {
radius = newRadius;
}

/** Return the area of this circle */


double getArea() { Method
return radius * radius * 3.14159;
}
}
• Rempmber deaulat constructor
UML Class Diagram

UML Class Diagram Circle Class name

radius: double Data fields

Circle() Constructors and


Circle(newRadius: double) methods
getArea(): double
getPerimeter(): double
setRadius(newRadius:
double): void

circle2: Circle circle3: Circle UML notation


circle1: Circle
for objects
radius = 1.0 radius = 25 radius = 125
// Define the circle class with two constructors
class SimpleCircle {
double radius;
Example: Defining
/** Construct a circle with radius 1 */
SimpleCircle() {
Classes and Creating
}
radius = 1; Objects
/** Construct a circle with a specified radius */
SimpleCircle(double newRadius) {
radius = newRadius;
}
/** Return the area of this circle */
double getArea() {
return radius * radius * Math.PI;
}
/** Return the perimeter of this circle */
double getPerimeter() {
return 2 * radius * Math.PI;
}
/** Set a new radius for this circle */
void setRadius(double newRadius) {
radius = newRadius;
}
}
public class TestSimpleCircle {
/** Main method */ Example: Defining
public static void main(String[] args) {
// Create a circle with radius 1 Classes and Creating
SimpleCircle circle1 = new SimpleCircle();
System.out.println("The area of the circle of radius " Objects
+ circle1.radius + " is " + circle1.getArea());

// Create a circle with radius 25


SimpleCircle circle2 = new SimpleCircle(25);
System.out.println("The area of the circle of radius "
+ circle2.radius + " is " + circle2.getArea()); The area of the circle of radius 1.0 is 3.141592653589793
The area of the circle of radius 25.0 is 1963.4954084936207
// Create a circle with radius 125 The area of the circle of radius 125.0 is 49087.385212340516
SimpleCircle circle3 = new SimpleCircle(125); The area of the circle of radius 100.0 is 31415.926535897932
System.out.println("The area of the circle of radius "
+ circle3.radius + " is " + circle3.getArea());

// Modify circle radius


circle2.radius = 100; // or circle2.setRadius(100)
System.out.println("The area of the circle of radius "
+ circle2.radius + " is " + circle2.getArea());
}
}
Constructors
• Constructors are a special kind of methods that are invoked to
construct objects.

Circle() {
}

Circle(double newRadius) {
radius = newRadius;
}
Constructors, cont.
A constructor with no parameters is referred to as a no-arg constructor.
· Constructors must have the same name as the class itself.
· Constructors do not have a return type—not even void.
· Constructors are invoked using the new operator when an object is
created. Constructors play the role of initializing objects.
Constructors, cont.
• Remember that a constructor cannot be abstract, final, synchronized,
and static. We cannot override a constructor.
• There are two types of constructor in Java:
• Default Constructor (also known as a no-argument constructor)
• Parameterized Constructor
Creating Objects Using Constructors
new ClassName();

Example:
new Circle();

new Circle(5.0);
Default Constructor
• A class may be defined without constructors. In this case, a no-arg
constructor with an empty body is implicitly defined in the class. This
constructor, called a default constructor, is provided automatically
only if no constructors are explicitly defined in the class.

• If there is any constructor defined in the class and you attempt to


create object using User m=new User(); will rise an error
Declaring Object Reference Variables
To reference an object, assign the object to a reference variable.

To declare a reference variable, use the syntax:

ClassName objectRefVar;

Example:
Circle myCircle;
Declaring/Creating Objects
in a Single Step
ClassName objectRefVar = new ClassName();

Assign object reference Create an object


Example:
Circle myCircle = new Circle();
Accessing Object’s Members
❑Referencing the object’s data:
objectRefVar.data
e.g., myCircle.radius

❑Invoking the object’s method:


objectRefVar.methodName(arguments)
e.g., myCircle.getArea()
Trace Code
Circle myCircle = new Circle(5.0);
myCircle reference value
Circle yourCircle = new Circle();

yourCircle.radius = 100; : Circle

radius: 5.0

yourCircle reference value

: Circle
Change radius in radius: 100.0
yourCircle
Caution
• Recall that you use
Math.methodName(arguments) (e.g., Math.pow(3, 2.5))
• to invoke a method in the Math class. Can you invoke getArea() using
SimpleCircle.getArea()? The answer is no. All the methods used before this
chapter are static methods, which are defined using the static keyword.
• However, getArea() is non-static. It must be invoked from an object using
objectRefVar.methodName(arguments) (e.g., myCircle.getArea()).
• More explanations will be given in the section on “Static Variables, Constants, and
Methods.”
Reference Data Fields
• The data fields can be of reference types. For example, the following
Student class contains a data field name of the String type.
public class Student {
String name; // name has default value null
int age; // age has default value 0
boolean isScienceMajor; // isScienceMajor has default value false
char gender; // c has default value '\u0000'
}
Default Value for a Data Field
• If a data field of a reference type does not reference any object, the
data field holds a special literal value, null.
• The default value of a data field is null for a reference type
• 0 for a numeric type
• false for a boolean type
• '\u0000' for a char type.
• However, Java assigns no default value to a local variable inside a
method.
Default Value for a Data Field
public class Test {
public static void main(String[] args) {
Student student = new Student();
System.out.println("name? " + student.name);
System.out.println("age? " + student.age);
System.out.println("isScienceMajor? " +
student.isScienceMajor);
System.out.println("gender? " + student.gender);
}
} name? null
age? 0
isScienceMajor? false
gender?
Default Value for a Data Field
• Java assigns no default value to a local variable inside a method.
public class Test {
public static void main(String[] args) {
int x; // x has no default value
String y; // y has no default value
System.out.println("x is " + x);
System.out.println("y is " + y);
}
}
Compile error: variable not initialized
Differences between Variables of
Primitive Data Types and Object Types

Created using new Circle()


Primitive type int i = 1 i 1

Object type Circle c c reference c: Circle

radius = 1
Copying Variables of Primitive Data Types and
Object Types
Object type assignment c1 = c2

Primitive type assignment i = j Before: After:

c1 c1
Before: After:

i 1 i 2 c2 c2

j 2 j 2 c1: Circle c2: Circle c1: Circle c2: Circle


radius = 5 radius = 9 radius = 5 radius = 9
Garbage Collection
• As shown in the previous figure, after the assignment statement c1 =
c2, c1 points to the same object referenced by c2. The object
previously referenced by c1 is no longer referenced. This object is
known as garbage. Garbage is automatically collected by JVM.
Static Variables, Constants, and Methods
Static variables are shared by all the instances of the class.
Static methods are not tied to a specific object. Static constants are
final variables shared by all the instances of the class.
• To declare static variables, constants, and methods, use the static
modifier.
Example of Using Instance and Class Variables
and Method
• Objective: Demonstrate the roles of instance and class variables and
their uses.
• This example adds a class variable numberOfObjects to track the
number of Circle objects created.
public class CircleWithStaticMembers {
double radius;
Example of Using
static int numberOfObjects = 0; Instance and Class
CircleWithStaticMembers() {
radius = 1.0;
Variables and Method
numberOfObjects++;
} Objective: Demonstrate the roles
CircleWithStaticMembers(double newRadius) { of instance and class variables and
radius = newRadius; their uses.
numberOfObjects++;
This example adds a class variable
}
static int getNumberOfObjects() { numberOfObjects to track the
return numberOfObjects; number of Circle objects created.
}
double getArea() {
return radius * radius * Math.PI;
}
}
public class Main { Example of Using Instance
public static void main(String[] args) { and Class Variables and
System.out.println("Before creating objects"); Method
System.out.println("The number of Circle objects is " + CircleWithStaticMembers.numberOfObjects);
CircleWithStaticMembers c1 = new CircleWithStaticMembers();
System.out.println("\nAfter creating c1");
System.out.println("c1: radius (" + c1.radius +") and number of Circle objects (" + c1.numberOfObjects + ")");
CircleWithStaticMembers c2 = new CircleWithStaticMembers(5);
c1.radius = 9;
System.out.println("\nAfter creating c2 and modifying c1");
System.out.println("c1: radius (" + c1.radius +") and number of Circle objects (" +c1.numberOfObjects + ")");
System.out.println("c2: radius (" + c2.radius +") and number of Circle objects (" + c2.numberOfObjects + ")");
}
} Before creating objects
The number of Circle objects is 0
After creating c1
c1: radius (1.0) and number of Circle objects (1)
After creating c2 and modifying c1
c1: radius (9.0) and number of Circle objects (2)
c2: radius (5.0) and number of Circle objects (2)
Visibility Modifiers and
Accessor/Mutator Methods
• By default, the class, variable, or method can be accessed by any class
in the same package.
❑ public
The class, data, or method is visible to any class in any package.

❑ private
The data or methods can be accessed only by the declaring class.
The get and set methods are used to read and modify private
properties.
Visibility Modifiers and
Accessor/Mutator Methods
• The private modifier restricts access to within a class, the default
modifier restricts access to within a package, and the public modifier
enables unrestricted access.
Visibility Modifiers and
Accessor/Mutator Methods
• The default modifier on a class restricts access to within a package,
and the public modifier enables unrestricted access.
NOTE
• An object cannot access its private members, as shown in (b). It is OK,
however, if the object is declared in its own class, as shown in (a).
Why Data Fields Should Be private?
• To protect data.
• Data Encapsulation
Example of
Data Field Encapsulation

Circle
The - sign indicates
private modifier -radius: double The radius of this circle (default: 1.0).
-numberOfObjects: int The number of circle objects created.

+Circle() Constructs a default circle object.


+Circle(radius: double) Constructs a circle object with the specified radius.
+getRadius(): double Returns the radius of this circle.
+setRadius(radius: double): void Sets a new radius for this circle.
+getNumberOfObjects(): int Returns the number of circle objects created.
+getArea(): double Returns the area of this circle.
public class CircleWithPrivateDataFields {
private double radius = 1; Example of
private static int numberOfObjects = 0;
public CircleWithPrivateDataFields() {
numberOfObjects++;
Data Field Encapsulation
}
public CircleWithPrivateDataFields(double newRadius) { public class Main {
radius = newRadius; public static void main(String[] args) {
numberOfObjects++; CircleWithPrivateDataFields myCircle =
} new CircleWithPrivateDataFields(5.0);
public double getRadius() { System.out.println("The area of the circle of radius "
return radius; + myCircle.getRadius() + " is " + myCircle.getArea());
} myCircle.setRadius(myCircle.getRadius() * 1.1);
public void setRadius(double newRadius) { System.out.println("The area of the circle of radius "
radius = (newRadius >= 0) ? newRadius : 0; + myCircle.getRadius() + " is " + myCircle.getArea());
} System.out.println("The number of objects created is "
public static int getNumberOfObjects() { + CircleWithPrivateDataFields.getNumberOfObjects());
return numberOfObjects; } }
}
public double getArea() { The area of the circle of radius 5.0 is 78.53981633974483
return radius * radius * Math.PI;
The area of the circle of radius 5.5 is 95.03317777109125
}
} The number of objects created is 1
Passing Objects to Methods
❑Passing by value for primitive type value (the value is passed to the
parameter)
❑Passing by value for reference type value (the value is the reference
to the object)
public class Main { Passing
public static void main(String[] args) {
CircleWithPrivateDataFields myCircle = new CircleWithPrivateDataFields(1); Objects to
int n = 5;
printAreas(myCircle, n); Methods
System.out.println("\n" + "Radius is " + myCircle.getRadius());
System.out.println("n is " + n);
Example
}
public static void printAreas(CircleWithPrivateDataFields c, int times) {
System.out.println("Radius \t\tArea");
while (times >= 1) {
System.out.println(c.getRadius() + "\t\t" + c.getArea());
c.setRadius(c.getRadius() + 1);
Radius Area
times--;
1.0 3.141592653589793
} 2.0 12.566370614359172
} } 3.0 28.274333882308138
4.0 50.26548245743669
5.0 78.53981633974483

Radius is 6.0
n is 5
Passing Objects to Methods, cont.
Array of Objects
• Circle[] circleArray = new Circle[10];

• An array of objects is actually an array of reference variables.


• So invoking circleArray[1].getArea() involves two levels of referencing
as shown in the figure. circleArray references to the entire array.
circleArray[1] references to a Circle object.
public class Main {
public static void main(String[] args) {
CircleWithPrivateDataFields[] circleArray;
circleArray = createCircleArray(); public static double sum(
printCircleArray(circleArray); CircleWithPrivateDataFields[] circleArray) {
} double sum = 0;
public static CircleWithPrivateDataFields[] createCircleArray() {
for (int i = 0; i < circleArray.length; i++)
CircleWithPrivateDataFields[] circleArray =
new CircleWithPrivateDataFields[5]; sum += circleArray[i].getArea();
for (int i = 0; i < circleArray.length; i++) { return sum;
circleArray[i] = }
new CircleWithPrivateDataFields(Math.random() * 100);
}
}
return circleArray; Radius Area
} 70.799357 15747.387180
public static void printCircleArray(
20.283846 1292.559252
CircleWithPrivateDataFields[] circleArray) {
System.out.printf("%-30s%-15s\n", "Radius", "Area"); 79.881382 20046.613256
for (int i = 0; i < circleArray.length; i++) { 32.226883 3262.770072
System.out.printf("%-30f%-15f\n", circleArray[i].getRadius(), 16.435723 848.647837
circleArray[i].getArea()); -----------------------------------------
} The total areas of circles is 41197.977597
System.out.println("-----------------------------------------");
System.out.printf("%-30s%-15f\n", "The total areas of circles is",
sum(circleArray));
}
Information hiding: Getter and setter methods
• A getter method (also called an 'accessor' method):
• It is one that accesses some attribute of an object.
• A getter method should not change the state of the object.

• A setter method (also called a 'mutator' method)


• It is one that changes the state of an object by setting the value of an
instance variable.
• Setter methods do not normally return a value.
Information hiding: getter and setter methods
• Example: Getter and setter methods for the User class
Information hiding: Member access by dot
notation (.)
• The keyword public in front of a member in the class User indicates
that it may be accessed using dot notation with a User reference
variable.
• In contrast, because we have used the keyword private in front of
the User instance variables, there is no access outside the class itself
to these variables.
• This is NOT allowed →

• This is allowed →
public class three {
private int a,b,c;
The this Keyword public three(int a,int b,int c){
this.a=a;
this.b=b;
❑The this keyword is the name of a reference this.c=c;
that refers to an object itself. One common }
public three(){
use of the this keyword is reference a class’s
this(0,0,0);
hidden data fields. }
public three(int a){
❑Another common use of the this keyword to this(a,0,0);
enable a constructor to invoke another }
public three(int a,int b){
constructor of the same class. (Calling
this(a,b,0);
Overloaded Constructor) }
}
Class Abstraction and Encapsulation
Class abstraction means to separate class implementation
from the use of the class. The creator of the class
provides a description of the class and let the user know
how the class can be used. The user of the class does not
need to know how the class is implemented. The detail of
implementation is encapsulated and hidden from the
user.

Class implementation Class Contract


is like a black box (Signatures of Clients use the
hidden from the clients
Class public methods and class through the
public constants) contract of the class

53
Designing the Loan Class
Loan
-annualInterestRate: double The annual interest rate of the loan (default: 2.5).
-numberOfYears: int The number of years for the loan (default: 1)
-loanAmount: double The loan amount (default: 1000).
-loanDate: Date The date this loan was created.

+Loan() Constructs a default Loan object.


+Loan(annualInterestRate: double, Constructs a loan with specified interest rate, years, and
numberOfYears: int, loan amount.
loanAmount: double)
+getAnnualInterestRate(): double Returns the annual interest rate of this loan.
+getNumberOfYears(): int Returns the number of the years of this loan.
+getLoanAmount(): double Returns the amount of this loan.
+getLoanDate(): Date Returns the date of the creation of this loan.
+setAnnualInterestRate( Sets a new annual interest rate to this loan.
annualInterestRate: double): void
+setNumberOfYears( Sets a new number of years to this loan.
numberOfYears: int): void
+setLoanAmount( Sets a new amount to this loan.
loanAmount: double): void
+getMonthlyPayment(): double Returns the monthly payment of this loan.
+getTotalPayment(): double Returns the total payment of this loan.

Loan TestLoanClass

Loan TestLoanClass
54
public class Loan {
private double annualInterestRate;
private int numberOfYears; public double getLoanAmount() {
private double loanAmount; return loanAmount;
private java.util.Date loanDate;
}
/** No-arg constructor */ public void setLoanAmount(double loanAmount) {
public Loan() { this.loanAmount = loanAmount;
this(2.5, 1, 1000); }
} public double getMonthlyPayment() {
public Loan(double annualInterestRate, int numberOfYears, double monthlyInterestRate = annualInterestRate / 1200;
double loanAmount) { double monthlyPayment = loanAmount * monthlyInterestRate / (1 -
this.annualInterestRate = annualInterestRate;
(1 / Math.pow(1 + monthlyInterestRate, numberOfYears * 12)));
this.numberOfYears = numberOfYears;
this.loanAmount = loanAmount; return monthlyPayment;
loanDate = new java.util.Date(); }
} public double getTotalPayment() {
public double getAnnualInterestRate() { double totalPayment = getMonthlyPayment() * numberOfYears * 12;
return annualInterestRate; return totalPayment;
} }
public void setAnnualInterestRate(double annualInterestRate) {
public java.util.Date getLoanDate() {
this.annualInterestRate = annualInterestRate;
} return loanDate;
}
public int getNumberOfYears() { }
return numberOfYears;
}
public void setNumberOfYears(int numberOfYears) {
this.numberOfYears = numberOfYears;
}
Enter annual interest rate, for example, 8.25: 22
import java.util.Scanner; Enter number of years as an integer: 5
Enter loan amount, for example, 120000.95: 120000
public class Main { The loan was created on Tue Nov 08 19:00:49 EET 2022
public static void main(String[] args) { The monthly payment is 3314.27
Scanner input = new Scanner(System.in); The total payment is 198856.17
System.out.print(
"Enter annual interest rate, for example, 8.25: ");
double annualInterestRate = input.nextDouble();
System.out.print("Enter number of years as an integer: ");
int numberOfYears = input.nextInt();
System.out.print("Enter loan amount, for example, 120000.95: ");
double loanAmount = input.nextDouble();
Loan loan =
new Loan(annualInterestRate, numberOfYears, loanAmount);
System.out.printf("The loan was created on %s\n" +
"The monthly payment is %.2f\nThe total payment is %.2f\n",
loan.getLoanDate().toString(), loan.getMonthlyPayment(),
loan.getTotalPayment());
}
}
Example: The Course Class
Course
-courseName: String The name of the course.
-students: String[] An array to store the students for the course.
-numberOfStudents: int The number of students (default: 0).
+Course(courseName: String) Creates a course with the specified name.
+getCourseName(): String Returns the course name.
+addStudent(student: String): void Adds a new student to the course.
+dropStudent(student: String): void Drops a student from the course.
+getStudents(): String[] Returns the students in the course.
+getNumberOfStudents(): int Returns the number of students in the course.

Course TestCourse

Course TestCourse

57
public class Course {
private String courseName;
private String[] students = new String[100];
private int numberOfStudents; public void dropStudent(String student) {

public Course(String courseName) { if (students.length <= 0) {


this.courseName = courseName; System.out.println("No student registered for this course");
} else {
}
String[] output = new String[students.length - 1];
public void addStudent(String student) { int count = 0;
students[numberOfStudents] = student; for (int i=0;count<numberOfStudents;i++) {
numberOfStudents++; if (!students[i].equals(student)) {
} output[count++] =students[i] ;
public String[] getStudents() { }
return students; else{
} numberOfStudents--;
public int getNumberOfStudents() { }
}
return numberOfStudents;
students=output;
} }
public String getCourseName() { }
return courseName; }
}
public class Main {
public static void main(String[] args) {
Course course1 = new Course("Data Structures");
Course course2 = new Course("Database Systems");
course1.addStudent("Jones");
course1.addStudent("Smith");
course1.addStudent("Kennedy"); Number of students in course1: 3
course2.addStudent("Jones"); Jones, Smith, Kennedy,
course2.addStudent("Smith");
System.out.println("Number of students in course1: " Course1 after Removeing a student
+ course1.getNumberOfStudents()); Number of students in course1: 2
String[] students = course1.getStudents();
for (int i = 0; i < course1.getNumberOfStudents(); i++) Jones, Smith,
System.out.print(students[i] + ", "); Number of students in course2: 2
course1.dropStudent("Kennedy");
System.out.println();
System.out.println("Course1 after Removeing a student");
System.out.println("Number of students in course1: "
+ course1.getNumberOfStudents());
students = course1.getStudents();
for (int i = 0; i < course1.getNumberOfStudents(); i++)
System.out.print(students[i] + ", ");

System.out.println();
System.out.print("Number of students in course2: "
+ course2.getNumberOfStudents());
}
}
Example: The StackOfIntegers
Class
StackOfIntegers
-elements: int[] An array to store integers in the stack.
-size: int The number of integers in the stack.
+StackOfIntegers() Constructs an empty stack with a default capacity of 16.
+StackOfIntegers(capacity: int) Constructs an empty stack with a specified capacity.
+empty(): boolean Returns true if the stack is empty.
+peek(): int Returns the integer at the top of the stack without
removing it from the stack.
+push(value: int): int Stores an integer into the top of the stack.
+pop(): int Removes the integer at the top of the stack and returns it.
+getSize(): int Returns the number of elements in the stack.
TestStackOfIntegers

TestStackOfIntegers
60
public class StackOfIntegers {
private int[] elements; public int pop() {
private int size; return elements[--size];
private int DEFAULT_CAPACITY = 16; }
public StackOfIntegers(int capacity) { public int peek() {
elements = new int[capacity];
return elements[size - 1];
}
public StackOfIntegers() { }
elements = new int[DEFAULT_CAPACITY]; public boolean empty() {
} return size == 0;
public void push(int value) { }
if (size >= elements.length) { public int getSize() {
int[] temp = new int[elements.length * 2]; return size;
System.arraycopy(elements, 0, temp, 0, elements.length); }
elements = temp; }
}
elements[size++] = value;
}
public class Main {
public static void main(String[] args) {
StackOfIntegers stack = new StackOfIntegers();
for (int i = 0; i < 10; i++)
stack.push(i); // Push i to the stack
while (!stack.empty()) // Test if stack is empty
System.out.print(stack.pop() + " "); // Remove and return from stack
}
}

9876543210
Designing the StackOfIntegers Class

63
Implementing StackOfIntegers
Class

StackOfIntegers

StackOfIntegers
64
Thanks
References
• Java: How To Program, Early Objects, 11th edition
• Cay S. Horstmann, Big Java: Late Objects

• Introduction to Java Programming and Data Structures, Comprehensive Version 12th


Edition, by Y. Liang (Author), Y. Daniel Liang
• Java documentation https://docs.oracle.com/javase
• Introduction to Java Programming and Data Structures, 12E, Y. Daniel Liang - TestSimpleCircle.java (pearsoncmg.com)
• Introduction to Java Programming and Data Structures, 12E, Y. Daniel Liang - CircleWithStaticMembers.java (pearsoncmg.com)
• Introduction to Java Programming and Data Structures, 12E, Y. Daniel Liang - TestCircleWithStaticMembers.java (pearsoncmg.com)
• Introduction to Java Programming and Data Structures, 12E, Y. Daniel Liang - CircleWithPrivateDataFields.java (pearsoncmg.com)
• Introduction to Java Programming and Data Structures, 12E, Y. Daniel Liang - TestCircleWithPrivateDataFields.java (pearsoncmg.com)
• Introduction to Java Programming and Data Structures, 12E, Y. Daniel Liang - TestPassObject.java (pearsoncmg.com)
References
• Introduction to Java Programming and Data Structures, 12E, Y. Daniel Liang - TestPassArray.java
(pearsoncmg.com)
• Introduction to Java Programming and Data Structures, 12E, Y. Daniel Liang - TestMax.java (pearsoncmg.com)
• Introduction to Java Programming and Data Structures, 12E, Y. Daniel Liang - Weather.java (pearsoncmg.com)
• Introduction to Java Programming and Data Structures, 12E, Y. Daniel Liang - TotalScore.java
(pearsoncmg.com)
• Introduction to Java Programming and Data Structures, 12E, Y. Daniel Liang - GradeExam.java
(pearsoncmg.com)
• Introduction to Java Programming and Data Structures, 12E, Y. Daniel Liang - CheckSudokuSolution.java
(pearsoncmg.com)
• Binary Search Animation by Y. Daniel Liang (pearsoncmg.com)
Advanced Programming Language
Dr. Ahmed Hesham Mostafa
Dr. Mohamed Atia
Lecture 4 – OOP Part 2
Class Relationships

Association
Aggregation
Composition
Inheritance (Chapter 13)

2
Association
• Association: is a general binary relationship that describes an activity between
two classes.
• Association in Java is a connection or relation between two
separate classes that are set up through their objects.
• Association relationship indicates how objects know each other and
how they are using each other’s functionality.
• It can be one-to-one, one-to-many, many-to-one and many-to-many.
• This UML diagram shows that a student may take any number of courses, a
faculty member may teach at most three courses, a course may have from 5 to
60 students, and a course is taught by only one faculty member.
Association
• Each class involved in an association may specify a multiplicity, which is
placed at the side of the class to specify how many of the class’s objects are
involved in the relationship in UML.
• A multiplicity could be a number or an interval that specifies how many of
the class’s objects are involved in the relationship.
• The character * means an unlimited number of objects, and the interval
m..n indicates that the number of objects is between m and n
• For example : each student may take any number of courses, and each
course must have at least 5 and at most 60 students. Each course is taught
by only one faculty member, and a faculty member may teach from 0 to 3
courses per semester.
Association
• In Java code, you can implement associations by using data fields and
methods.
• The relation “a student takes a course” is implemented using the
addCourse method in the Student class and the addStudent method in the
Course class.
• The relation “a faculty teaches a course” is implemented using the
addCourse method in the Faculty class and the setFaculty method in the
Course class.
• The Student class may use a list to store the courses that the student is
taking, the Faculty class may use a list to store the courses that the faculty
is teaching
• Course class may use a list to store students enrolled in the course and a
data field to store the instructor who teaches the course.
Association
Object Composition
• Composition is actually a special case of the aggregation relationship.
Aggregation models has-a relationships and represents an ownership
relationship between two objects.
• The owner object is called an aggregating object and its class an
aggregating class.
• The subject object is called an aggregated object and its class an
aggregated class.

Composition Aggregation

1 1 1..3 1
Name Student Address

7
Aggregation or Composition
• We refer aggregation between two objects as composition if the existence
of the aggregated object is dependent on the aggregating object.
• In other words, if a relationship is composition, the aggregated object
cannot exist on its own
• For example, “a student has a name” is a composition relationship
between the Student class and the Name class because Name is dependent
on Student,
• “a student has an address” is an aggregation relationship between the
Student class and the Address class because an address can exist by itself.
Composition implies exclusive ownership.
• One object owns another object. When the owner object is destroyed, the
dependent object is destroyed as well. (The class (owner) who create
(construct) the object )
Class Representation
An aggregation relationship is usually represented as a
data field in the aggregating class. For example, the
relationship in Figure 10.6 can be represented as follows:

public class Name { public class Student { public class Address {


... private Name name; ...
} private Address address; }

...
}

Aggregated class Aggregating class Aggregated class

9
public class Job {
private String role;
Composition in Java
public class Person {
private long salary; Example
private int id; //composition has-a relationship
private Job job;
public String getRole() {
return role; public Person(){
} this.job=new Job();
public void setRole(String role) { job.setSalary(1000L);
this.role = role; }
} public long getSalary() {
public long getSalary() { return job.getSalary();
return salary; }
}
public void setSalary(long salary) { }
this.salary = salary;
}
public int getId() { public class TestPerson {
return id;
} public static void main(String[] args) {
public void setId(int id) { Person person = new Person();
this.id = id; long salary = person.getSalary();
} }
} }
Aggregation or Composition
Since aggregation and composition relationships are represented using
classes in similar ways, many texts don’t differentiate them and call
both compositions.

11
Aggregation Between Same Class
Aggregation may exist between objects of the same class. For example,
a person may have a supervisor.
1
Person
Supervisor
1

public class Person {


// The type for the data is the class itself
private Person supervisor;
...
}
12
Aggregation Between Same Class
What happens if a person has several supervisors?

1
Person
Supervisor
m

public class Person {


...
private Person[] supervisors;
}

13
Inheritance and Polymorphism
• Suppose you will define classes to model circles, rectangles, and
triangles.
• These classes have many common features.
• What is the best way to design these classes so to avoid redundancy?
The answer is to use inheritance.
Superclasses and Subclasses
GeometricObject
-color: String The color of the object (default: white).
-filled: boolean Indicates whether the object is filled with a color (default: false).
-dateCreated: java.util.Date The date when the object was created.
+GeometricObject() Creates a GeometricObject.
+GeometricObject(color: String, Creates a GeometricObject with the specified color and filled
filled: boolean) values.
+getColor(): String Returns the color.
+setColor(color: String): void Sets a new color.
+isFilled(): boolean Returns the filled property.
+setFilled(filled: boolean): void Sets a new filled property.
+getDateCreated(): java.util.Date Returns the dateCreated.
+toString(): String Returns a string representation of this object.

Circle Rectangle
-radius: double -width: double
+Circle() -height: double
+Circle(radius: double) +Rectangle() GeometricObject

+Circle(radius: double, color: String,


filled: boolean)
+Rectangle(width: double, height: double)
+Rectangle(width: double, height: double
GeometricObject
color: String, filled: boolean)
Circle

+getRadius(): double
+setRadius(radius: double): void +getWidth(): double Circle
+getArea(): double +setWidth(width: double): void Rectangle

+getPerimeter(): double +getHeight(): double


+setHeight(height: double): void
Rectangle
+getDiameter(): double TestCircleRectangle

+printCircle(): void +getArea(): double


+getPerimeter(): double TestCircleRectangle
15
public class SimpleGeometricObject {
private String color = "white";
private boolean filled;
private java.util.Date dateCreated;
public void setColor(String color) {
/** Construct a default geometric object */ this.color = color;
public SimpleGeometricObject() { }
dateCreated = new java.util.Date(); public boolean isFilled() {
} return filled;
}
/** Construct a geometric object with the specified color public void setFilled(boolean filled) {
* and filled value */ this.filled = filled;
public SimpleGeometricObject(String color, boolean filled) { }
dateCreated = new java.util.Date(); public java.util.Date getDateCreated() {
this.color = color; return dateCreated;
this.filled = filled; }
} public String toString() {
return "created on " + dateCreated + "\ncolor: " +
/** Return color */ color + " and filled: " + filled;
public String getColor() { }
return color; }
}
public class Circle extends SimpleGeometricObject {
private double radius; public double getArea() {
public Circle() { return radius * radius * Math.PI;
} }
public Circle(double radius) {
this.radius = radius; /** Return diameter */
} public double getDiameter() {
public Circle(double radius,String color, boolean filled) { return 2 * radius;
this.radius = radius; }
setColor(color);
/** Return perimeter */
setFilled(filled); public double getPerimeter() {
} return 2 * radius * Math.PI;
public double getRadius() { }
return radius;
} /* Print the circle info */
public void setRadius(double radius) { public void printCircle() {
this.radius = radius; System.out.println("The circle is created " +
} getDateCreated() +
" and the radius is " + radius);
}
}
public class Rectangle extends SimpleGeometricObject {
private double width;
private double height;
public void setWidth(double width) {
public Rectangle() { this.width = width;
} }
public Rectangle( /** Return height */
double width, double height) { public double getHeight() {
this.width = width; return height;
this.height = height; }
} /** Set a new height */
public Rectangle( public void setHeight(double height) {
double width, double height, String color, boolean filled) { this.height = height;
this.width = width; }
this.height = height; /** Return area */
setColor(color); public double getArea() {
setFilled(filled); return width * height;
} }
public double getWidth() { /** Return perimeter */
return width; public double getPerimeter() {
} return 2 * (width + height);
}
}
public class Main {
public static void main(String[] args) { A circle created on Sat Nov 19 20:31:22 EET 2022
Circle circle = new Circle(1);
color: white and filled: false
System.out.println("A circle " + circle.toString());
System.out.println("The color is " + circle.getColor()); The color is white
System.out.println("The radius is " + circle.getRadius()); The radius is 1.0
System.out.println("The area is " + circle.getArea()); The area is 3.141592653589793
System.out.println("The diameter is " + circle.getDiameter()); The diameter is 2.0

Rectangle rectangle = new Rectangle(2, 4); A rectangle created on Sat Nov 19 20:31:22 EET 2022
System.out.println("\nA rectangle " + rectangle.toString()); color: white and filled: false
System.out.println("The area is " + rectangle.getArea());
The area is 8.0
System.out.println("The perimeter is " +rectangle.getPerimeter());
} The perimeter is 12.0
}
Super Keyword in Java
• The super keyword in Java is a reference variable used to refer
to the immediate parent class object. It plays a crucial role in
inheritance and polymorphism, allowing subclasses to access
and utilize the properties and methods of their parent classes.
• Characteristics and Usage
• Accessing Parent Class Variables
• When a subclass and its parent class have the same variable
names, the super keyword can be used to differentiate and
access the parent class's variable. For example:
class Vehicle {
int maxSpeed = 120;
}

class Car extends Vehicle {


int maxSpeed = 180;
Output:
void display() { Maximum Speed: 120
System.out.println("Maximum Speed: " + super.maxSpeed);
}
}

public class Test {


public static void main(String[] args) {
Car small = new Car();
small.display();
}
}
• Invoking Parent Class class Person {
void message() {
Methods System.out.println("This is person class");
• The super keyword can }
}
also be used to call
methods from the class Student extends Person {
void message() {
parent class, especially System.out.println("This is student class");
when the subclass has }
overridden those void display() {
methods. For instance: message();
super.message();
Output: }
This is student class }
This is person class
public class Test {
public static void main(String args[]) {
Here, super.message() calls the message() method Student s = new Student();
from the Person class s.display();
}
}
• Calling Parent Class class Person {
Person() {
Constructors System.out.println("Person class Constructor");
• The super keyword can }
}
be used to invoke the
parent class's class Student extends Person {
Student() {
constructor. This is super();
particularly useful for System.out.println("Student class Constructor");
initializing inherited }
}
properties. For example:
public class Test {
public static void main(String[] args) {
Student s = new Student();
Output: }
Person class Constructor }
Student class Constructor
Are superclass’s Constructor Inherited?

No. They are not inherited.


They are invoked explicitly or implicitly.
Explicitly using the super keyword.
A constructor is used to construct an instance of a class. Unlike
properties and methods, a superclass's constructors are not inherited in
the subclass.
They can only be invoked from the subclasses' constructors, using the
keyword super. If the keyword super is not explicitly used, the
superclass's no-arg constructor is automatically invoked.
24
Superclass’s Constructor Is Always Invoked
A constructor may invoke an overloaded constructor or its
superclass’s constructor. If none of them is invoked
explicitly, the compiler puts super() as the first statement
in the constructor. For example,

public A() { public A() {


is equivalent to
} super();
}

public A(double d) { public A(double d) {


// some statements is equivalent to
super();
} // some statements
}

25
Using the Keyword super
The keyword super refers to the superclass
of the class in which super appears. This
keyword can be used in two ways:
❑To call a superclass constructor
❑To call a superclass method

26
Important Points to Remember While
Using “Java Super Keyword”
• Call to super() must be the first statement in the
Derived(Student) Class constructor because if you think about it, it
makes sense that the superclass has no knowledge of any subclass,
so any initialization it needs to perform is separate from and
possibly prerequisite to any initialization performed by the subclass.
Therefore, it needs to complete its execution first.
• If a constructor does not explicitly invoke a superclass constructor,
the Java compiler automatically inserts a call to the no-argument
constructor of the superclass. If the superclass does not have a no-
argument constructor, you will get a compile-time error. The
object does have such a constructor, so if the Object is the only
superclass, there is no problem.
class HelloWorld {
public static void main(String[] args) {
Child c=new Child();
ERROR!/tmp/aXeRULLvU9/Hello }
World.java:19: error: call to super }
must be first statement in
class Parent {
constructor super(); Parent() {
System.out.println("Parent constructor");
}
}

class Child extends Parent {


Child() {
System.out.println("Child constructor");
super();
}
}
Constructor Chaining
• In constructor chain, a constructor is called from another constructor in the
same class this process is known as constructor chaining. It occurs through
inheritance. When we create an instance of a derived class, all the
constructors of the inherited class (base class) are first invoked, after that
the constructor of the calling class (derived class) is invoked.
• We can achieve constructor chaining in two ways:
• Within the same class: If the constructors belong to the same class, we
use this
• From the base class: If the constructor belongs to different classes (parent
and child classes), we use the super keyword to call the constructor from
the base class.
• Remember that changing the order of the constructor does not affect the
output.
Constructor Chaining
Constructing an instance of a class invokes all the superclasses’ constructors
along the inheritance chain. This is known as constructor chaining.
public class Faculty extends Employee {
public static void main(String[] args) {
new Faculty();
}

public Faculty() {
System.out.println("(4) Faculty's no-arg constructor is invoked");
}
}

class Employee extends Person {


public Employee() {
this("(2) Invoke Employee’s overloaded constructor");
System.out.println("(3) Employee's no-arg constructor is invoked");
}

public Employee(String s) {
System.out.println(s);
}
}

class Person {
public Person() {
System.out.println("(1) Person's no-arg constructor is invoked");
}
} 31
animation
Trace Execution
public class Faculty extends Employee {
public static void main(String[] args) {
new Faculty(); 1. Start from the
} main method
public Faculty() {
System.out.println("(4) Faculty's no-arg constructor is invoked");
}
}

class Employee extends Person {


public Employee() {
this("(2) Invoke Employee’s overloaded constructor");
System.out.println("(3) Employee's no-arg constructor is invoked");
}

public Employee(String s) {
System.out.println(s);
}
}

class Person {
public Person() {
System.out.println("(1) Person's no-arg constructor is invoked");
}
}
32
animation
Trace Execution
public class Faculty extends Employee {
public static void main(String[] args) {
new Faculty(); 2. Invoke Faculty
} constructor
public Faculty() {
System.out.println("(4) Faculty's no-arg constructor is invoked");
}
}

class Employee extends Person {


public Employee() {
this("(2) Invoke Employee’s overloaded constructor");
System.out.println("(3) Employee's no-arg constructor is invoked");
}

public Employee(String s) {
System.out.println(s);
}
}

class Person {
public Person() {
System.out.println("(1) Person's no-arg constructor is invoked");
}
}
33
animation
Trace Execution
public class Faculty extends Employee {
public static void main(String[] args) {
new Faculty();
}

public Faculty() {
System.out.println("(4) Faculty's no-arg constructor is invoked");
}
} 3. Invoke Employee’s no-
class Employee extends Person {
arg constructor
public Employee() {
this("(2) Invoke Employee’s overloaded constructor");
System.out.println("(3) Employee's no-arg constructor is invoked");
}

public Employee(String s) {
System.out.println(s);
}
}

class Person {
public Person() {
System.out.println("(1) Person's no-arg constructor is invoked");
}
}
34
animation
Trace Execution
public class Faculty extends Employee {
public static void main(String[] args) {
new Faculty();
}

public Faculty() {
System.out.println("(4) Faculty's no-arg constructor is invoked");
}
}
4. Invoke Employee(String)
class Employee extends Person { constructor
public Employee() {
this("(2) Invoke Employee’s overloaded constructor");
System.out.println("(3) Employee's no-arg constructor is invoked");
}

public Employee(String s) {
System.out.println(s);
}
}

class Person {
public Person() {
System.out.println("(1) Person's no-arg constructor is invoked");
}
}
35
animation
Trace Execution
public class Faculty extends Employee {
public static void main(String[] args) {
new Faculty();
}

public Faculty() {
System.out.println("(4) Faculty's no-arg constructor is invoked");
}
}

class Employee extends Person {


public Employee() {
this("(2) Invoke Employee’s overloaded constructor");
System.out.println("(3) Employee's no-arg constructor is invoked");
}

public Employee(String s) {
System.out.println(s);
}
} 5. Invoke Person() constructor
class Person {
public Person() {
System.out.println("(1) Person's no-arg constructor is invoked");
}
}
36
animation
Trace Execution
public class Faculty extends Employee {
public static void main(String[] args) {
new Faculty();
}

public Faculty() {
System.out.println("(4) Faculty's no-arg constructor is invoked");
}
}

class Employee extends Person {


public Employee() {
this("(2) Invoke Employee’s overloaded constructor");
System.out.println("(3) Employee's no-arg constructor is invoked");
}

public Employee(String s) {
System.out.println(s);
}
}
6. Execute println
class Person {
public Person() {
System.out.println("(1) Person's no-arg constructor is invoked");
}
}
37
animation
Trace Execution
public class Faculty extends Employee {
public static void main(String[] args) {
new Faculty();
}

public Faculty() {
System.out.println("(4) Faculty's no-arg constructor is invoked");
}
}

class Employee extends Person {


public Employee() {
this("(2) Invoke Employee’s overloaded constructor");
System.out.println("(3) Employee's no-arg constructor is invoked");
}

public Employee(String s) {
System.out.println(s);
}
}
7. Execute println
class Person {
public Person() {
System.out.println("(1) Person's no-arg constructor is invoked");
}
}
38
animation
Trace Execution
public class Faculty extends Employee {
public static void main(String[] args) {
new Faculty();
}

public Faculty() {
System.out.println("(4) Faculty's no-arg constructor is invoked");
}
}

class Employee extends Person {


public Employee() {
this("(2) Invoke Employee’s overloaded constructor");
System.out.println("(3) Employee's no-arg constructor is invoked");
}

public Employee(String s) {
System.out.println(s);
}
}
8. Execute println
class Person {
public Person() {
System.out.println("(1) Person's no-arg constructor is invoked");
}
}
39
animation
Trace Execution
public class Faculty extends Employee {
public static void main(String[] args) {
new Faculty();
}

public Faculty() {
System.out.println("(4) Faculty's no-arg constructor is invoked");
}
}
9. Execute println
class Employee extends Person {
public Employee() {
this("(2) Invoke Employee’s overloaded constructor");
System.out.println("(3) Employee's no-arg constructor is invoked");
}

public Employee(String s) {
System.out.println(s);
}
}

class Person {
public Person() {
System.out.println("(1) Person's no-arg constructor is invoked");
}
}
40
The Need of Constructor Chaining
• Suppose, there are five tasks to perform. There are two ways to
perform these tasks, either implement all the tasks in a single
constructor or create separate tasks in a single constructor.
• By using the constructor chaining mechanism, we can implement
multiple tasks in a single constructor. So, whenever we face such
types of problems, we should use constructor chaining. We can make
the program more readable and understandable by using constructor
chaining.
Rules of Constructor Chaining
• An expression that uses this keyword must be the first
line of the constructor.
• Order does not matter in constructor chaining.
• There must exist at least one constructor that does not
use this
Constructor Calling form another Constructor
• The calling of the constructor can be done in two ways:
• By using this() keyword: It is used when we want to call
the current class constructor within the same class.
• By using super() keyword: It is used when we want to
call the superclass constructor from the base class.
• Note: In the same constructor block, we cannot use this() and
super() simultaneously.
Constructor Chaining Examples
Calling Current Class Constructor
• We use this() keyword if we want to call the current class constructor
within the same class. The use of this() is mandatory because JVM never
put it automatically like the super() keyword. Note that this() must be the
first line of the constructor. There must exist at least one constructor
without this() keyword.
• Syntax:
this(); or this(parameters list);
• For example:
this();
this("Javatpoint");

public class ConstructorChain
In the above example, we have created an {
instance of the class without passing any //default constructor
parameter. It first calls the default ConstructorChain()
constructor and the default constructor {
redirects the call to the parameterized one this("Javatpoint");
because of this(). The statements inside the System.out.println("Default constructor called.");
parameterized constructor are executed }
and return back to the default constructor. //parameterized constructor
After that, the rest of the statements in the ConstructorChain(String str)
default constructor is executed and the {
object is successfully initialized. The System.out.println("Parameterized constructor called");
following is the calling sequence of the }
constructor: //main method
public static void main(String args[])
{
//initializes the instance of example class
ConstructorChain cc = new ConstructorChain();
}
}
Calling Super Class Constructor
• Sometimes, we need to call the superclass (parent class) constructor
from the child class (derived class) in such cases, we use the super()
keyword in the derived class constructor. It is optional to write super()
because JVM automatically puts it. It should always write in the first
line. We get a syntax error if we try to call a superclass constructor in
the child class.
• Syntax:
super(); or super(Parameter List);
• super(): It calls the no-argument or default constructor of the
superclass.
• super(parameters): It invokes the superclass parameterized
constructor.
• Remember that the superclass constructor cannot be inherited in the
subclass. It can be called from the subclass constructor by using the
super keyword.
//derived class or child class
//parent class or base class class Prototype extends Demo
class Demo {
{ //derived class default constructor
//base class default constructor Prototype()
Demo() {
{ this("Java", "Python");
this(80, 90); System.out.println("Derived class default constructor called");
System.out.println("Base class default constructor called"); }
} //derived class parameterized constructor
//base class parameterized constructor Prototype(String str1, String str2)
Demo(int x, int y) {
{ super();
System.out.println("Base class parameterized constructor System.out.println("Derived class parameterized constructor
called"); called");
} } }
} public class ConstructorChaining
{
//main method
public static void main(String args[])
{
//initializes the instance of example class
Prototype my_example = new Prototype();
} }
Defining a Subclass
A subclass inherits from a superclass. You can also:
❑ Add new properties
❑ Add new methods
❑ Override the methods of the superclass

48
Calling Superclass Methods
You could rewrite the printCircle() method in the Circle class as
follows:

public void printCircle() {


System.out.println("The circle is created " +
super.getDateCreated() + " and the radius is " + radius);
}

49
Overriding Methods in the Superclass
A subclass inherits methods from a superclass. Sometimes it is
necessary for the subclass to modify the implementation of a method
defined in the superclass. This is referred to as method overriding.

public class Circle extends GeometricObject {


// Other methods are omitted

/** Override the toString method defined in GeometricObject */


public String toString() {
return super.toString() + "\nradius is " + radius;
}
}

50
Method Overloading

• Method overloading in java is a feature that allows a class to


have more than one method with the same name, but with
different parameters.
• Java supports method overloading through two
mechanisms:
1. By changing the number of parameters
2.By changing the data type of parameters Overloading by
changing the number of parameters A method can be
overloaded by changing the number of parameters.
• Method overloading cannot be done by changing the return
type of methods.
NOTE

An instance method can be overridden only


if it is accessible. Thus a private method
cannot be overridden, because it is not
accessible outside its own class. If a method
defined in a subclass is private in its
superclass, the two methods are completely
unrelated.

52
NOTE

Like an instance method, a static method


can be inherited. However, a static method
cannot be overridden. If a static method
defined in the superclass is redefined in a
subclass, the method defined in the
superclass is hidden.

53
Overriding vs. Overloading
public class Test { public class Test {
public static void main(String[] args) { public static void main(String[] args) {
A a = new A(); A a = new A();
a.p(10); a.p(10);
a.p(10.0); a.p(10.0);
} }
} }

class B { class B {
public void p(double i) { public void p(double i) {
System.out.println(i * 2); System.out.println(i * 2);
} }
} }

class A extends B { class A extends B {


// This method overrides the method in B // This method overloads the method in B
public void p(double i) { public void p(int i) {
System.out.println(i); System.out.println(i);
} }
} }

54
The Object Class and Its Methods
Every class in Java is descended from the
java.lang.Object class. If no inheritance is
specified when a class is defined, the
superclass of the class is Object.

public class Circle { public class Circle extends Object {


... Equivalent
...
} }

55
The toString() method in Object
The toString() method returns a string representation of the
object. The default implementation returns a string consisting
of a class name of which the object is an instance, the at sign
(@), and a number representing this object.

Loan loan = new Loan();


System.out.println(loan.toString());

The code displays something like Loan@15037e5 . This


message is not very helpful or informative. Usually you should
override the toString method so that it returns a digestible string
representation of the object.

56
Thanks
References
• Java: How To Program, Early Objects, 11th edition
• Cay S. Horstmann, Big Java: Late Objects

• Introduction to Java Programming and Data Structures, Comprehensive Version 12th


Edition, by Y. Liang (Author), Y. Daniel Liang
• Java documentation https://docs.oracle.com/javase
• Introduction to Java Programming and Data Structures, 12E, Y. Daniel Liang - TestSimpleCircle.java (pearsoncmg.com)
• Introduction to Java Programming and Data Structures, 12E, Y. Daniel Liang - CircleWithStaticMembers.java (pearsoncmg.com)
• Introduction to Java Programming and Data Structures, 12E, Y. Daniel Liang - TestCircleWithStaticMembers.java (pearsoncmg.com)
• Introduction to Java Programming and Data Structures, 12E, Y. Daniel Liang - CircleWithPrivateDataFields.java (pearsoncmg.com)
• Introduction to Java Programming and Data Structures, 12E, Y. Daniel Liang - TestCircleWithPrivateDataFields.java (pearsoncmg.com)
• Introduction to Java Programming and Data Structures, 12E, Y. Daniel Liang - TestPassObject.java (pearsoncmg.com)
References
• Introduction to Java Programming and Data Structures, 12E, Y. Daniel Liang - TestPassArray.java
(pearsoncmg.com)
• Introduction to Java Programming and Data Structures, 12E, Y. Daniel Liang - TestMax.java (pearsoncmg.com)
• Introduction to Java Programming and Data Structures, 12E, Y. Daniel Liang - Weather.java (pearsoncmg.com)
• Introduction to Java Programming and Data Structures, 12E, Y. Daniel Liang - TotalScore.java
(pearsoncmg.com)
• Introduction to Java Programming and Data Structures, 12E, Y. Daniel Liang - GradeExam.java
(pearsoncmg.com)
• Introduction to Java Programming and Data Structures, 12E, Y. Daniel Liang - CheckSudokuSolution.java
(pearsoncmg.com)
• Binary Search Animation by Y. Daniel Liang (pearsoncmg.com)
Advanced Programming Language
Dr. Ahmed Hesham Mostafa
Dr. Mohamed Atia
Lecture 5 – OOP Part 3
Polymorphism
Polymorphism means that a variable of a supertype can
refer to a subtype object.

A class defines a type. A type defined by a


subclass is called a subtype, and a type defined by
its superclass is called a supertype. Therefore, you
can say that Circle is a subtype of
GeometricObject and GeometricObject is a
supertype for Circle.
PolymorphismDemo

PolymorphismDemo

2
Polymorphism, Dynamic Binding and Generic Programming
public class PolymorphismDemo {
public static void main(String[] args) {
m(new GraduateStudent());
Method m takes a parameter
m(new Student());
m(new Person());
of the Object type. You can
m(new Object()); invoke it with any object.
}

public static void m(Object x) { An object of a subtype can be used wherever its
System.out.println(x.toString());
} supertype value is required. This feature is
}
known as polymorphism.
class GraduateStudent extends Student {
}

class Student extends Person { When the method m(Object x) is executed, the
public String toString() {
return "Student";
argument x’s toString method is invoked. x
} may be an instance of GraduateStudent,
}
Student, Person, or Object. Classes
class Person extends Object {
public String toString() {
GraduateStudent, Student, Person, and Object
return "Person"; have their own implementation of the toString
}
} method. Which implementation is used will be
determined dynamically by the Java Virtual
DynamicBindingDemo
Machine at runtime. This capability is known
DynamicBindingDemo as dynamic binding.

3
Generic Programming
public class PolymorphismDemo { Polymorphism allows methods to be used
public static void main(String[] args) {
m(new GraduateStudent()); generically for a wide range of object
m(new Student()); arguments. This is known as generic
m(new Person());
m(new Object()); programming. If a method’s parameter
} type is a superclass (e.g., Object), you may
public static void m(Object x) { pass an object to this method of any of
System.out.println(x.toString()); the parameter’s subclasses (e.g., Student
}
} or String). When an object (e.g., a Student
object or a String object) is used in the
class GraduateStudent extends Student {
} method, the particular implementation of
the method of the object that is invoked
class Student extends Person {
public String toString() { (e.g., toString) is determined dynamically.
return "Student";
}
}

class Person extends Object {


public String toString() {
return "Person";
}
}

6
Casting Objects
You have already used the casting operator to convert variables of
one primitive type to another. Casting can also be used to convert an
object of one class type to another within an inheritance hierarchy.
In the preceding section, the statement
m(new Student());

assigns the object new Student() to a parameter of the Object type.


This statement is equivalent to:

Object o = new Student(); // Implicit casting


m(o);

The statement Object o = new Student(), known as


implicit casting, is legal because an instance of
Student is automatically an instance of Object.
7
Why Casting Is Necessary?
Suppose you want to assign the object reference o to a variable of
the Student type using the following statement:

Student b = o;

A compile error would occur. Why does the statement Object o =


new Student() work and the statement Student b = o doesn’t? This is
because a Student object is always an instance of Object, but an
Object is not necessarily an instance of Student. Even though you can
see that o is really a Student object, the compiler is not so clever to
know it. To tell the compiler that o is a Student object, use an explicit
casting. The syntax is similar to the one used for casting among
primitive data types. Enclose the target object type in parentheses
and place it before the object to be cast, as follows:

Student b = (Student)o; // Explicit casting


8
Casting from
Superclass to Subclass
Explicit casting must be used when casting an object
from a superclass to a subclass. This type of casting may
not always succeed.
Apple x = (Apple)fruit;

Orange x = (Orange)fruit;

9
The instanceof Operator
Use the instanceof operator to test whether an object is an
instance of a class:

Object myObject = new Circle();


... // Some lines of code
/** Perform casting if myObject is an instance of
Circle */
if (myObject instanceof Circle) {
System.out.println("The circle diameter is " +
((Circle)myObject).getDiameter());
...
}

10
Example: Demonstrating
Polymorphism and Casting
This example creates two geometric objects: a
circle, and a rectangle, invokes the
displayGeometricObject method to display the
objects. The displayGeometricObject displays
the area and diameter if the object is a circle,
and displays area if the object is a rectangle.
CastingDemo

CastingDemo

12
public class CastingDemo {
/** Main method */
public static void main(String[] args) {
// Create and initialize two objects
Object object1 = new CircleFromSimpleGeometricObject(1);
Object object2 = new RectangleFromSimpleGeometricObject(1, 1);
// Display circle and rectangle
displayObject(object1);
displayObject(object2);
}
/** A method for displaying an object */
public static void displayObject(Object object) {
if (object instanceof CircleFromSimpleGeometricObject) {
System.out.println("The circle area is " +
((CircleFromSimpleGeometricObject)object).getArea());
System.out.println("The circle diameter is " +
((CircleFromSimpleGeometricObject)object).getDiameter());
}
else if (object instanceof
RectangleFromSimpleGeometricObject) {
System.out.println("The rectangle area is " +
((RectangleFromSimpleGeometricObject)object).getArea());
}
}
}
The equals Method
The equals() method compares the
contents of two objects. The default implementation of
the equals method in the Object class is as follows:

public boolean equals(Object obj) {


return this == obj;
}
public boolean equals(Object o) {
For example, the if (o instanceof Circle) {
equals method is return radius == ((Circle)o).radius;
overridden in }
the Circle else
return false;
class. }

14
NOTE
The == comparison operator is used for
comparing two primitive data type values or for
determining whether two objects have the same
references. The equals method is intended to
test whether two objects have the same
contents, provided that the method is modified
in the defining class of the objects. The ==
operator is stronger than the equals method, in
that the == operator checks whether the two
reference variables refer to the same object.
15
The ArrayList Class
You can create an array to store objects. But the array’s size is fixed
once the array is created. Java provides the ArrayList class that can
be used to store an unlimited number of objects.

java.util.ArrayList<E>
+ArrayList() Creates an empty list.
+add(o: E) : void Appends a new element o at the end of this list.
+add(index: int, o: E) : void Adds a new element o at the specified index in this list.
+clear(): void Removes all the elements from this list.
+contains(o: Object): boolean Returns true if this list contains the element o.
+get(index: int) : E Returns the element from this list at the specified index.
+indexOf(o: Object) : int Returns the index of the first matching element in this list.
+isEmpty(): boolean Returns true if this list contains no elements.
+lastIndexOf(o: Object) : int Returns the index of the last matching element in this list.
+remove(o: Object): boolean Removes the element o from this list.
+size(): int Returns the number of elements in this list.
+remove(index: int) : boolean Removes the element at the specified index.
+set(index: int, o: E) : E Sets the element at the specified index.

16
Generic Type
ArrayList is known as a generic class with a generic type E.
You can specify a concrete type to replace E when creating
an ArrayList. For example, the following statement creates
an ArrayList and assigns its reference to variable cities. This
ArrayList object can be used to store strings.

ArrayList<String> cities = new ArrayList<String>();

ArrayList<String> cities = new ArrayList<>();


TestArrayList

TestArrayList
17
Differences and Similarities between Arrays
and ArrayList
Operation Array ArrayList

Creating an array/ArrayList String[] a = new String[10] ArrayList<String> list = new ArrayList<>();


Accessing an element a[index] list.get(index);
Updating an element a[index] = "London"; list.set(index, "London");
Returning size a.length list.size();
Adding a new element list.add("London");
Inserting a new element list.add(index, "London");
Removing an element list.remove(index);
Removing an element list.remove(Object);
Removing all elements list.clear();

DistinctNumbers

DistinctNumbers

18
Array Lists from/to Arrays
Creating an ArrayList from an array of objects:
String[] array = {"red", "green", "blue"};
ArrayList<String> list = new
ArrayList<>(Arrays.asList(array));

Creating an array of objects from an ArrayList:


String[] array1 = new String[list.size()];
list.toArray(array1);

19
Stack Animation
https://liveexample.pearsoncmg.com/dsanimation/StackeBook.html

22
The MyStack Classes
A stack to hold objects.
MyStack

MyStack

MyStack
-list: ArrayList A list to store elements.
+isEmpty(): boolean Returns true if this stack is empty.
+getSize(): int Returns the number of elements in this stack.
+peek(): Object Returns the top element in this stack.
+pop(): Object Returns and removes the top element in this stack.
+push(o: Object): void Adds a new element to the top of this stack.
+search(o: Object): int Returns the position of the first element in the stack from
the top that matches the specified element.

23
import java.util.ArrayList;
public class MyStack {
public class Main {
private ArrayList<Object> list = new ArrayList<>();
public boolean isEmpty() { public static void main(String[] args) {
return list.isEmpty(); MyStack obj=new MyStack();
} obj.push(5);
public int getSize() { obj.push("ahmed");
return list.size(); obj.push(3.7);
} obj.push('a');
public Object peek() { while(!obj.isEmpty()){
return list.get(getSize() - 1); System.out.println(obj.pop());
}
}
public Object pop() {
Object o = list.get(getSize() - 1); }
list.remove(getSize() - 1); }
return o;
} a
public void push(Object o) {
list.add(o); 3.7
}
@Override /** Override the toString in the Object class */
ahmed
public String toString() { 5
return "stack: " + list.toString();
}}
The protected Modifier
❑The protected modifier can be applied on data
and methods in a class. A protected data or a
protected method in a public class can be accessed
by any class in the same package or its subclasses,
even if the subclasses are in a different package.
❑private, default, protected, public

Visibility increases

private, none (if no modifier is used), protected, public

25
Accessibility Summary

Modifier Accessed Accessed Accessed Accessed


on members from the from the from a from a different
in a class same class same package subclass package

public

protected -

default - -

private - - -

26
Visibility Modifiers
package p1;
public class C1 { public class C2 {
public int x; C1 o = new C1();
protected int y; can access o.x;
int z; can access o.y;
private int u; can access o.z;
cannot access o.u;
protected void m() {
} can invoke o.m();
} }

package p2;

public class C3 public class C4 public class C5 {


extends C1 { extends C1 { C1 o = new C1();
can access x; can access x; can access o.x;
can access y; can access y; cannot access o.y;
can access z; cannot access z; cannot access o.z;
cannot access u; cannot access u; cannot access o.u;
can invoke m(); can invoke m(); cannot invoke o.m();
} } }

27
The final Modifier
❑The final class cannot be extended:
final class Math {
...
}

❑The final variable is a constant:


final static double PI = 3.14159;

❑The final method cannot be


overridden by its subclasses.

30
Abstract Classes and Abstract Methods
GeometricObject

GeometricObject
Circle

Circle
Rectangle

Rectangle
TestGeometricObject

TestGeometricObject

31 31
abstract method in abstract class
An abstract method cannot be contained in a
nonabstract class. If a subclass of an abstract
superclass does not implement all the abstract
methods, the subclass must be defined abstract. In
other words, in a nonabstract subclass extended from
an abstract class, all the abstract methods must be
implemented, even if they are not used in the
subclass.

32 32
object cannot be created from abstract
class
An abstract class cannot be instantiated using
the new operator, but you can still define its
constructors, which are invoked in the
constructors of its subclasses. For instance,
the constructors of GeometricObject are
invoked in the Circle class and the Rectangle
class.

33 33
abstract class without abstract method

A class that contains abstract methods must


be abstract. However, it is possible to define
an abstract class that contains no abstract
methods. In this case, you cannot create
instances of the class using the new operator.
This class is used as a base class for defining
a new subclass.

34 34
superclass of abstract class may be
concrete

A subclass can be abstract even if its


superclass is concrete. For example, the
Object class is concrete, but its subclasses,
such as GeometricObject, may be abstract.

35 35
abstract class as type

You cannot create an instance from an


abstract class using the new operator, but an
abstract class can be used as a data type.
Therefore, the following statement, which
creates an array whose elements are of
GeometricObject type, is correct.
GeometricObject[] geo = new GeometricObject[10];

37 37
Abstract Classes and Abstract Methods
GeometricObject

GeometricObject
Circle

Circle
Rectangle

Rectangle
TestGeometricObject

TestGeometricObject

38 38
public abstract class GeometricObject {
private String color = "white"; public boolean isFilled() {
private boolean filled; return filled;
private java.util.Date dateCreated; }

public void setFilled(boolean filled) {


protected GeometricObject() { this.filled = filled;
dateCreated = new java.util.Date(); }
}
public java.util.Date getDateCreated() {
protected GeometricObject(String color, boolean filled) { return dateCreated;
dateCreated = new java.util.Date(); }
this.color = color;
this.filled = filled; @Override
public String toString() {
}
return "created on " + dateCreated + "\ncolor: " + color +
" and filled: " + filled;
public String getColor() { }
return color;
} public abstract double getArea();
public void setColor(String color) {
this.color = color; public abstract double getPerimeter();
} }
public class Circle extends GeometricObject {
private double radius;
public Circle() {
}
public Circle(double radius) {
this.radius = radius;
}
public double getRadius() {
return radius;
}
public void setRadius(double radius) {
this.radius = radius;
}
@Override /** Return area */
public double getArea() {
return radius * radius * Math.PI;
}
public double getDiameter() {
return 2 * radius;
}
@Override /** Return perimeter */
public double getPerimeter() {
return 2 * radius * Math.PI;
}
public void printCircle() {
System.out.println("The circle is created " + getDateCreated() +
" and the radius is " + radius);
}
}
public class Rectangle extends GeometricObject {
private double width;
private double height;
public void setHeight(double height) {
public Rectangle() {
} this.height = height;
public Rectangle(double width, double height) { }
this.width = width; @Override /** Return area */
this.height = height; public double getArea() {
}
return width * height;
public double getWidth() {
return width; }
} @Override /** Return perimeter */
public void setWidth(double width) { public double getPerimeter() {
this.width = width; return 2 * (width + height);
}
}
public double getHeight() {
return height; }
}
public class Main {
public static void main(String[] args) {
GeometricObject geoObject1 = new Circle(5); The two objects have the same area? false
GeometricObject geoObject2 = new Rectangle(5, 3);
System.out.println("The two objects have the same area? " + The area is 78.53981633974483
equalArea(geoObject1, geoObject2)); The perimeter is 31.41592653589793
displayGeometricObject(geoObject1);
displayGeometricObject(geoObject2); The area is 15.0
}
The perimeter is 16.0

public static boolean equalArea(GeometricObject object1,


GeometricObject object2) {
return object1.getArea() == object2.getArea();
}
public static void displayGeometricObject(GeometricObject object) {
System.out.println();
System.out.println("The area is " + object.getArea());
System.out.println("The perimeter is " + object.getPerimeter());
}
}
Interfaces
What is an interface?
Why is an interface useful?
How do you define an interface?
How do you use an interface?

43 43
Realization
• Realization is a relationship between the blueprint class and
the object containing its respective implementation level
details. This object is said to realize the blueprint class. In
other words, you can understand this as the relationship
between the interface and the implementing class.
What is an interface?
Why is an interface useful?
An interface is a classlike construct that contains only
constants and abstract methods. In many ways, an
interface is similar to an abstract class, but the intent of
an interface is to specify common behavior for objects.
For example, you can specify that the objects are
comparable, edible, cloneable using appropriate
interfaces.

45 45
Define an Interface
To distinguish an interface from a class, Java uses the
following syntax to define an interface:
public interface InterfaceName {
constant declarations;
abstract method signatures;
}

Example:
public interface Edible {
/** Describe how to eat */
public abstract String howToEat();
}
46 46
Interface is a Special Class
An interface is treated like a special class in Java.
Each interface is compiled into a separate bytecode file,
just like a regular class. Like an abstract class, you cannot
create an instance from an interface using the new
operator, but in most cases you can use an interface more
or less the same way you use an abstract class.
For example, you can use an interface as a data type for a
variable, as the result of casting, and so on.

47 47
Omitting Modifiers in Interfaces
All data fields are public final static and all methods are public
abstract in an interface. For this reason, these modifiers can be
omitted, as shown below:

public interface T1 { public interface T1 {


public static final int K = 1; Equivalent int K = 1;

public abstract void p(); void p();


} }

A constant defined in an interface can be accessed using syntax


InterfaceName.CONSTANT_NAME (e.g., T1.K).

48 48
Interfaces vs. Abstract Classes
In an interface, the data must be constants; an abstract class can
have all types of data.
Each method in an interface has only a signature without
implementation; an abstract class can have concrete methods.

49 49
Interfaces vs. Abstract Classes, cont.
All classes share a single root, the Object class, but there is no single root for
interfaces. Like a class, an interface also defines a type. A variable of an interface
type can reference any instance of the class that implements the interface. If a class
extends an interface, this interface plays the same role as a superclass. You can use
an interface as a data type and cast a variable of an interface type to its subclass,
and vice versa.

Suppose that c is an instance of Class2. c is also an instance of Object, Class1,


Interface1, Interface1_1, Interface1_2, Interface2_1, and Interface2_2.
50 50
Interface Example

public interface Employee {


public double calculateSalary(double workedHours);
}
Interface Example
public class Payroll {
Employee employee;
public Payroll(Employee employee) {
this.employee = employee;
}

public double calculateSalary(double workedHours){


return this.employee.calculateSalary(workedHours);
}
}
Interface Example
public class Developer implements Employee{
private double workedHourCost;
public double getWorkedHourCost() {
return workedHourCost;
}
public void setWorkedHourCost(double workedHourCost) {
this.workedHourCost = workedHourCost;
}
@Override
public double calculateSalary(double workedHours) {
return workedHours*getWorkedHourCost();
}
}
Interface Example
public class Tester implements Employee{
private double workedHourCost;
public double calculateBounce(double hoursworked){
if(hoursworked>100)return 500;
return 0;
}
public double getWorkedHourCost() {
return workedHourCost;
}
public void setWorkedHourCost(double workedHourCost) {
this.workedHourCost = workedHourCost;
}
@Override
public double calculateSalary(double workedHours) {
return workedHours*getWorkedHourCost();
}
}
Interface Example
public class TeamLeader implements Employee{
private double workedHourCost;
public double getWorkedHourCost() {
return workedHourCost;
}

public void setWorkedHourCost(double workedHourCost) {


this.workedHourCost = workedHourCost;
}
@Override
public double calculateSalary(double workedHours) {
return workedHours*getWorkedHourCost();
}
}
Interface Example
Interface Example
public class Main {
Dev salary = 1200.0
public static void main(String[] args) {
Developer ahmed=new Developer(); Leader salary = 2000.0
ahmed.setWorkedHourCost(12); Tester salary = 800.0
TeamLeader hesham=new TeamLeader();
hesham.setWorkedHourCost(20);
Tester mostafa=new Tester();
mostafa.setWorkedHourCost(8);

System.out.println("Dev salary = "+ new Payroll(ahmed).calculateSalary(100));


System.out.println("Leader salary = "+new Payroll(hesham).calculateSalary(100));
System.out.println("Tester salary = "+ new Payroll(mostafa).calculateSalary(100));
}
}
The Comparable Interface
• The Comparable interface defines the compareTo method for
comparing objects.
• Suppose you want to design a generic method to find the larger of
two objects of the same type,
• such as two students, two dates, two circles, two rectangles, or two
squares. In order to accomplish this, the two objects must be
comparable, so the common behavior for the objects must be
compara-ble.
• Java provides the Comparable interface for this purpose. The
package java.lang;
interface is defined as follows: public interface Comparable<E> {
public int compareTo(E o);
}
The Comparable Interface
• The compareTo method determines the order of this object with the
specified object o and returns a negative integer, zero, or a positive
integer if this object is less than, equal to, or greater than o.
• The Comparable interface is a generic interface. The generic type E is
replaced by a concrete type when implementing this interface.
• Many classes in the Java library implement Comparable to define a
natural order for objects.
• The classes Byte, Short, Integer, Long, Float, Double, Character,
BigInteger, BigDecimal, Calendar, String, and Date all implement the
Comparable interface.
Example
1 System.out.println(new Integer(3).compareTo(new Integer(5)));
2 System.out.println("ABC".compareTo("ABE"));
3 java.util.Date date1 = new java.util.Date(2013, 1, 1);
4 java.util.Date date2 = new java.util.Date(2012, 1, 1);
5 System.out.println(date1.compareTo(date2));
displays
Line 1 displays a negative value since 3 is less than 5.
−1 Line 2 displays zero since ABC is equal to ABC.
0 Line 5 displays a positive value since date1 is greater than date2.

60 60
Generic sort Method
Let n be an Integer object, s be a String object, and d be a
Date object. All the following expressions are true.

n instanceof Integer s instanceof String d instanceof java.util.Date


n instanceof Object s instanceof Object d instanceof Object
n instanceof Comparable s instanceof Comparable d instanceof Comparable

The java.util.Arrays.sort(array) method requires that


the elements in an array are instances of
Comparable<E>.
SortComparableObjects

SortComparableObjects

61 61
import java.math.*;

public class SortComparableObjects {


public static void main(String[] args) {
String[] cities = {"Savannah", "Boston", "Atlanta", "Tampa"};
java.util.Arrays.sort(cities);
for (String city: cities)
System.out.print(city + " ");
System.out.println();

BigInteger[] hugeNumbers = {new BigInteger("2323231092923992"),


new BigInteger("432232323239292"),
new BigInteger("54623239292")};
java.util.Arrays.sort(hugeNumbers);
for (BigInteger number: hugeNumbers)
System.out.print(number + " ");
}
}

Atlanta Boston Savannah Tampa


54623239292 432232323239292 2323231092923992
Defining Classes to Implement Comparable

You can now use the sort method to sort an array of


ComparableRectangle objects,

ComparableRectangle SortRectangles

ComparableRectangle SortRectangles

63 63
public class ComparableRectangle extends Rectangle
implements Comparable<ComparableRectangle> {
/** Construct a ComparableRectangle with specified properties */
public ComparableRectangle(double width, double height) {
super(width, height);
}
@Override // Override the compareTo method defined in Comparable
public int compareTo(ComparableRectangle o) {
if (getArea() > o.getArea())
return 1;
else if (getArea() < o.getArea())
return -1;
else
return 0;
}
@Override // Implement the toString method in GeometricObject
public String toString() {
return "Width: " + getWidth() + " Height: " + getHeight() +
" Area: " + getArea();
}
}
public class SortRectangles {
public static void main(String[] args) {
ComparableRectangle[] rectangles = {
new ComparableRectangle(3.4, 5.4),
new ComparableRectangle(13.24, 55.4),
new ComparableRectangle(7.4, 35.4),
new ComparableRectangle(1.4, 25.4)};
java.util.Arrays.sort(rectangles);
for (Rectangle rectangle: rectangles) {
System.out.print(rectangle + " ");
System.out.println();
}
}
}
Width: 3.4 Height: 5.4 Area: 18.36
Width: 1.4 Height: 25.4 Area: 35.559999999999995
Width: 7.4 Height: 35.4 Area: 261.96
Width: 13.24 Height: 55.4 Area: 733.496
compareTo
• The Object class contains the equals method, which is intended for the subclasses of the
Object class to override in order to compare whether the contents of the objects are the
same.
• Suppose the Object class contains the compareTo method, as defined in the Comparable
interface; the sort method can be used to compare a list of any objects. Whether a
compareTo method should be included in the Object class is debatable.
• Since the compareTo method is not defined in the Object class, the Comparable interface
is defined in Java to enable objects to be compared if they are instances of the
Comparable interface.
• compareTo should be consistent with equals.
• That is, for two objects o1 and o2, o1.compareTo(o2) == 0 if and only if o1.equals(o2) is
true.
• Therefore, you should also override the equals method in the ComparableRectangle class
to return true if two rectangles have the same area.
The Cloneable Interfaces
• Cloning is a technique for creating an exact copy of Java objects. By copy,
we mean that all the data are replicated in the newly copied object.
• To create an exact copy of an object in Java, we use a Clonable interface. A
Java class implements the Clonable interface to create a clone of the class
object. The Cloneable interface exists in the java.lang package.
• A Cloneable interface in Java is used to clone an object in the Java class.
The object class has a clone() method, which creates an exact copy of the
object. The cloned object has a separate space in memory where the copy
of the original object is stored. If a class doesn't implement the clonable
interface and we try to clone the object, we get an exception called
CloneNotSupportedException.
The Cloneable Interfaces
Marker Interface: An empty interface.
A marker interface does not contain constants or methods.
It is used to denote that a class possesses certain desirable
properties. A class that implements the Cloneable
interface is marked cloneable, and its objects can be
cloned using the clone() method defined in the Object
class.

package java.lang;
public interface Cloneable {
}

68 68
Examples
Many classes (e.g., Date and Calendar) in the Java library implement
Cloneable. Thus, the instances of these classes can be cloned. For
example, the following code

Calendar calendar = new GregorianCalendar(2003, 2, 1);


Calendar calendarCopy = (Calendar)calendar.clone();
System.out.println("calendar == calendarCopy is " +
(calendar == calendarCopy));
System.out.println("calendar.equals(calendarCopy) is " +
calendar.equals(calendarCopy));

displays
calendar == calendarCopy is false
calendar.equals(calendarCopy) is true

69 69
Implementing Cloneable Interface
To define a custom class that implements the Cloneable
interface, the class must override the clone() method in
the Object class. The following code defines a class
named House that implements Cloneable and
Comparable.

House

House

70 70
@Override /** Override the protected
public class House implements Cloneable,
clone method defined in
Comparable<House> {
the Object class, and strengthen its
private int id;
accessibility */
private double area;
public Object clone() {
private java.util.Date whenBuilt;
try {
return super.clone();
public House(int id, double area) {
}
this.id = id;
catch (CloneNotSupportedException ex) {
this.area = area;
return null;
whenBuilt = new java.util.Date();
}
}
}
public int getId() {
@Override // Implement the compareTo
return id;
method defined in Comparable
}
public int compareTo(House o) {
public double getArea() {
if (area > o.area)
return area;
return 1;
}
else if (area < o.area)
public java.util.Date getWhenBuilt() {
return -1;
return whenBuilt;
else
}
return 0;
}
}
Shallow vs. Deep Copy
• You can now create an object of the House class and create an identical copy from it, as follows:
• House house1 = new House(1, 1750.50);
• House house2 = (House)house1.clone();
• house1 and house2 are two different objects with identical contents. The clone method in the
Object class copies each field from the original object to the target object.
• If the field is of a primitive type, its value is copied. For example, the value of area (double type) is
copied from house1 to house2.
• If the field is of an object, the reference of the field is copied. For example, the field whenBuilt is
of the Date class, so its reference is copied into house2
• Therefore, house1.whenBuilt == house2.whenBuilt is true,
• although house1 == house2 is false.
• This is referred to as a shallow copy rather than a deep copy, meaning if the field is of an object
type, the object’s reference is copied rather than its contents.
Shallow vs. Deep Copy
House house1 = new House(1, 1750.50);
House house2 = (House)house1.clone();

Shallow
Copy

73 73
Shallow vs. Deep Copy
To perform a deep copy for a House object, replace the clone() method in lines 26–33 with the following
code

public Object clone() throws CloneNotSupportedException {


// Perform a shallow copy
House houseClone = (House)super.clone();
// Deep copy on whenBuilt
houseClone.whenBuilt = (java.util.Date)(whenBuilt.clone());
return houseClone;
}
Shallow vs. Deep Copy
House house1 = new House(1, 1750.50);
House house2 = (House)house1.clone();

Deep
Copy

75 75
Thanks
References
• Introduction to Java Programming and Data Structures, Comprehensive Version 12th
Edition, by Y. Liang (Author), Y. Daniel Liang
• This slides based on slides provided by Introduction to Java Programming and Data Structures,
Comprehensive Version 12th Edition, by Y. Liang (Author), Y. Daniel Liang
Advanced Programming Language
Dr. Ahmed Hesham Mostafa
Dr. Mohamed Atia
Lecture 6 – Exceptions handling
Exception
• In Java, runtime errors are thrown as exceptions.
• An exception is an object that represents an error or a condition that
prevents execution from proceeding normally.
• If the exception is not handled, the program will terminate
abnormally.
• How can you handle the exception so the program can continue to
run or else terminate gracefully?
Exception-Handling Overview
• Show runtime error
Quotient

Quotient

QuotientWithIf

• Fix it using an if statement QuotientWithIf

• With a method
QuotientWithIf

QuotientWithIf
Exception-Handling Overview
Show runtime error
Enter two integers: 1 0
Exception in thread "main"
import java.util.Scanner; java.lang.ArithmeticException: / by zero
public class Main { at Main.main(Main.java:9)
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
// Prompt the user to enter two integers
System.out.print("Enter two integers: ");
int number1 = input.nextInt();
int number2 = input.nextInt();
System.out.println(number1 + " / " + number2 + " is " +(number1 / number2));
}
}
Exception-Handling Overview
Fix it using an if statement
import java.util.Scanner;
public class Main { Enter two integers: 1 0
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
Divisor cannot be zero
System.out.print("Enter two integers: ");
int number1 = input.nextInt();
int number2 = input.nextInt();
if (number2 != 0)
System.out.println(number1 + " / " + number2 + " is " +
(number1 / number2));
else
System.out.println("Divisor cannot be zero ");
}
}
Exception-Handling
public class Main { Overview
public static int quotient(int number1, int number2) {
if (number2 == 0) { With a method
System.out.println("Divisor cannot be zero");
System.exit(1);
} Enter two integers: 1 0
return number1 / number2; Divisor cannot be zero
}
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.print("Enter two integers: ");
int number1 = input.nextInt();
int number2 = input.nextInt();
int result = quotient(number1, number2);
System.out.println(number1 + " / " + number2 + " is "+ result);
}}
Exception-Handling Overview
With a method
• The method quotient (previous slide) returns the quotient of two
integers. If number2 is 0, it cannot return a value, so the program is
terminated in line 7.
• This is clearly a problem. You should not let the method terminate
the program—the caller should decide whether to terminate the
program.
• How can a method notify its caller an exception has occurred? Java
enables a method to throw an exception that can be caught and
handled by the caller . as shown in next slide.
import java.util.Scanner;
public class Main {
public static int quotient(int number1, int number2) {
if (number2 == 0)
using exception
throw new ArithmeticException("Divisor cannot be zero"); handling
return number1 / number2;
}
public static void main(String[] args) {
Enter two integers: 1 0
Scanner input = new Scanner(System.in);
System.out.print("Enter two integers: "); Exception: an integer cannot be divided by zero
int number1 = input.nextInt(); Execution continues ...
int number2 = input.nextInt();
try {
int result = quotient(number1, number2);
System.out.println(number1 + " / " + number2 + " is " + result);
}
catch (ArithmeticException ex) {
System.out.println("Exception: an integer " +"cannot be divided by zero
");
}
System.out.println("Execution continues ...");
}
}
using exception handling
• The value thrown, in this case new ArithmeticException("Divisor
cannot be zero"), is called an exception.
• The execution of a throw statement is called throwing an exception.
• The exception is an object created from an exception class. In this
case, the exception class is java.lang.ArithmeticException.
• The constructor ArithmeticException(str) is invoked to construct an
exception object, where str is a message that describes the exception.
using exception handling
• When an exception is thrown, the normal execution flow is
interrupted. As the name suggests, to “throw an exception” is to pass
the exception from one place to another.
• The statement for invoking the method is contained in a try block.
The try block contains the code that is executed in normal scinario.
• The exception is caught by the catch block.
• The code in the catch block is executed to handle the exception.
Afterward, the statement after the catch block is executed.
using exception handling
• The throw statement is similar to a method call, but instead of calling
a method, it calls a catch block.
• In this sense, a catch block is like a method definition with a
parameter that matches the type of the value being thrown.
• Unlike a method, however, after the catch block is executed, the
program control does not return to the throw statement; instead, it
executes the next statement after the catch block.
using exception handling
• The identifier ex in the catch–block header catch
(ArithmeticException ex)
• acts very much like a parameter in a method. Thus, this parameter is
referred to as a catch block parameter.
• The type (e.g., ArithmeticException) preceding ex specifies what kind
of exception the catch block can catch.
• Once the exception is caught, you can access the thrown value from
this parameter in the body of a catch block.
using exception handling
• In summary, a template for a try-throw-catch block may look as follows:
try {
Code to run;
A statement or a method that may throw an exception;
More code to run;
}
catch (type ex) {
Code to process the exception;
}
using exception handling
• An exception may be thrown directly by using a throw statement in a
try block, or by invoking a method that may throw an exception.
• The main method invokes quotient (line 20). If the quotient method
executes normally, it returns a value to the caller.
• If the quotient method encounters an exception, it throws the
exception back to its caller.
• The caller’s catch block handles the exception.
Exception Advantages
• Now you see the advantages of using exception handling.
• It enables a method to throw an exception to its caller. Without this
capability, a method must handle the exception or terminate the
program.
• Often the called method does not know what to do in case of error.
Exception V.S If-else
• You should use if / else to handle all cases you expect. You
should not use try {} catch {} to handle everything (in most cases)
because a useful Exception could be raised and you can learn about
the presence of a bug from it.
• You should use try {} catch {} in situations where you suspect
something can/will go wrong and you don't want it to bring down the
whole system, like network timeout/file system access problems, files
doesn't exist, etc.
Handling InputMismatchException
InputMismatchExceptionDemo

InputMismatchExceptionDemo

By handling InputMismatchException, your program will


continuously read an input until it is correct.

17
import java.util.*; When executing input.nextInt() (line 11), an
public class InputMismatchExceptionDemo { InputMismatchException occurs if the input entered is not an
public static void main(String[] args) { integer. Suppose 3.5 is entered. An InputMismatchException
Scanner input = new Scanner(System.in); occurs and the control is transferred to the catch block. The
boolean continueInput = true; statements in the catch block are now executed. The
do { statement input.nextLine() in line 22 discards the current
try { input line so the user can enter a new line of input. The
System.out.print("Enter an integer: "); variable continueInput controls the loop. Its initial value is
int number = input.nextInt(); true (line 6) and it is changed to false (line 17) when a valid
// Display the result input is received. Once a valid input is received, there is no
System.out.println("The number entered is " + number); need to continue the input.
continueInput = false;
}
catch (InputMismatchException ex) {
System.out.println("Try again. (" +
"Incorrect input: an integer is required)");
input.nextLine(); // discard input
}
} while (continueInput);
}
}
Exception Types
ClassNotFoundException

ArithmeticException
IOException

Exception NullPointerException
RuntimeException
IndexOutOfBoundsException
Many more classes
Object Throwable IllegalArgumentException

Many more classes


LinkageError

Error VirtualMachineError

Many more classes


19
System Errors
ClassNotFoundException

ArithmeticException
IOException

Exception NullPointerException
RuntimeException
IndexOutOfBoundsException
Many more classes
Object Throwable IllegalArgumentException

Many more classes


System errors are thrown by JVM and
represented in the Error class. The LinkageError

Error class describes internal system


errors. Such errors rarely occur. If one Error VirtualMachineError
does, there is little you can do beyond
notifying the user and trying to Many more classes
terminate the program gracefully.

20
Exceptions
Exception describes errors ClassNotFoundException
caused by your program.
These errors can be caught ArithmeticException
IOException
and handled by your
program. Exception NullPointerException
RuntimeException
IndexOutOfBoundsException
Many more classes
Object Throwable IllegalArgumentException

Many more classes


LinkageError

Error VirtualMachineError

Many more classes

21
Runtime Exceptions
ClassNotFoundException

ArithmeticException
IOException

Exception NullPointerException
RuntimeException
IndexOutOfBoundsException
Many more classes
Object Throwable IllegalArgumentException

Many more classes


LinkageError
RuntimeException is caused by
programming errors, such as bad casting,
Error VirtualMachineError accessing an out-of-bounds array, and
numeric errors.
Many more classes

22
Examples of Subclasses of Exception
• ClassNotFoundException Attempt to use a class that does not exist.
This exception would occur, for example, if you tried to run a
nonexistent class using the java command or if your program were
composed of, say, three class files, only two of which could be found.
• IOException Related to input/output operations, such as invalid input,
reading past the end of a file, and opening a nonexistent file.
Examples of subclasses of IOException are InterruptedIOException,
EOFException (EOF is short for End of File), and
FileNotFoundException.
Checked Exceptions vs. Unchecked Exceptions
• RuntimeException, Error and their subclasses are known as
unchecked exceptions.
• All other exceptions are known as checked exceptions, meaning that
the compiler forces the programmer to check and deal with the
exceptions.
Unchecked Exceptions
• In most cases, unchecked exceptions reflect programming logic errors
that are not recoverable.
• For example, a NullPointerException is thrown if you access an object
through a reference variable before an object is assigned to it; an
IndexOutOfBoundsException is thrown if you access an element in an
array outside the bounds of the array.
• These are the logic errors that should be corrected in the program.
Unchecked exceptions can occur anywhere in the program.
• To avoid overuse of try-catch blocks, Java does not mandate you to
write code to catch unchecked exceptions.
Unchecked Exceptions
ClassNotFoundException

ArithmeticException
IOException

Exception NullPointerException
RuntimeException
IndexOutOfBoundsException
Many more classes
Object Throwable IllegalArgumentException

Many more classes


LinkageError

Error VirtualMachineError Unchecked


exception.

Many more classes

26
Declaring, Throwing, and Catching Exceptions

method1() { declare exception


method2() throws Exception {
try {
invoke method2; if (an error occurs) {
}
catch exception catch (Exception ex) { throw new Exception(); throw exception
Process exception; }
} }
}

Java’s exception-handling model is based on three operations:


declaring an exception, throwing an exception, and catching an
exception
Declaring Exceptions
• Every method must state the types of checked exceptions it might throw. This is
known as declaring exceptions.
• Because system errors and runtime errors can happen to any code, Java does not
require that you declare Error and RuntimeException (unchecked exceptions)
explicitly in the method. However, all other exceptions thrown by the method
must be explicitly declared in the method header so the caller of the method is
informed of the exception.
• The throws keyword indicates myMethod might throw an IOException.
• public void myMethod() throws IOException
• If the method might throw multiple exceptions, add a list of the
exceptions, separated by commas, after throws:public void myMethod()
throws IOException, OtherException,…,Exception
• If a method does not declare exceptions in the superclass, you cannot
override it to declare exceptions in the subclass.(Liskov Substitution )
Throwing Exceptions
When the program detects an error, the program can create an
instance of an appropriate exception type and throw it. This is known
as throwing an exception. Here is an example,

throw new TheException();

TheException ex = new TheException();


throw ex;
Throwing Exceptions Example
• Here is an example: Suppose the program detects that an argument
passed to the method violates the method contract (e.g., the
argument must be nonnegative, but a negative argument is passed);
the program can create an instance of IllegalArgumentException and
throw it, as follows:

IllegalArgumentException ex =
new IllegalArgumentException("Wrong Argument");
throw ex;
Or, if you prefer, you can use the following:
throw new IllegalArgumentException("Wrong Argument");
Throwing Exceptions Example
/** Set a new radius */
public void setRadius(double newRadius)
throws IllegalArgumentException {
if (newRadius >= 0)
radius = newRadius;
else
throw new IllegalArgumentException(
"Radius cannot be negative");
}
Note
• IllegalArgumentException is an exception class in the Java API.
• In general, each exception class in the Java API has at least two
constructors: a no-arg constructor and a constructor with a String
argument that describes the exception.
• This argument is called the exception message, which can be
obtained by invoking getMessage() from an exception object.
TIP
• The keyword to declare an exception is throws, and the keyword to
throw an exception is throw .
Catching Exceptions
try {
statements; // Statements that may throw
exceptions
}
catch (Exception1 exVar1) {
handler for exception1;
}
catch (Exception2 exVar2) {
handler for exception2;
}
...
catch (ExceptionN exVar3) {
handler for exceptionN;
}
Catching Exceptions
• If one of the statements inside the try block throws an exception,
Java skips the remaining statements in the try block and starts
the process of finding the code to handle the exception.
• The code that handles the exception is called the exception
handler; it is found by propagating the exception backward
through a chain of method calls, starting from the current
method.
• Each catch block is examined in turn, from first to last, to see
whether the type of the exception object is an instance of the
exception class in the catch block.
Catching Exceptions
• If so, the exception object is assigned to the variable declared
and the code in the catch block is executed.
• If no handler is found, Java exits this method, passes the
exception to the method’s caller, and continues the same process
to find a handler.
• If no handler is found in the chain of methods being invoked, the
program terminates and prints an error message on the console.
• The process of finding a handler is called catching a exception.
Catching Exceptions
main method { method1 { method2 { An exception
... ... ... is thrown in
try { try { try { method3
... ... ...
invoke method1; invoke method2; invoke method3;
statement1; statement3; statement5;
} } }
catch (Exception1 ex1) { catch (Exception2 ex2) { catch (Exception3 ex3) {
Process ex1; Process ex2; Process ex3;
} } }
statement2; statement4; statement6;
} } }

Call Stack
method3

method2 method2

method1 method1 method1

main method main method main method main method


Catching Exceptions
• Suppose the main method invokes method1, method1 invokes
method2, method2 invokes method3, and method3 throws an
exception, as shown in Figure 12.3. Consider the following scenario:
• ■ If the exception type is Exception3, it is caught by the catch block
for handling exception ex3 in method2. statement5 is skipped and
statement6 is executed.
• ■ If the exception type is Exception2, method2 is aborted, the control
is returned to method1, and the exception is caught by the catch
block for handling exception ex2 in method1. statement3 is skipped
and statement4 is executed.
Catching Exceptions
• ■If the exception type is Exception1, method1 is aborted, the control
is returned to the main method, and the exception is caught by the
catch block for handling exception ex1 in the main method.
statement1 is skipped and statement2 is executed.
• ■ If the exception type is not caught in method2, method1, or main,
the program
• terminates and statement1 and statement2 are not executed.
public class Main {
In methodA
public static void main(String[] args) {
In methodB
try {
Caught exception in main: / by zero
methodA();
} catch (Exception e) {
=== Code Execution Successful ===
System.out.println("Caught exception in main: " + e.getMessage());
}
}
public static void methodA() throws Exception {
System.out.println("In methodA");
methodB();
System.out.println("This line in methodA will not be executed if exception is thrown.");
}
public static void methodB() throws Exception {
System.out.println("In methodB");
int res= 5/0;
System.out.println("This line in methodB will not be executed if exception is thrown.");
}
}
Catching Exceptions
• The order in which exceptions are specified in catch blocks is
important. A compile error will result if a catch block for a superclass
type appears before a catch block for a subclass type. For example,
the ordering in (a) below is erroneous, because RuntimeException is a
subclass of Exception. The correct ordering should be as shown in (b).
Catching Exceptions
• Java forces you to deal with checked exceptions. If a method declares
a checked exception (i.e., an exception other than Error or
RuntimeException), you must invoke it in a try-catch block or declare
to throw the exception in the calling method. For example, suppose
method p1 invokes method p2 and p2 may throw a checked
exception (e.g., IOException); you have to write the code as shown in
(a) or (b) below.
void p2() throws IOException {
if (a file does not exist) {
throw new IOException("File does not exist");
}

...
}
Getting Information from Exceptions
• An exception object contains valuable information about the exception.
You may use the following instance methods in the java.lang.Throwable
class to get information regarding the exception, as shown in Figure 12.4.
The printStackTrace() method prints stack trace
public class Main {
public static void main(String[] args) {
try {
System.out.println(sum(new int[] {1, 2, 3, 4, 5}));
}
catch (Exception ex) {
ex.printStackTrace();
System.out.println("\n" + ex.getMessage());
System.out.println("\n" + ex.toString());
System.out.println("\nTrace Info Obtained from getStackTrace");
StackTraceElement[] traceElements = ex.getStackTrace();
for (int i = 0; i < traceElements.length; i++) {
System.out.print("method " + traceElements[i].getMethodName());
System.out.print("(" + traceElements[i].getClassName() + ":");
System.out.println(traceElements[i].getLineNumber() + ")");
}
}
}
private static int sum(int[] list) {
int result = 0;
for (int i = 0; i <= list.length; i++)
result += list[i];
return result;
}}
java.lang.ArrayIndexOutOfBoundsException: Index 5 out of bounds for length 5
at Main.sum(Main.java:23) printStackTrace()printStackTrace()
at Main.main(Main.java:4)

Index 5 out of bounds for length 5 getMessage()

java.lang.ArrayIndexOutOfBoundsException: Index 5 out of bounds for length 5 toString()

Trace Info Obtained from getStackTrace Using


method sum(Main:23) getStackTrace()
method main(Main:4)
Example: Declaring, Throwing, and Catching
Exceptions
• Objective: This example demonstrates declaring, throwing, and
catching exceptions by modifying the setRadius method in the Circle
class defined in Chapter 9. The new setRadius method throws an
exception if radius is negative.
CircleWithException

CircleWithException
TestCircleWithException

TestCircleWithException
public class CircleWithException {
/** The radius of the circle */
private double radius; public void setRadius(double newRadius)
/** The number of the objects created */ throws IllegalArgumentException {
private static int numberOfObjects = 0; if (newRadius >= 0)
/** Construct a circle with radius 1 */ radius = newRadius;
public CircleWithException() { else
this(1.0); throw new IllegalArgumentException(
} "Radius cannot be negative");
/** Construct a circle with a specified radius */ }
public CircleWithException(double newRadius) { /** Return numberOfObjects */
setRadius(newRadius); public static int getNumberOfObjects() {
numberOfObjects++; return numberOfObjects;
} }
/** Return radius */ /** Return the area of this circle */
public double getRadius() { public double findArea() {
return radius; return radius * radius * 3.14159;
} }
}
public class Main {

public static void main(String[] args) {


try {
CircleWithException c1 = new CircleWithException(5);
CircleWithException c2 = new CircleWithException(-5);
CircleWithException c3 = new CircleWithException(0);
}
catch (IllegalArgumentException ex) {
System.out.println(ex);
}

System.out.println("Number of objects created: " +


CircleWithException.getNumberOfObjects());
}
}
java.lang.IllegalArgumentException: Radius cannot be negative
Number of objects created: 1
The finally Clause
try {
statements;
}
catch(TheException ex) {
handling ex;
}
finally {
finalStatements;
}
The finally Clause
• The code in the finally block is executed under all situations, regardless of
whether an exception occurs in the try block or is caught. Consider three
possible cases:
• 1. If no exception arises in the try block, finalStatements is executed and
the next statement after the try statement is executed.
• 2. If a statement causes an exception in the try block that is caught in a
catch block, the rest of the statements in the try block are skipped, the
catch block is executed, and the finally clause is executed. The next
statement after the try statement is executed.
• 3. If one of the statements causes an exception that is not caught in any
catch block, the other statements in the try block are skipped, the finally
clause is executed, and the exception is passed to the caller of this method.
Rethrowing Exceptions
Java allows an exception handler to rethrow the exception if the
handler cannot process the exception, or simply wants to let its caller
be notified of the exception.
try {
statements;
}
catch(TheException ex) {
perform operations before exits;
throw ex;
}
public class RethrowExample {
//output
public static void main(String[] args) {
Caught in process: Error occurred in riskyOperation
try {
Caught in main: Error occurred in riskyOperation
process();
} catch (Exception e) {
System.out.println("Caught in main: " + e.getMessage());
}
}
public static void process() throws Exception {
try {
riskyOperation();
} catch (Exception e) {
System.out.println("Caught in process: " + e.getMessage());
// Rethrow the exception Explanation:
throw e; 1.riskyOperation throws an exception.
} 2.The process method catches it, logs the error,
} and rethrows the same exception.
public static void riskyOperation() throws Exception { 3.The main method catches the rethrown
throw new Exception("Error occurred in riskyOperation"); exception and handles it.
}
}
animation

Trace a Program Execution


Suppose no
exceptions in the
statements
try {
statements;
}
catch(TheException ex) {
handling ex;
}
finally {
finalStatements;
}

Next statement;

Liang, Introduction to Java Programming and Data Structures, Twelfth Edition, (c) 2020 Pearson Education, Inc. All rights
reserved.
54
animation

Trace a Program Execution


The final block is
try { always executed
statements;
}
catch(TheException ex) {
handling ex;
}
finally {
finalStatements;
}

Next statement;

Liang, Introduction to Java Programming and Data Structures, Twelfth Edition, (c) 2020 Pearson Education, Inc. All rights
reserved.
55
animation

Trace a Program Execution


Next statement in the
try { method is executed
statements;
}
catch(TheException ex) {
handling ex;
}
finally {
finalStatements;
}

Next statement;

Liang, Introduction to Java Programming and Data Structures, Twelfth Edition, (c) 2020 Pearson Education, Inc. All rights
reserved.
56
animation

Trace a Program Execution


try { Suppose an exception
statement1; of type Exception1 is
statement2; thrown in statement2
statement3;
}
catch(Exception1 ex) {
handling ex;
}
finally {
finalStatements;
}

Next statement;

Liang, Introduction to Java Programming and Data Structures, Twelfth Edition, (c) 2020 Pearson Education, Inc. All rights
reserved.
57
animation

Trace a Program Execution


try { The exception is
statement1; handled.
statement2;
statement3;
}
catch(Exception1 ex) {
handling ex;
}
finally {
finalStatements;
}

Next statement;

Liang, Introduction to Java Programming and Data Structures, Twelfth Edition, (c) 2020 Pearson Education, Inc. All rights
reserved.
58
animation

Trace a Program Execution


try { The final block is
statement1; always executed.
statement2;
statement3;
}
catch(Exception1 ex) {
handling ex;
}
finally {
finalStatements;
}

Next statement;

Liang, Introduction to Java Programming and Data Structures, Twelfth Edition, (c) 2020 Pearson Education, Inc. All rights
reserved.
59
animation

Trace a Program Execution


try { The next statement in
statement1; the method is now
statement2; executed.
statement3;
}
catch(Exception1 ex) {
handling ex;
}
finally {
finalStatements;
}

Next statement;

Liang, Introduction to Java Programming and Data Structures, Twelfth Edition, (c) 2020 Pearson Education, Inc. All rights
reserved.
60
animation

Trace a Program Execution


try {
statement1; statement2 throws an
statement2; exception of type
statement3; Exception2.
}
catch(Exception1 ex) {
handling ex;
}
catch(Exception2 ex) {
handling ex;
throw ex;
}
finally {
finalStatements;
}

Next statement;

Liang, Introduction to Java Programming and Data Structures, Twelfth Edition, (c) 2020 Pearson Education, Inc. All rights
reserved.
61
animation

Trace a Program Execution


try {
statement1; Handling exception
statement2;
statement3;
}
catch(Exception1 ex) {
handling ex;
}
catch(Exception2 ex) {
handling ex;
throw ex;
}
finally {
finalStatements;
}

Next statement;

Liang, Introduction to Java Programming and Data Structures, Twelfth Edition, (c) 2020 Pearson Education, Inc. All rights
reserved.
62
animation

Trace a Program Execution


try {
statement1; Execute the final block
statement2;
statement3;
}
catch(Exception1 ex) {
handling ex;
}
catch(Exception2 ex) {
handling ex;
throw ex;
}
finally {
finalStatements;
}

Next statement;

Liang, Introduction to Java Programming and Data Structures, Twelfth Edition, (c) 2020 Pearson Education, Inc. All rights
reserved.
63
animation

Trace a Program Execution


try {
statement1; Rethrow the exception
statement2; and control is
statement3; transferred to the caller
}
catch(Exception1 ex) {
handling ex;
}
catch(Exception2 ex) {
handling ex;
throw ex;
}
finally {
finalStatements;
}

Next statement;

Liang, Introduction to Java Programming and Data Structures, Twelfth Edition, (c) 2020 Pearson Education, Inc. All rights
reserved.
64
When Using Exceptions
• Exception handling separates error-handling code from normal
programming tasks, thus making programs easier to read and to
modify.
• Be aware, however, that exception handling usually requires more
time and resources because it requires instantiating a new exception
object, rolling back the call stack, and propagating the errors to the
calling methods.
When to Throw Exceptions
• An exception occurs in a method. If you want the exception to be
processed by its caller, you should create an exception object and
throw it. If you can handle the exception in the method where it
occurs, there is no need to throw it.
When to Use Exceptions
• When should you use the try-catch block in the code? You should use it to
deal with unexpected error conditions. Do not use it to deal with simple,
expected situations. For example, the following code
try {
System.out.println(refVar.toString());
}
catch (NullPointerException ex) {
System.out.println("refVar is null");
}
When to Use Exceptions
• is better to be replaced by
if (refVar != null)
System.out.println(refVar.toString());
else
System.out.println("refVar is null");
Defining Custom Exception Classes
• Use the exception classes in the API whenever possible.
• Define custom exception classes if the predefined classes are not
sufficient.
• Define custom exception classes by extending Exception or a subclass
of Exception.
Custom Exception Class Example
• In Listing 13.8, the setRadius method throws an exception if the
radius is negative. Suppose you wish to pass the radius to the handler,
you have to create a custom exception class.

InvalidRadiusException

InvalidRadiusException
CircleWithRadiusException

CircleWithRadiusException
TestCircleWithRadiusException

TestCircleWithRadiusException
public class InvalidRadiusException extends Exception {
private double radius;
public InvalidRadiusException(double radius) {
super("Invalid radius " + radius);
this.radius = radius;
}
public double getRadius() {
return radius;
}
}
public class CircleWithRadiusException {
private double radius;
private static int numberOfObjects = 0; public void setRadius(double newRadius)
throws InvalidRadiusException {
public CircleWithRadiusException() {
if (newRadius >= 0)
this(1.0); radius = newRadius;
} else
public CircleWithRadiusException(double newRadius) { throw new InvalidRadiusException(newRadius);
try { }
setRadius(newRadius);
numberOfObjects++; /** Return numberOfObjects */
} public static int getNumberOfObjects() {
catch (InvalidRadiusException ex) { return numberOfObjects;
}
ex.printStackTrace();
} /** Return the area of this circle */
} public double findArea() {
public double getRadius() { return radius * radius * 3.14159;
return radius; }
} }
public class Main {
public static void main(String[] args) {
try {
CircleWithRadiusException c1 = new CircleWithRadiusException(5);
c1.setRadius(-5);
CircleWithRadiusException c3 = new CircleWithRadiusException(0);
}
catch (InvalidRadiusException ex) {
System.out.println(ex);
}

System.out.println("Number of objects created: " +


CircleWithRadiusException.getNumberOfObjects());
}
}

InvalidRadiusException: Invalid radius -5.0


Number of objects created: 1
Try-with-resources Feature in Java

• In Java, the Try-with-resources statement is a try statement that


declares one or more resources in it. A resource is an object that must
be closed once your program is done using it. For example, a File
resource or a Socket connection resource. The try-with-resources
statement ensures that each resource is closed at the end of the
statement execution. If we don’t close the resources, it may
constitute a resource leak and also the program could exhaust the
resources available to it.
• By this, now we don’t need to add an extra finally block for just
passing the closing statements of the resources. The resources will be
closed as soon as the try-catch block is executed.
Syntax: Try-with-resources

try(declare resources here) {


// use resources
}
catch(FileNotFoundException e) {
// exception handling
}
Output:
Resource are closed and message has been
written into the gfgtextfile.txt

import java.io.*;
class GFG {
public static void main(String[] args)
{
// Try block to check for exceptions
try (FileOutputStream fos = new FileOutputStream("gfgtextfile.txt")) {
String text = "Hello World. This is my java program";
byte arr[] = text.getBytes();
fos.write(arr);
}
catch (Exception e) {
System.out.println(e);
}
System.out.println(
"Resource are closed and message has been written into the
gfgtextfile.txt");
}
}
import java.io.*;
class GFG {
public static void main(String[] args)
{
try (FileOutputStream fos = new FileOutputStream("outputfile.txt");
BufferedReader br =
new BufferedReader( new FileReader("gfgtextfile.txt"))
)
{
while ((text = br.readLine()) != null) {
byte arr[] = text.getBytes();
}

System.out.println( "File content copied to another one.");


}
catch (Exception e) {
System.out.println(e);
}
System.out.println(
"Resource are closed and message has been written into the
gfgtextfile.txt");
}
}
Output:
File content copied to another one. Resource
are closed and message has been written into
the gfgtextfile.txt
Thanks
References
• Introduction to Java Programming and Data Structures, Comprehensive Version 12th
Edition, by Y. Liang (Author), Y. Daniel Liang
• This slides based on slides provided by Introduction to Java Programming and Data Structures,
Comprehensive Version 12th Edition, by Y. Liang (Author), Y. Daniel Liang
• © Copyright 1992-2012 by Pearson Education, Inc. All Rights Reserved.

• php - What is the advantage of using try {} catch {} versus if {} else {} - Stack Overflow
Advanced Programming Language
Dr. Ahmed Hesham Mostafa
Dr. Mohamed Atia
Lecture 7 – IO Files
Files and Streams

• Java views each file as a sequential stream of bytes (Fig. 17.1).


• Every operating system provides a mechanism to determine the end of
a file, such as an end-of-file marker or a count of the total bytes in the
file that is recorded in a system-maintained administrative data
structure.
• A Java program simply receives an indication from the operating
system when it reaches the end of the stream
Files and Streams (cont.)

• File streams can be used to input and output data as bytes or characters.
• Streams that input and output bytes are known as byte-based streams,
representing data in its binary format.
• Streams that input and output characters are known as character-based
streams, representing data as a sequence of characters.
• Files that are created using byte-based streams are referred to as binary files.
• Files created using character-based streams are referred to as text files. Text
files can be read by text editors.
• Binary files are read by programs that understand the specific content of the
file and the ordering of that content.
Files and Streams (cont.)

• A Java program opens a file by creating an object and associating a stream of


bytes or characters with it.
▪ Can also associate streams with different devices.
• Java creates three stream objects when a program begins executing
▪ System.in (the standard input stream object) normally inputs bytes from the keyboard
▪ System.out (the standard output stream object) normally outputs character data to the
screen
▪ System.err (the standard error stream object) normally outputs character-based error
messages to the screen.
Files and Streams (cont.)

• Java programs perform file processing by using classes from package


java.io.
• Includes definitions for stream classes
▪ FileInputStream (for byte-based input from a file)
▪ FileOutputStream (for byte-based output to a file)
▪ FileReader (for character-based input from a file)
▪ FileWriter (for character-based output to a file)
• You open a file by creating an object of one these stream classes. The
object’s constructor opens the file.
Files and Streams (cont.)

• Can perform input and output of objects or variables of primitive data types
without having to worry about the details of converting such values to byte
format.
• To perform such input and output, objects of classes ObjectInputStream and
ObjectOutputStream can be used together with the byte-based file stream
classes FileInputStream and FileOutputStream.
• The complete hierarchy of classes in package java.io can be viewed in the
online documentation at
• http://download.oracle.com/javase/6/docs/api/java/io/packag
e-tree.html
Files and Streams (cont.)

• Class File provides information about files and directories.


• Character-based input and output can be performed with classes
Scanner and Formatter.
▪ Class Scanner is used extensively to input data from the keyboard. This
class can also read data from a file.
▪ Class Formatter enables formatted data to be output to any text-based
stream in a manner similar to method System.out.printf.
Class File

• Class File provides four constructors.


• The one with a String argument specifies the name of a file or
directory to associate with the File object.
▪ The name can contain path information as well as a file or directory name.
▪ A file or directory’s path specifies its location on disk.
▪ An absolute path contains all the directories, starting with the root directory,
that lead to a specific file or directory.
▪ A relative path normally starts from the directory in which the application
began executing and is therefore “relative” to the current directory.
Class File (cont.)

• The constructor with two String arguments specifies an absolute or relative


path and the file or directory to associate with the File object.
• The constructor with File and String arguments uses an existing File
object that specifies the parent directory of the file or directory specified by the
String argument.
• Figure 17.2 lists some common File methods. The
• http://download.oracle.com/javase/6/docs/api/java/io/Fi
le.html
10
Problem: Explore File Properties
• Objective: Write a program that demonstrates how to create files in a
platform-independent way and use the methods in the File class to
obtain their properties. The following figures show a sample run of
the program on Windows and on Unix.
TestFileClass

TestFileClass
import java.io.File;
public class Main {
public static void main(String[] args) {
File file = new File("C:\\Users\\ahmed\\Desktop\\a.txt");
System.out.println("Does it exist? " + file.exists()); Does it exist? true
System.out.println("The file has " + file.length() + " bytes"); The file has 373 bytes
System.out.println("Can it be read? " + file.canRead()); Can it be read? true
System.out.println("Can it be written? " + file.canWrite()); Can it be written? true
System.out.println("Is it a directory? " + file.isDirectory()); Is it a directory? false
System.out.println("Is it a file? " + file.isFile()); Is it a file? true
System.out.println("Is it absolute? " + file.isAbsolute()); Is it absolute? true
System.out.println("Is it hidden? " + file.isHidden()); Is it hidden? false
System.out.println("Absolute path is " + Absolute path is C:\Users\ahmed\Desktop\a.txt
file.getAbsolutePath()); Last modified on Thu Dec 08 23:56:05 EET 2022
System.out.println("Last modified on " +
new java.util.Date(file.lastModified()));
}
}
Text I/O
• A File object encapsulates the properties of a file or a path, but does
not contain the methods for reading/writing data from/to a file.
• In order to perform I/O, you need to create objects using appropriate
Java I/O classes.
• The objects contain the methods for reading/writing data from/to a
file.
• This section introduces how to read/write strings and numeric values
from/to a text file using the Scanner and PrintWriter classes.
Writing Data Using PrintWriter
java.io.PrintWriter
+PrintWriter(filename: String) Creates a PrintWriter for the specified file.
+print(s: String): void Writes a string.
+print(c: char): void Writes a character.
+print(cArray: char[]): void Writes an array of character.
+print(i: int): void Writes an int value.
WriteData

+print(l: long): void Writes a long value.


WriteData
+print(f: float): void Writes a float value.
+print(d: double): void Writes a double value.
+print(b: boolean): void Writes a boolean value.
Also contains the overloaded A println method acts like a print method; additionally it
println methods. prints a line separator. The line separator string is defined
Also contains the overloaded by the system. It is \r\n on Windows and \n on Unix.
printf methods. The printf method was introduced in §4.6, “Formatting
Console Output and Strings.”
.
import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
public class Main {
public static void main(String[] args) {
File file = new File("scores.txt");
if (file.exists()) {
System.out.println("File already exists");
System.exit(0);
}
PrintWriter output = null;
try {
output = new PrintWriter(file);
// Write formatted output to the file
output.print("John T Smith ");
output.println(90);
output.print("Eric K Jones ");
output.println(85);
// Close the file
output.close();
} catch (FileNotFoundException e) {
throw new (e);
} RuntimeException
}}
Reading Data Using Scanner
java.util.Scanner
+Scanner(source: File) Creates a Scanner object to read data from the specified file.
+Scanner(source: String) Creates a Scanner object to read data from the specified string.
+close() Closes this scanner.
+hasNext(): boolean Returns true if this scanner has another token in its input.
+next(): String Returns next token as a string.
+nextByte(): byte Returns next token as a byte.
+nextShort(): short Returns next token as a short. ReadData

+nextInt(): int Returns next token as an int. ReadData


+nextLong(): long Returns next token as a long.
+nextFloat(): float Returns next token as a float.
+nextDouble(): double Returns next token as a double.
+useDelimiter(pattern: String): Sets this scanner’s delimiting pattern.
Scanner
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class Main {
public static void main(String[] args) throws FileNotFoundException {
File file = new File("scores.txt");
Scanner input = new Scanner(file);
while (input.hasNext()) {
String firstName = input.next();
John T Smith 90
String mi = input.next(); Eric K Jones 85
String lastName = input.next();
int score = input.nextInt();
System.out.println(firstName + " " + mi + " " + lastName + " " + score);
}
input.close();
}
}
Case Study(CRUD Operations)
• CRUD refers to the four basic operations a software
application should be able to perform – Create, Read, Update,
and Delete
• Create mini system to add, delete , update , search , list
,student to files
• There admin class that control the system
import java.util.Scanner;
public class Main { Main Class
public static void main(String[] args) {
String Fname, Lname;
int id, oldID, age, level;
double GPA;
Admin admin=new Admin();
Scanner in=new Scanner(System.in);
int choice;
while(true) {
System.out.println("1- Add student" + "\n" +
"2- Delete Student" + "\n" +
"3- Update Student" + "\n" +
"4- Search Student" + "\n" +
"5- List all Students" + "\n" +
"6- Exit" + "\n");
System.out.println("Enter your Choice");
choice=in.nextInt();
switch(choice){
case 1:
System.out.println("Enter Student Info ... "); Main Class
System.out.print("Student First Name : ");
Fname = in.next();
System.out.print("Student Last Name : ");
Lname = in.next();
System.out.print("Student ID : ");
id = in.nextInt();
System.out.print("Student Age : ");
age = in.nextInt();
System.out.print("Student Level : ");
level = in.nextInt();
System.out.print("Student GPA : ");
GPA = in.nextDouble();
admin.addNewStudent(id, Fname, Lname, age, level, GPA);
break;
case 2:
System.out.print("\nDelete Student info ...!\nEnter Student ID : ");
id = in.nextInt();
admin.deleteStudent(id);
break;
case 3:
System.out.print("\nUpdate Student info ...!\nEnter Student OldID : ");
Main Class
oldID = in.nextInt();
System.out.println("\nEnter Student New Info ... ");
System.out.print("Student First Name : ");
Fname = in.next();
System.out.print("Student Last Name : ");
Lname = in.next();
System.out.print("Student ID : ");
id = in.nextInt();
System.out.print("Student Age : ");
age = in.nextInt();
System.out.print("Student Level : ");
level = in.nextInt();
System.out.print("Student GPA : ");
GPA = in.nextDouble();
Student x = new Student(id, Fname, Lname, age, level, GPA);
admin.updateStudent(oldID, x);
break;
case 4: Main Class
System.out.print("\nSearch for Student ...!\nEnter Student ID : ");
id = in.nextInt();
admin.searchForStudent(id);
break;

case 5:
admin.displayStudents();
break;
case 6:
System.exit(0);

}
}
public class Admin { public void addNewStudent(int id, String fname, String lname, int age, int level, double GPA) {
String user; pass, fname, lname; Student x = new Student( id, fname, lname, age, level, GPA);
int id, age; if (x.addStudent()) {
public Admin() { } System.out.println(x.toString() + "Added Successfully ... !");
public Admin(int id, String fname, String lname, int age) { } else {
this.id = id;
this.fname = fname; }
System.out.println("Failed to insert ... !");
Admin Class
this.lname = lname; }
this.age = age; public void displayStudents() {
} Student x = new Student();
public int getId() { System.out.println(x.displayAllStudents());
return id; }
} public void searchForStudent(int id) {
public void setId(int id) { Student x = new Student();
this.id = id; System.out.println(x.searchStudent(id));
} }
public String getFname() { public void updateStudent(int oldID, Student newStudentValues) {
return fname; Student x = new Student();
} x.updateStudent(oldID, newStudentValues);
public void setFname(String fname) { System.out.println("Updated Successfully ... !");
this.fname = fname; }
} public void deleteStudent(int Id) {
public String getLname() { Student x = new Student();
return lname; x.deleteStudent(Id);
} System.out.println("deleted Successfully ... !");
public void setLname(String lname) { }
this.lname = lname; }
}
public int getAge() {
return age; }
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList; FileManger Class
import java.util.Scanner;
public class FileManger {
public boolean write(String Query, String FilePath, boolean appendType) {
PrintWriter writter = null;
try {
System.out.print("\nwritting in ! " + FilePath);
writter = new PrintWriter(new FileWriter(new File(FilePath), appendType));
writter.println(Query);
System.out.println(" ... Done ! ");
return true;
} catch (IOException e) {
System.out.println(e);
Go To binary Version

Go To binary Version
} finally {
writter.close();
}
return false;
}
public ArrayList<Object> read(String FilePath) {
Scanner Reader = null;
try {
System.out.println("Reading ! From " + FilePath);
Reader = new Scanner(new File(FilePath));
} catch (FileNotFoundException e) {
System.out.println(e+" Cann't find file");
FileManger Class
}
ArrayList<Student> Students = new ArrayList<Student>();
Student x;
while (Reader.hasNext()) {
x = new Student();
String Line = Reader.nextLine();
String[] seprated = Line.split(",");
x.setId(Integer.parseInt(seprated[0]));
x.setFname(seprated[1]);
x.setLname(seprated[2]);
x.setAge(Integer.parseInt(seprated[3]));
x.setLevel(Integer.parseInt(seprated[4]));
x.setGPA(Double.parseDouble(seprated[5]));
Students.add(x);
}
return (ArrayList<Object>) (Object) Students;
}
}
import java.util.ArrayList;
public class Student {
private int level;
private int age; public void setLname(String lname) {
private double GPA; this.lname = lname;
private String fname; }
private String lname; public void setLevel(int level) {
private int id; this.level = level;
private final String studentFileName = "Students.txt"; }
public static ArrayList<Student> Students = new ArrayList<Student>();
private FileManger fileManger=new FileManger(); public int getAge() {
Student Class
public Student(){} return age;
public Student(int id, String fname, String lname, int age, int level, double GPA) { }
this.id=id;
this.fname=fname; public void setAge(int age) {
this.lname=lname; this.age = age;
this.age=age; }
this.level = level;
this.GPA = GPA; public void setGPA(double GPA) {
} this.GPA = GPA;
public int getId() { }
return id;
} public int getLevel() {
public void setId(int id) { return this.level;
this.id = id; }
}
public String getFname() { public double getGPA() {
return fname; return this.GPA;
} }
public void setFname(String fname) {
this.fname = fname;
}
public String getLname() {
return lname;
}
public boolean addStudent() {
if (fileManger.write(getStudentData(), studentFileName, true)) {
return true;
} else {
return false; Student Class
}
}

private String getStudentData() {


return this.id + "," + this.fname + "," + this.lname + "," + this.age + "," + this.level + "," + this.GPA;
}

private void commitToFile() {


fileManger.write(Students.get(0).getStudentData(), studentFileName, false);
for (int i = 1; i < Students.size(); i++) {
fileManger.write(Students.get(i).getStudentData(), studentFileName, true);
} Go To binary Version

Go To binary Version
}
private int getStudentIndex(int id){
for (int i = 0; i < Students.size(); i++)
if(Students.get(i).getId() == id)
return i;
Student Class
return -1;
}

private void loadFromFile() {


Students = (ArrayList<Student>) (Object) fileManger.read(studentFileName);
}

public String displayAllStudents() {


loadFromFile();
String S = "\nAll Student Data:\n";
for (Student x : Students) {
S = S + x.toString();
}
return S;
}
public String searchStudent(int id){
loadFromFile();
int index = getStudentIndex(id);
if(index != -1)
return "\nFound ...!" + Students.get(index).toString();
else
return "\nNot Found ...!";
Student Class
}
public void updateStudent(int oldID, Student x){
loadFromFile();
int index = getStudentIndex(oldID);
Students.set(index, x);
commitToFile();
}
public void deleteStudent(int id){
loadFromFile();
int index = getStudentIndex(id);
Students.remove(index);
commitToFile();
}
@Override
public String toString() {
return "\nI'm Eng : " + fname + " " + lname + "\n" + "ID : " + id + " Age : " + age + "\n" + "Level : " + level + " GPA : " + GPA+ "\n";
}
}
How is I/O Handled in Java?
• A File object encapsulates the properties of a file or a path, but does
not contain the methods for reading/writing data from/to a file. In
order to perform I/O, you need to create objects using appropriate
Java I/O classes.
Scanner input = new Scanner(new File("temp.txt"));
System.out.println(input.nextLine());

Program
Input stream
Input object
created from an 01011…1001 File
input class

PrintWriter output = new PrintWriter("temp.txt"); Output object


created from an 11001…1011
File
output class
output.println("Java 101"); Output stream

output.close();
Text File vs. Binary File
• Data stored in a text file are represented in human-readable form.
• Data stored in a binary file are represented in binary form. You cannot read
binary files. Binary files are designed to be read by programs.
• For example, the Java source programs are stored in text files and can be
read by a text editor, but the Java classes are stored in binary files and are
read by the JVM. The advantage of binary files is that they are more
efficient to process than text files.
• Although it is not technically precise and correct, you can imagine that a
text file consists of a sequence of characters and a binary file consists of a
sequence of bits. For example, the decimal integer 199 is stored as the
sequence of three characters: '1', '9', '9' in a text file and the same integer
is stored as a byte-type value C7 in a binary file, because decimal 199
equals to hex C7.
Binary I/O
• Text I/O requires encoding and decoding.
• The JVM converts a Unicode to a file specific encoding when writing a
character and coverts a file specific encoding to a Unicode when
reading a character.
• Binary I/O does not require conversions. When you write a byte to a
file, the original byte is copied into the file. When you read a byte
from a file, the exact byte in the file is returned.
Binary I/O Classes
InputStream
The value returned is a byte as an int type.
java.io.InputStream

+read(): int Reads the next byte of data from the input stream. The value byte is returned as
an int value in the range 0 to 255. If no byte is available because the end of
the stream has been reached, the value –1 is returned.
+read(b: byte[]): int Reads up to b.length bytes into array b from the input stream and returns the
actual number of bytes read. Returns -1 at the end of the stream.
+read(b: byte[], off: int, Reads bytes from the input stream and stores into b[off], b[off+1], …,
len: int): int b[off+len-1]. The actual number of bytes read is returned. Returns -1 at the
end of the stream.
+available(): int Returns the number of bytes that can be read from the input stream.
+close(): void Closes this input stream and releases any system resources associated with the
stream.
+skip(n: long): long Skips over and discards n bytes of data from this input stream. The actual
number of bytes skipped is returned.
+markSupported(): boolean Tests if this input stream supports the mark and reset methods.
+mark(readlimit: int): void Marks the current position in this input stream.
+reset(): void Repositions this stream to the position at the time the mark method was last
called on this input stream.
35
OutputStream

The value is a byte as an int type.

java.io.OutputStream

+write(int b): void Writes the specified byte to this output stream. The parameter b is an int value.
(byte)b is written to the output stream.
+write(b: byte[]): void Writes all the bytes in array b to the output stream.
+write(b: byte[], off: int, Writes b[off], b[off+1], …, b[off+len-1] into the output stream.
len: int): void
+close(): void Closes this output stream and releases any system resources associated with the
stream.
+flush(): void Flushes this output stream and forces any buffered output bytes to be written out.

36
FileInputStream/FileOutputStream
FileInputStream
DataInputStream
InputStream FilterInputStream
BufferedInputStream
ObjectInputStream
Object
FileOutputStream BufferedOutputStream

OutputStream FilterOutputStream DataOutputStream

ObjectOutputStream PrintStream

FileInputStream/FileOutputStream associates a binary input/output stream


with an external file. All the methods in FileInputStream/FileOuptputStream
are inherited from its superclasses.
FileInputStream
To construct a FileInputStream, use the following constructors:
public FileInputStream(String filename)
public FileInputStream(File file)

A java.io.FileNotFoundException would occur if you attempt to create a


FileInputStream with a nonexistent file.
FileOutputStream
To construct a FileOutputStream, use the following constructors:

public FileOutputStream(String filename)


public FileOutputStream(File file) TestFileStream
Run

public FileOutputStream(String filename, boolean append) TestFileStream Run


public FileOutputStream(File file, boolean append)

If the file does not exist, a new file would be created. If the file already exists, the
first two constructors would delete the current contents in the file. To retain the
current content and append new data into the file, use the last two constructors by
passing true to the append parameter.
import java.io.*;
public class TestFileStream {
public static void main(String[] args) throws IOException {
try (
// Create an output stream to the file
FileOutputStream output = new
FileOutputStream("temp.dat");
){
// Output values to the file
for (int i = 1; i <= 10; i++)
output.write(i);
}
try (
// Create an input stream for the file
FileInputStream input = new FileInputStream("temp.dat");
){
// Read values from the file
int value;
while ((value = input.read()) != -1)
System.out.print(value + " ");
}
}
}
FilterInputStream/FilterOutputStream
FileInputStream
DataInputStream
InputStream FilterInputStream
BufferedInputStream
ObjectInputStream
Object
FileOutputStream BufferedOutputStream

OutputStream FilterOutputStream DataOutputStream

ObjectOutputStream PrintStream

Filter streams are streams that filter bytes for some purpose. The basic byte input
stream provides a read method that can only be used for reading bytes. If you want
to read integers, doubles, or strings, you need a filter class to wrap the byte input
stream. Using a filter class enables you to read integers, doubles, and strings instead
of bytes and characters. FilterInputStream and FilterOutputStream are the base
classes for filtering data. When you need to process primitive numeric types, use
DatInputStream and DataOutputStream to filter bytes.
41
DataInputStream/DataOutputStream
DataInputStream reads bytes from the stream
and converts them into appropriate primitive
type values or strings.

FileInputStream
DataInputStream
InputStream FilterInputStream
BufferedInputStream
ObjectInputStream
Object
FileOutputStream BufferedOutputStream

OutputStream FilterOutputStream DataOutputStream

ObjectOutputStream PrintStream

DataOutputStream converts primitive type values


or strings into bytes and output the bytes to the
stream.
42
DataInputStream
DataInputStream extends FilterInputStream and implements the
DataInput interface.

43
DataOutputStream
DataOutputStream extends FilterOutputStream and implements the
DataOutput interface.

44
What is UTF
• UTF in Java refers to Unicode Transformation Format, which is a
standard for encoding characters into a sequence of bytes. Java uses
UTF encoding for character representation, particularly UTF-8 and
Modified UTF-8, in its various classes and APIs.
• UTF-8:
• A variable-length encoding that represents every Unicode character.
• It uses 1 to 4 bytes per character.
• Java supports UTF-8 for reading and writing text files and network
communication.
• Widely used because of its backward compatibility with ASCII (characters in
the range 0-127 use one byte).
What is UTF
• Modified UTF-8:
• A variation of UTF-8 used internally in Java for serialization (e.g., in DataInput
and DataOutput streams).
• Differs from standard UTF-8 in two ways:It uses two bytes for null (\u0000)
instead of one.
• It encodes surrogate pairs directly as three bytes, unlike UTF-8, which
encodes them as six bytes.
• Used for efficiency in JVM-internal operations like .class file representation.
• Example: In a serialized form or when using Java DataInputStream and
DataOutputStream
Where is UTF Used in Java?
• String Encoding and Decoding:
• String.getBytes() and new String(byte[], Charset) support UTF encoding.
• File I/O:
• Classes like InputStreamReader, OutputStreamWriter, and Files use UTF-8 by
default in many cases.
• Serialization:
• Modified UTF-8 is used in DataInputStream and DataOutputStream
Why UTF-8? What is UTF-8?
• UTF-8 is a coding scheme that allows systems to operate with both ASCII
and Unicode efficiently. Most operating systems use ASCII. Java uses
Unicode.
1.Networking: Protocols and web services often rely on UTF-8 for text-based
communication
• The ASCII character set is a subset of the Unicode character set. Since most
applications need only the ASCII character set, it is a waste to represent an
8-bit ASCII character as a 16-bit Unicode character. The UTF-8 is an
alternative scheme that stores a character using 1, 2, or 3 bytes.
• ASCII values (less than 0x7F) are coded in one byte. Unicode values less
than 0x7FF are coded in two bytes. Other Unicode values are coded in
three bytes.
Characters and Strings in Binary I/O
• A Unicode consists of two bytes. The writeChar(char c) method writes the
Unicode of character c to the output. The writeChars(String s) method
writes the Unicode for each character in the string s to the output.
• The writeBytes(String s) method writes the lower byte of the Unicode for
each character in the string s to the output. The high byte of the Unicode is
discarded. The writeBytes method is suitable for strings that consist of
ASCII characters, since an ASCII code is stored only in the lower byte of a
Unicode. If a string consists of non-ASCII characters, you have to use the
writeChars method to write the string.
• The writeUTF(String s) method writes a string using the UTF coding
scheme. UTF is efficient for compressing a string with Unicode characters.
Using DataInputStream/DataOutputStream
Data streams are used as wrappers on existing input and output streams to filter
data in the original stream. They are created using the following constructors:
public DataInputStream(InputStream instream)
public DataOutputStream(OutputStream outstream)

The statements given below create data streams. The first statement creates an
input stream for file in.dat; the second statement creates an output stream for file
out.dat.
DataInputStream infile =
new DataInputStream(new FileInputStream("in.dat")); TestDataStream
Run

DataOutputStream outfile = TestDataStream Run


new DataOutputStream(new FileOutputStream("out.dat"));
import java.io.*;
public class TestDataStream {
public static void main(String[] args) throws IOException {
try ( // Create an output stream for file temp.dat
DataOutputStream output =
new DataOutputStream(new FileOutputStream("temp.dat"));
) {
// Write student test scores to the file
output.writeUTF("Liam");
output.writeDouble(85.5); Liam 85.5
output.writeUTF("Susan"); Susan 185.5
output.writeDouble(185.5); Chandra 105.25
output.writeUTF("Chandra");
output.writeDouble(105.25);
}
try ( // Create an input stream for file temp.dat
DataInputStream input =
new DataInputStream(new FileInputStream("temp.dat"));
) {
// Read student test scores from the file
System.out.println(input.readUTF() + " " + input.readDouble());
System.out.println(input.readUTF() + " " + input.readDouble());
System.out.println(input.readUTF() + " " + input.readDouble());
} }}
Concept of pipeline

DataInputStream FileInputStream External File

int, double, string … 01000110011 …

DataOutputStream FileOutputStream External File

int, double, string … 01000110011 …

52
Order and Format
• CAUTION: You have to read the data in the same order and same
format in which they are stored. For example, since names are
written in UTF-8 using writeUTF, you must read names using readUTF.
• Checking End of File
• TIP: If you keep reading data at the end of a stream, an EOFException
would occur. So how do you check the end of a file? You can use
input.available() to check it. input.available() == 0 indicates that it is
the end of a file.
BufferedInputStream/BufferedOutputStream
• can be used to speed up input and output by reducing the number of
disk reads and writes.
• Using BufferedInputStream, the whole block of data on the disk is
read into the buffer in the memory once.
• The individual data are then loaded to your program from the buffer.
• Using BufferedOutputStream, the individual data are first written to
the buffer in the memory. When the buffer is full, all data in the
buffer are written to the disk once
Constructing
BufferedInputStream/BufferedOutputStream
// Create a BufferedInputStream
public BufferedInputStream(InputStream in)
public BufferedInputStream(InputStream in, int bufferSize)

// Create a BufferedOutputStream
public BufferedOutputStream(OutputStream out)
public BufferedOutputStream(OutputStreamr out, int bufferSize)

55
BufferedInputStream/
BufferedOutputStream Using buffers to speed up I/O

FileInputStream
DataInputStream
InputStream FilterInputStream
BufferedInputStream
ObjectInputStream
Object
FileOutputStream BufferedOutputStream

OutputStream FilterOutputStream DataOutputStream

ObjectOutputStream PrintStream

BufferedInputStream/BufferedOutputStream does not contain new


methods. All the methods BufferedInputStream/BufferedOutputStream are
inherited from the InputStream/OutputStream classes.
56
Case Studies: Copy File
This case study develops a program that copies files. The user needs to
provide a source file and a target file as command-line arguments using
the following command:

java Copy source target

The program copies a source file to a target file and displays the number
of bytes in the file. If the source does not exist, tell the user the file is not
found. If the target file already exists, tell the user the file already exists.

Copy
Run

Copy Run

57
import java.io.*;
public class Copy {
/** Main method
@param args[0] for sourcefile
@param args[1] for target file */
public static void main(String[] args) throws IOException {
// Check command-line parameter usage
if (args.length != 2) {
System.out.println(
"Usage: java Copy sourceFile targetfile");
System.exit(1);
}
// Check if source file exists
File sourceFile = new File(args[0]);
if (!sourceFile.exists()) {
System.out.println("Source file " + args[0] + " does not exist");
System.exit(2);
}
// Check if target file exists
File targetFile = new File(args[1]);
if (targetFile.exists()) {
System.out.println("Target file " + args[1] + " already exists");
System.exit(3);
}
try (
// Create an input stream
BufferedInputStream input =
new BufferedInputStream(new FileInputStream(sourceFile));

// Create an output stream


BufferedOutputStream output =
new BufferedOutputStream(new FileOutputStream(targetFile));
) {
// Continuously read a byte from input and write it to output
// The input value of −1 signifies the end of a file.
int r, numberOfBytesCopied = 0;
while ((r = input.read()) != -1) {
output.write((byte)r);
numberOfBytesCopied++;
}

// Display the file size


System.out.println(numberOfBytesCopied + " bytes copied");
}
}
}
InputStream
The value returned is a byte as an int type.
java.io.InputStream

+read(): int Reads the next byte of data from the input stream. The value byte is returned as
an int value in the range 0 to 255. If no byte is available because the end of
the stream has been reached, the value –1 is returned.
+read(b: byte[]): int Reads up to b.length bytes into array b from the input stream and returns the
actual number of bytes read. Returns -1 at the end of the stream.
+read(b: byte[], off: int, Reads bytes from the input stream and stores into b[off], b[off+1], …,
len: int): int b[off+len-1]. The actual number of bytes read is returned. Returns -1 at the
end of the stream.
+available(): int Returns the number of bytes that can be read from the input stream.
+close(): void Closes this input stream and releases any system resources associated with the
stream.
+skip(n: long): long Skips over and discards n bytes of data from this input stream. The actual
number of bytes skipped is returned.
+markSupported(): boolean Tests if this input stream supports the mark and reset methods.
+mark(readlimit: int): void Marks the current position in this input stream.
+reset(): void Repositions this stream to the position at the time the mark method was last
called on this input stream.
60
Object I/O
DataInputStream/DataOutputStream enables you to perform I/O
for primitive type values and strings.
ObjectInputStream/ObjectOutputStream enables you to perform
I/O for objects in addition for primitive type values and strings.

FileInputStream
DataInputStream
InputStream FilterInputStream
BufferedInputStream
ObjectInputStream
Object
FileOutputStream BufferedOutputStream

OutputStream FilterOutputStream DataOutputStream

ObjectOutputStream PrintStream

61
ObjectInputStream

ObjectInputStream extends InputStream and


implements ObjectInput and ObjectStreamConstants.

java.io.InputStream ObjectStreamConstants

java.io.DataInput

java.io.ObjectInputStream java.io.ObjectInput

+ObjectInputStream(in: InputStream) +readObject(): Object Reads an object.

62
ObjectOutputStream

ObjectOutputStream extends OutputStream and


implements ObjectOutput and ObjectStreamConstants.

java.io.OutputStream ObjectStreamConstants

java.io.DataOutput

java.io.ObjectOutputStream java.io.ObjectOutput

+ObjectOutputStream(out: OutputStream) +writeObject(o: Object): void Writes an object.

63
Using Object Streams
You may wrap an ObjectInputStream/ObjectOutputStream on any
InputStream/OutputStream using the following constructors:

// Create an ObjectInputStream
public ObjectInputStream(InputStream in)

// Create an ObjectOutputStream
public ObjectOutputStream(OutputStream out)
TestObjectOutputStream
Run

TestObjectOutputStream Run
TestObjectInputStream
Run

TestObjectInputStream Run
import java.io.*;

public class TestObjectOutputStream {


public static void main(String[] args) throws IOException {
try ( // Create an output stream for file object.dat
ObjectOutputStream output =
new ObjectOutputStream(new FileOutputStream("object.dat"));
) {
// Write a string, double value, and object to the file
output.writeUTF("Jamal");
output.writeDouble(85.5);
output.writeObject(new java.util.Date());
}
}
}

12345
John Susan Kim
The Serializable Interface
• Not all objects can be written to an output stream. Objects that can
be written to an object stream is said to be serializable. A serializable
object is an instance of the java.io.Serializable interface. So the class
of a serializable object must implement Serializable.
• The Serializable interface is a marker interface. It has no methods, so
you don't need to add additional code in your class that implements
Serializable.
• Implementing this interface enables the Java serialization mechanism
to automate the process of storing the objects and arrays.
The Serializable Interface
• To appreciate this automation feature, consider what you otherwise need
to do in order to store an object. Suppose that you wish to store an
ArrayList object. To do this, you need to store all the elements in the list.
• Each element is an object that may contain other objects. As you can see,
this would be a very tedious process. Fortunately, you don’t have to go
through it manually.
• Java provides a built-in mechanism to automate the process of writing
objects. This process is referred as object serialization, which is
implemented in ObjectOutputStream. In contrast, the process of reading
objects is referred as object deserialization, which is implemented in
ObjectInputStream.
The Serializable Interface
• Many classes in the Java API implement Serializable. All the wrapper
classes for primitivetype values, java.math.BigInteger,
java.math.BigDecimal, java.lang.String, java.lang.StringBuilder,
java.lang.StringBuffer, java.util.Date, and java.util.ArrayList implement
java.io.Serializable.
• Attempting to store an object that does not support the Serializable
interface would cause a NotSerializableException.
• To make the object is Serializable , its class must
implement the Serializable interface
• Note that the in Java static field are not serialized and The values of the
object’s static variables are not stored..
The transient Keyword
• If an object is an instance of Serializable, but it contains non-
serializable instance data fields, can the object be serialized?
• The answer is no. To enable the object to be serialized, you can use
the transient keyword to mark these data fields to tell the JVM to
ignore these fields when writing the object to an object stream.
The transient Keyword
• When we de-serialized an object only, instance variables are saved
and will have same values after the process.
• Transient variables − The values of the transient variables are never
considered (they are excluded from the serialization process). i.e.
When we declare a variable transient, after de-serialization its value
will always be null, false, or, zero (default value).
• Static variables − The values of static variables will not be preserved
during the de-serialization process. In-fact static variables are also not
serialized but since these belongs to the class. After de-serialization
they get their current values from the class.
The transient Keyword, cont.
Consider the following class:

public class Foo implements java.io.Serializable {


private int v1;
private static double v2;
private transient A v3 = new A();
}
class A { } // A is not serializable

When an object of the Foo class is serialized, only variable v1 is serialized. Variable
v2 is not serialized because it is a static variable, and variable v3 is not serialized
because it is marked transient. If v3 were not marked transient, a
java.io.NotSerializableException would occur.
class Student implements Serializable{
public void setAge(int age) {
private String name;
this.age = age;
private transient int age;
}
private static int year = 2018;
public void setYear(int year) {
public Student(){
Student.year = year;
System.out.println("This is a constructor");
}
this.name = "Krishna";
}
this.age = 25;
}
public Student(String name, int age){
this.name = name;
this.age = age;
}
public void display() {
System.out.println("Name: "+this.name);
System.out.println("Age: "+this.age);
System.out.println("Year: "+Student.year);
}
public void setName(String name) {
this.name = name;
}
public class SerializeExample{
public static void main(String args[]) throws Exception{
Student std = new Student("Vani", 27);
//Serializing the object
FileOutputStream fos = new FileOutputStream("e:\student.ser");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(std);
oos.close(); fos.close();
//Printing the data before de-serialization
System.out.println("Values before de-serialization");
std.display();
std.setYear(2019); //Changing the static variable value
std.setName("Varada"); //Changing the instance variable value
std.setAge(19); //Changing the transient variable value
System.out.println("Object serialized.......");
//De-serializing the object
FileInputStream fis = new FileInputStream("e:\student.ser");
ObjectInputStream ois = new ObjectInputStream(fis);
Student deSerializedStd = (Student) ois.readObject();
System.out.println("Object de-serialized.......");
ois.close(); fis.close();
System.out.println("Values after de-serialization");
deSerializedStd.display();
}}
Output
After the process the value of the
• Values before de-serialization: instance variables will be same. The
• Name: Vani transient variables display the default
• Age: 27 values, and the static variables print
the new (current) value from the
• Year: 2018 class.
• Object serialized.......
• Object de-serialized.......
• Values after de-serialization:
• Name: Vani
• Age: 0
• Year: 2019
Serializing Arrays
• An array is serializable if all its elements are serializable. So an entire
array can be saved using writeObject into a file and later restored
using readObject. Here is an example that stores an array of five int
values and an array of three strings, and reads them back to display
on the console.
TestObjectStreamForArray
Run

TestObjectStreamForArray Run
import java.io.*;
public class TestObjectStreamForArray {
public static void main(String[] args)
throws ClassNotFoundException, IOException {
int[] numbers = {1, 2, 3, 4, 5};
String[] strings = {"John", "Susan", "Kim"};
try ( // Create an output stream for file array.dat
ObjectOutputStream output = new ObjectOutputStream(new
FileOutputStream("array.dat", true));
) {
// Write arrays to the object output stream
output.writeObject(numbers);
output.writeObject(strings);
}
try ( // Create an input stream for file array.dat
ObjectInputStream input =new ObjectInputStream(new FileInputStream("array.dat"));
) {
int[] newNumbers = (int[])(input.readObject());
String[] newStrings = (String[])(input.readObject());
// Display arrays
for (int i = 0; i < newNumbers.length; i++)
System.out.print(newNumbers[i] + " ");
System.out.println();
for (int i = 0; i < newStrings.length; i++)
System.out.print(newStrings[i] + " ");
}
}
}
Reimplementing The Case study in Slide 18 but
using Binary Objects
public class FileMangerBinary implements Serializable {
public boolean write(String FilePath, Object data) {
try { FileManger Class
System.out.print("\nwritting in ! " + FilePath);

ObjectOutputStream writter = new ObjectOutputStream(new


FileOutputStream(FilePath));

writter.writeObject(data);

System.out.println(" ... Done ! ");


writter.close();
return true;

} catch (IOException e) {
System.out.println("Can't write ...!\n" + e);
} Go To text Version

return false; Go To text Version


}
FileManger Class
public Object read(String FilePath) {
Object Result = null;
try {
System.out.println("Reading ! From " + FilePath);
ObjectInputStream Reader = new ObjectInputStream(new
FileInputStream(FilePath));
Result = Reader.readObject();
} catch (IOException e) {
System.out.println(e);
}
return Result;
}
}
public boolean addStudent() {
loadFromFile(); Some Methods from
Students.add(this);
return commitToFile(); Student Class
}

public boolean commitToFile() {


return FManger.write(studentFileName, Students);
}

public void loadFromFile() {


Students = (ArrayList<Student>) FManger.read(studentFileName);
}

Go To text Version

Go To text Version
Random Access Files
• All of the streams you have used so far are known as read-only or
write-only streams.
• The external files of these streams are sequential files that cannot be
updated without creating a new file.
• It is often necessary to modify files or to insert new records into files.
• Java provides the RandomAccessFile class to allow a file to be read
from and write to at random locations.
RandomAccessFile

83
RandomAccessFile
• A random access file consists of a sequence of bytes. There is a
special marker called file pointer that is positioned at one of these
bytes.
• A read or write operation takes place at the location of the file
pointer. When a file is opened, the file pointer sets at the beginning of
the file.
• When you read or write data to the file, the file pointer moves
forward to the next data.
• For example, if you read an int value using readInt(), the JVM reads
four bytes from the file pointer and now the file pointer is four bytes
ahead of the previous location.
File Pointer
RandomAccessFile Methods
• Many methods in RandomAccessFile are the same as those in
DataInputStream and DataOutputStream. For example,
readInt(), readLong(), writeDouble(), readLine(),
writeInt(), and writeLong() can be used in data input
stream or data output stream as well as in RandomAccessFile
streams.
RandomAccessFile Methods, cont.
void seek(long pos) throws IOException;
Sets the offset from the beginning of the RandomAccessFile
stream to where the next read
or write occurs.

long getFilePointer() IOException;


Returns the current offset, in bytes, from the
beginning of the file to where the next read
or write occurs.
RandomAccessFile Methods, cont.
long length()IOException
Returns the length of the file.

final void writeChar(int v) throws IOException


Writes a character to the file as a two-byte Unicode, with the
high byte written first.

final void writeChars(String s)


throws IOException
Writes a string to the file as a sequence of
characters.
RandomAccessFile Constructor
RandomAccessFile raf =
new RandomAccessFile("test.dat", "rw"); //
allows read and write

RandomAccessFile raf =
new RandomAccessFile("test.dat", "r"); // read
only
A Short Example on RandomAccessFile

TestRandomAccessFile
Run

TestRandomAccessFile Run
import java.io.*;

public class TestRandomAccessFile {


public static void main(String[] args) throws IOException {
try ( // Create a random access file
RandomAccessFile inout = new RandomAccessFile("inout.dat", "rw");
) {
// Clear the file to destroy the old contents if exists
inout.setLength(0);

// Write new integers to the file


for (int i = 0; i < 200; i++)
inout.writeInt(i);

// Display the current length of the file


System.out.println("Current file length is " + inout.length());

// Retrieve the first number


inout.seek(0); // Move the file pointer to the beginning
System.out.println("The first number is " + inout.readInt());
// Retrieve the second number
inout.seek(1 * 4); // Move the file pointer to the second number
System.out.println("The second number is " + inout.readInt());
// Retrieve the tenth number
inout.seek(9 * 4); // Move the file pointer to the tenth number
System.out.println("The tenth number is " + inout.readInt());
// Modify the eleventh number
inout.writeInt(555);

// Append a new number


inout.seek(inout.length()); // Move the file pointer to the end
inout.writeInt(999);

// Display the new length


System.out.println("The new length is " + inout.length());

// Retrieve the new eleventh number


inout.seek(10 * 4); // Move the file pointer to the eleventh number
System.out.println("The eleventh number is " + inout.readInt());
}
} Current file length is 800
} The first number is 0
The second number is 1
The tenth number is 9
The new length is 804
The eleventh number is 555
Thanks
References
• Introduction to Java Programming and Data Structures, Comprehensive Version 12th
Edition, by Y. Liang (Author), Y. Daniel Liang
• Tamer AbdElaziz Yassen, Free Object-Oriented Programming (OOP) Tutorial - Object Oriented Programming using Java in
Arabic (Free) | Udemy

• This slides based on slides provided by Introduction to Java Programming and Data Structures,
Comprehensive Version 12th Edition, by Y. Liang (Author), Y. Daniel Liang
• © Copyright 1992-2012 by Pearson Education, Inc. All Rights Reserved.

• php - What is the advantage of using try {} catch {} versus if {} else {} - Stack Overflow

You might also like