CSC409
Advanced Java Programming
By: Debesh Adhikari
Course Description
• Familiarize students with basic as well as advanced features of Java
Programming
• GUI and Event driven Programming, Database Connectivity, Socket
programming, Servlets and JSP Technology, and Distributed Programming
Course Objectives
• Introduce basic concepts of Java Programming
• Exemplify the concept of GUI programming and JDBC
• Demonstrate socket programming, remoted objects, and servlet and JSP
Technology
UNIT 1
Programming
in Java
Java
Architecture
Java
Architecture • Write a java program with .java extension file
• Compile it with a compiler or javac command
• It will generate a Bytecode file with the class
name, and .class extension
• Java is platform independent as it is run by JVM
rather than being directly run locally
• JVM converts the .class file into machine
code(Binary Code) depending on the type of OS
Components of
Java The execution of a program is done with all these
Architecture three components:
• Java Virtual Machine (JVM)
• Java Runtime Environment (JRE)
• Java Development Kit (JDK)
Java virtual • Write Once Run Anywhere (WORA)
Machine • A Java platform component that gives us an
(JVM) environment to execute java programs
• Main task is to convert byte code into machine
code
• JVM loads the code into memory and verifies it
• After that, it executes the code and provides a
runtime environment
• Java Virtual Machine (JVM) has its own
architecture (for self further study and research)
Java Runtime
Environment • It provides an environment in which Java
(JRE) programs are executed
• The JRE is used to run Java applications.
• JRE takes our Java code, integrates it with the
required libraries, and then starts the JVM to
execute it
• A part of the Java Development Kit (JDK)
• It does not include development tools or the Java
compiler.
Java
Development • The JDK is a full-featured software development
Kit (JDK) kit used to develop Java applications and applets.
It includes everything needed for developing Java
programs.
• Java Development Kit holds JRE, a compiler, an
interpreter or loader, and other several
development tools
Java Components:
Development
Kit (JDK) • Java Compiler (javac): Translates Java code into
bytecode.
• Java Runtime Environment (JRE): Contains the Java
Virtual Machine (JVM), which runs Java bytecode, as
well as libraries and other components required for
running applications.
• Development Tools: Includes tools like javadoc for
generating documentation, javap for disassembling
class files, and more.
Java Buzzwords
1. Simple:
• Java programming language is very simple and easy to learn, understand, and code
• Most of the syntaxes in java follow basic programming language C and object-
oriented programming concepts are like C++
• Many complicated features like pointers, operator overloading, structures, unions,
etc. have been removed
• Garbage collector makes Java further simpler
2. Secure:
• It does not have pointers concept
• Applet which can be embedded into a web application does not allow access to other
parts of the computer, which keeps away from harmful programs like viruses and
unauthorized access
Java Buzzwords
3. Portable (Write Once Run Anywhere)
4. Object Oriented
5. Robust:
• The java code can be executed on a variety of environments
• Has a strong memory management mechanism (garbage
collector)
• Strictly typed language
• It has a strong set of exception handling mechanism, and many
more
Java Buzzwords
6. Architecture Neutral
7. Platform Independent
8. Multi-threaded
9. Interpreted:
• The byte code is interpreted to any machine code so that it runs on the native
machine
10. High Performance
• Features like JVM, interpretation, and its simplicity
Java Buzzwords
11. Distributed
• The byte code is interpreted to any machine code so that it runs on the native
machine
• Supports Remote Method Invocation (RMI)
12.Dynamic:
• The java byte code may be dynamically updated on a running system
• Dynamic memory allocation and deallocation (objects and garbage collector)
Java Buzzwords
13. Garbage Collection
• Java's automatic memory management system that reclaims memory used by objects
no longer in use.
• Supports Remote Method Invocation (RMI)
14. Extensible:
• Java allows developers to extend the language's capabilities through custom libraries
and frameworks.
Path and ClassPath Variables
1. Path Variable:
• PATH is an environment variable used by our Operating System to locate
different files, like executable files (.exe) or java binaries ( java or javac
command)
• .path is like, we are setting an environment for the operating system, to
look in this path for executables
• When you run a command in the terminal or command prompt, the
system searches for the executable file in the directories listed in the
PATH variable.
Path and ClassPath Variables
2. ClassPath Variable:
• CLASSPATH is also an environment variable, which is used by the java compiler, to find the
path of classes
• The CLASSPATH environment variable is used by the Java Virtual Machine (JVM) and Java
applications to locate user-defined classes and packages. It tells the JVM where to look for
classes and resources needed for Java programs.
The main difference between PATH and CLASSPATH is that Path is set for java tools in java
programs like java and javac, which are used to compile your code. Whereas CLASSPATH is
used by System or Application class loader to locate and load compile Java bytecodes
stored in the .class file
Path -> Java files
ClassPath -> Class Files
Path and ClassPath Variables
The CLASSPATH can also be set at runtime using the -classpath or -cp command-line
options when executing Java applications.
This method is often preferred over setting a global CLASSPATH environment
variable, as it avoids conflicts and makes the configuration specific to each
application.
If the CLASSPATH is not set or is empty, the JVM uses the current directory (.) by
default.
java -cp
.:/home/user/java/classes:/home/user/java/lib/someLibrary.jar:/home/user/java/o
ther_classes com.example.MainClass
Sample Java Program
// Your First Program
class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, World!");
}
}
Output: Hello, World!
Note: static keyword - it can be accessed without creating objects
Running Java Programs
• Will be demonstrated in Lab
• Refer to Java Architecture
1.2 Arrays
• An array is a collection of similar type of elements (homogeneous elements)
which has contiguous memory location
• It is a data structure
• Array in Java is index-based, the first element of the array is stored at the 0th
index, 2nd element is stored on 1st index and so on.
• Unlike C/C++, we can get the length of the array using the length member. In
C/C++, we need to use the sizeof operator
1.2 Arrays
Advantages
• Code Optimization: It makes the code optimized, we can retrieve or sort the data
efficiently
• Random access: We can get any data located at an index position
Disadvantages
• Size Limit: We can store only the fixed size of elements in the array. It doesn't grow its
size at runtime. To solve this problem, collection framework is used in Java which
grows automatically
1.2 Arrays
Advanced Information:
• In Java, array is an object of a dynamically generated class
• Java array inherits the Object class and implements the Serializable as well as
Cloneable interfaces
• We can store primitive values or objects in an array in Java
• Java provides the feature of anonymous arrays which is not available in C/C++
// anonymous int array
new int[] { 1, 2, 3, 4};
Arrays
• There are two types of array
1. Single dimensional array
2. Multidimensional array
• Syntax to Declare an Array
• dataType[] arr; (or)
• dataType []arr; (or)
• dataType arr[];
• Instantiation of an Array
• arrayRefVar = new datatype[size];
Arrays
• Array Declaration Examples
String[] cars;
int[] myNum;
• Declaring Values
String[] cars = {"Volvo", "BMW", "Ford", "Mazda"};
int[] myNum = {10, 20, 30, 40};
• Access the Elements of an Array
System.out.println(cars[0]);
//Output: Volvo
Arrays
• Array Length
System.out.println(cars.length);
// Outputs 4
Loop Through an Array
• You can loop through the array elements with the for loop and use the
length property to specify how many times the loop should run
String[] cars = {"Volvo", "BMW", "Ford", "Mazda"};
for (int i = 0; i < cars.length; i++) {
System.out.println(cars[i]);
}
Loop Through an Array with for-each
• There is also a "for-each" loop, which is used exclusively to loop through
elements in arrays:
• Syntax:
for (type variable : arrayname) {
...
}
• Example:
String[] cars = {"Volvo", "BMW", "Ford", "Mazda"};
for (String i : cars) {
System.out.println(i);
}
Loop Through Multidimensional Arrays
A multidimensional array is essentially an array of arrays, and you can access
its elements by using multiple indices.
The most common multidimensional array is a two-dimensional array, which
can be visualized as a matrix or a table with rows and columns.
Create and loop through multidimensional arrays using nested loops
Loop Through Multidimensional Arrays
public class MultiDimensionalArrayExample {
public static void main(String[] args) {
// Declare and initialize a 2D array
int[][] array = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
// Loop through the array using nested loops
for (int i = 0; i < array.length; i++) { // Loop through rows
for (int j = 0; j < array[i].length; j++) { // Loop through columns
System.out.print(array[i][j] + " ");
}
System.out.println(); // Move to the next line after each row
} }}
Multidimensional Arrays
int[][] myNumbers = { {1, 2, 3, 4}, {5, 6, 7} };
int x = myNumbers[1][2];
System.out.println(x);
// Outputs 7
Loop Through Multidimensional Arrays
Using foreach
// Loop through the array using nested foreach loops
for (int[] row : array) { // Loop through each row (which is an array)
for (int element : row) { // Loop through each element in the row
System.out.print(element + " ");
}
System.out.println(); // Move to the next line after each row
Class and Object
• Everything in Java is associated with classes and objects, along with its
attributes and methods
• For example: in real life, a car is an object. The car has attributes, such as
weight and color, and methods, such as drive and brake
• A Class is like an object constructor, or a "blueprint" for creating objects
• To create a class, we use the keyword class
• To create an object of a class, specify the class name, followed by the object
name, and use the keyword new
Class and Object
public class Main {
int x = 5;
public static void main(String[] args) {
Main myObj = new Main();
System.out.println(myObj.x);
}
}
//Outputs 5
Method Overloading
• With method overloading, multiple methods can have the same name with
different parameters:
int myMethod(int x)
float myMethod(float x)
double myMethod(double x, double y)
Same or Different Return Type: Overloaded methods can have the same or
different return types, but the return type alone cannot be used to
distinguish overloaded methods.
Method Overloading
Key Characteristics of Overloading
• Same Method Name: All overloaded methods must have the same name.
• Different Parameter Lists: The parameter lists of overloaded methods must
differ in either the number of parameters, the type of parameters, or both.
The return type alone is not sufficient to distinguish overloaded methods.
• Same or Different Return Type: Overloaded methods can have the same or
different return types, but the return type alone cannot be used to
distinguish overloaded methods.
Method Overloading
Overloaded methods can have different access modifiers.
They can throw different exceptions.
It's good practice to overload methods only when they perform conceptually
similar operations.
Method Overloading
public int add(int a, int b) {
return a + b;
}
public int add(int a, int b, int c) {
return a + b + c;
}
// Method to calculate the sum of two double numbers
public double add(double a, double b) {
return a + b;
}
Access Privileges
In Java, access privileges (or access modifiers) are keywords that determine
the visibility and accessibility of classes, methods, and fields (attributes)
within the code.
They control where and how these members can be accessed, thereby
enforcing encapsulation and protecting the integrity of the data.
Access modifiers are essential for encapsulation, a core principle of object-oriented
programming that helps protect an object's data and behavior from unintended
interference and misuse.
Access Privileges
There are four types of Java access modifiers:
1. Private: The access level of a private modifier is only within the class. It cannot be
accessed from outside the class.
2. Default: The access level of a default modifier is only within the package. It cannot
be accessed from outside the package. If you do not specify any access level, it will be
the default.
3. Protected: The access level of a protected modifier is within the package and outside
the package through child class. If you do not make the child class, it cannot be
accessed from outside the package.
4. Public: The access level of a public modifier is everywhere. It can be accessed from
within the class, outside the class, within the package and outside the package.
Interface
• In Java, an interface is an abstract type that is used to specify a set of
methods that a class must implement.
• One way to achieve abstraction in Java, is with interfaces
• It serves as a contract between the interface and the classes that
implement it, ensuring that the classes provide implementations for the
methods declared in the interface.
• It is a completely "abstract class" that is used to group related methods
with empty bodies
Interface
Key Features of Interfaces
1. Abstract Methods: By default, all methods in an interface are abstract and public. They do not have a body and must be
implemented by classes that use the interface.
2. Constants: An interface can contain constants, which are implicitly public, static, and final.
3. Multiple Inheritance: A class can implement multiple interfaces, which allows Java to support multiple inheritance of type.
4. Default Methods: Since Java 8, interfaces can include default methods with a body. These methods provide default
behavior that implementing classes can override.
5. Static Methods: Since Java 8, interfaces can also include static methods, which belong to the interface itself rather than
any instance of the class.
Interface
interface Animal {
public void animalSound(); // interface method (does not have a body)
public void sleep(); // interface method (does not have a body)
}
Interface
// Pig "implements" the Animal interface
class Pig implements Animal {
public void animalSound() {
// The body of animalSound() is provided here
System.out.println("The pig says: wee wee");
}
public void sleep() {
// The body of sleep() is provided here
System.out.println("Zzz");
}
}
Interface
class Main {
public static void main(String[] args) {
Pig myPig = new Pig(); // Create a Pig object
myPig.animalSound();
myPig.sleep();
}
}
Inner Class
• In Java, it is also possible to nest classes (a class within a class)
• The purpose of nested classes is to group classes that belong together,
which makes your code more readable and maintainable
• To access the inner class, create an object of the outer class, and then
create an object of the inner class.
Inner Class
• In Java, an inner class is a class that is defined within another class.
• Inner classes can access the members (including private members) of the outer class that
they are associated with. This feature is useful when you need to logically group classes
and want to keep the code more readable and maintainable.
There are several types of inner classes in Java:
1.Member Inner Class
2.Static Nested Class
3.Local Inner Class
4.Anonymous Inner Class
Inner Class
1. Member Inner Class: A member inner class is a non-static class that is defined within another
class. It has access to all members of the outer class, including private members.
2. Static Nested Class: A static nested class is similar to a member inner class, but it is marked with
the static keyword. Unlike member inner classes, static nested classes cannot access instance
members of the outer class directly.
3. Local Inner Class: A local inner class is defined within a method or a block of code. It can access
local variables of the enclosing block, provided they are final or effectively final (unchanged after
initialization).
4. Anonymous Inner Class: An anonymous inner class is an inner class without a name and for which
only a single object is created. It is used to provide an implementation of an interface or an
abstract class, or to override methods of a class.java
Inner Class
class OuterClass {
int x = 10;
class InnerClass {
int y = 5;
}
}
Inner Class
public class Main {
public static void main(String[] args) {
OuterClass myOuter = new OuterClass();
OuterClass.InnerClass myInner = myOuter.new InnerClass();
System.out.println(myInner.y + myOuter.x);
}
}
// Outputs 15 (5 + 10)
Inner Class
Usage and Benefits
• Encapsulation: Inner classes can be used to encapsulate helper classes that are
only used by the outer class, keeping them hidden from the outside world.
• Logical Grouping: They provide a way to logically group classes that are only used
in one place, making the code more organized.
• Access to Outer Class Members: Inner classes can directly access the members of
their enclosing class, making them useful for certain designs like callback
implementations.
• Inner classes can add clarity and structure to your code, but they should be used
judiciously to avoid making the code overly complex.
Final
• The final keyword is a non-access modifier used for classes, attributes and
methods, which makes them non-changeable
• The final keyword is useful when you want a variable to always store the
same value, like PI (3.14159...)
• The final keyword is called a "modifier“
final int x = 10;
Final
• The final keyword is a non-access modifier that can be applied to variables,
methods, and classes. It has different meanings depending on where it is used.
Final variables: local, instance and static.
1. final local : A variable declared with the final keyword becomes a constant,
meaning its value cannot be changed once it has been initialized.
2. Final Instance Variables: For instance variables, final ensures that the variable
is initialized once and cannot be reassigned. It must be initialized either during
declaration or in the constructor.
3. Final Static Variables: Final static variables are constants at the class level,
often used to define constants. They must be initialized when they are declared
or in a static initializer block.
Final
• Final Methods: When a method is declared as final, it cannot be overridden
by subclasses. This is useful when you want to prevent subclasses from
changing the implementation of a method.
• Final Class: A class declared as final cannot be subclassed, cannot be
inherited. This is useful when you want to prevent other classes from
extending and modifying the behavior of your class.
Final
public class Main {
final int x = 10;
public static void main(String[] args) {
Main myObj = new Main();
myObj.x = 25; // will generate an error: cannot assign a value to a final
variable
System.out.println(myObj.x);
}
}
Static
• The static keyword is a non-access modifier (means it is used for other purposes)
used for methods and attributes
• Static methods/attributes can be accessed without creating an object of a class.
• Static variables (class variables), static methods, static blocks, static nested class
static void myStaticMethod() {
System.out.println(“Can be called without creating objects");
}
In Main function we can just call:
myStaticMethod();
Static
public class Example {
public static int staticVar = 0;
public static void main(String[] args) {
Example.staticVar = 10;
System.out.println(Example.staticVar); // Outputs: 10
}
}
Static: Key Characteristics
Memory Management:
Static variables are stored in the static memory area and have a single copy shared among all
instances of the class. They are initialized when the class is loaded into memory.
Class-Level Scope:
Static methods and variables belong to the class rather than any specific instance. As a result, they
can be accessed without creating an object of the class.
No Access to Instance Members:
Static methods and nested classes cannot access instance variables and methods directly. They can
only access static members. To access instance members, a reference to an instance must be
provided.
The static keyword is useful for defining members that should be shared across all instances of a
class, utility methods, and constants.
Packages
• A package in Java is used to group related classes
• We use packages to avoid name conflicts, and to write a better maintainable code
• In Java, a package is a namespace that organizes a set of related classes and
interfaces
• Conceptually, you can think of packages as similar to folders in a file system. They
help in avoiding name conflicts, managing large codebases, and controlling access
to classes.
• Packages are divided into two categories:
• Built-in Packages (packages from the Java API)
• To use a class or a package from the library, you need to use the import keyword
• User-defined Packages (create your own packages)
• To create a package, use the package keyword
Key Point About Package
• Namespace Management: Packages provide a way to organize and group
related classes, interfaces, enumerations, and annotations, preventing
naming conflicts by grouping classes into different namespaces.
• Access Control: Packages help control access to classes and members. You
can use access modifiers (public, protected, private, and default package-
private) to control access to classes and class members from outside the
package.
• Modularity and Maintainability: By grouping related classes, packages
make code more modular, easier to maintain, and easier to navigate.
• Reusability: Packages can be reused in other programs or projects,
facilitating code reuse.
Package
package com.example.mypackage;
public class MyClass {
public void display() {
System.out.println("This is a class in a package.");
}
}
To create a package, you use the package keyword at the beginning of your Java source file, followed
by the package name. For example, to create a package named com.example.mypackage
Package Name Convention: The package name is typically written in all lowercase. To prevent
naming conflicts, it's common practice to use the reverse of the domain name of the organization as
the root package (e.g., com.example).
Package
Using Classes from a Package
To use a class from a different package, you need to import it using the import statement.
You can import a specific class or the entire package.
import com.example.mypackage.MyClass;
//import com.example.mypackage.*;
public class Test {
public static void main(String[] args) {
MyClass obj = new MyClass();
obj.display(); // Outputs: This is a class in a package.
}
}
Inheritance
• Inheritance is one of the fundamental concepts in object-oriented programming (OOP),
including Java
• It allows a new class (called the subclass or derived class) to inherit attributes and methods
from an existing class (called the superclass or base class).
• The subclass can reuse the code from the superclass and can also have additional properties
and behaviors or override existing ones
• In Java, it is possible to inherit attributes and methods from one class to another
• We group the "inheritance concept" into two categories:
• subclass (child) - the class that inherits from another class
• superclass (parent) - the class being inherited from
• To inherit from a class, use the extends keyword
Key Concepts of Inheritance
• Superclass and Subclass
• extends Keyword
• Single Inheritance: Java supports single inheritance, meaning a class can
only extend one superclass. However, a class can implement multiple
interfaces.
• Method Overriding: A subclass can provide its own implementation of a
method that is already defined in its superclass. This is known as method
overriding.
• super Keyword: The super keyword is used to refer to the superclass. It can
be used to call superclass methods and constructors.
Inheritance
class Vehicle {
protected String brand = "Ford"; // Vehicle attribute
public void honk() { // Vehicle method
System.out.println("Tuut, tuut!");
}
}
class Car extends Vehicle {
private String modelName = "Mustang"; // Car attribute
public static void main(String[] args) {
Car myCar = new Car(); // Create a myCar object
myCar.honk(); // Call the honk() method (from the Vehicle class) on the myCar object
// Display the value of the brand attribute (from the Vehicle class) and the value of the modelName from the Car class
System.out.println(myCar.brand + " " + myCar.modelName);
}
} // Output: Tuut, tuut! /n Ford Mustang
Advantages of Inheritance
• Code Reusability: Inheritance promotes code reuse. The subclass can use
the methods and properties of the superclass without rewriting the same
code.
• Method Overriding: Subclasses can provide specific implementations of
methods that are already defined in the superclass, allowing for dynamic
polymorphism.
• Clear Structure: Inheritance helps in creating a clear class hierarchy, making
it easier to manage and understand the relationships between classes.
Advantages of Inheritance
• Tight Coupling: Inheritance introduces a strong relationship between the
superclass and subclass, making changes in the superclass potentially affect
subclasses.
• Single Inheritance Limitation: Java's restriction to single inheritance can
sometimes limit the design flexibility, although interfaces can mitigate this.
• Increased Complexity: Overuse of inheritance can make the codebase
complex and harder to understand.
Multiple Inheritance in Java
• Single Inheritance Limitation: Java's restriction to single inheritance can
sometimes limit the design flexibility, although interfaces can mitigate this.
Overriding
• Overriding is a feature that allows a subclass or child class to provide a specific
implementation of a method that is already provided by one of its super-classes
or parent classes
• When a method in a subclass has the same name, same parameters or signature,
and same return type(or sub-type) as a method in its super-class, then the
method in the subclass is said to override the method in the super-class
• One of the way by which java achieve Run Time Polymorphism
• The version of a method that is executed will be determined by the object that is
used to invoke it
• If an object of a parent class is used to invoke the method, then the version in the
parent class will be executed, but if an object of the subclass is used to invoke the
method, then the version in the child class will be executed
Key Points About Overriding
• Same Signature: The method in the subclass must have the same name, return type (or a
subtype), and parameter list as the method in the superclass.
• @Override Annotation: Although not mandatory, it's a good practice to use the
@Override annotation above the overridden method. This helps catch errors at compile
time if the method signature doesn't match the superclass method.
• Access Modifier: The access level of the overridden method in the subclass cannot be
more restrictive than the access level of the method in the superclass. For example, if the
superclass method is public, the subclass method cannot be protected or private.
• Checked Exceptions: The overridden method can throw fewer or no checked exceptions,
but it cannot throw new or broader checked exceptions than those declared by the
superclass method.
• Dynamic Method Dispatch: When a method is overridden, the version of the method
that gets executed is determined by the object's actual type, not the reference type. This
is known as dynamic method dispatch and is a form of runtime polymorphism.
Overriding
// Superclass
class Animal {
public void sound() {
System.out.println("Animal makes // Another Subclass
a sound"); class Cat extends Animal {
} @Override
} public void sound() {
System.out.println("Cat meows");
// Subclass
}
class Dog extends Animal { }
@Override
public void sound() {
System.out.println("Dog barks");
}
}
Overriding
public class Main {
public static void main(String[] args) {
Animal myAnimal = new Animal(); // Animal reference and object
Animal myDog = new Dog(); // Animal reference but Dog object
Animal myCat = new Cat(); // Animal reference but Cat object
myAnimal.sound(); // Outputs: Animal makes a sound
myDog.sound(); // Outputs: Dog barks
myCat.sound(); // Outputs: Cat meows
}
}
Key Points About Overriding
• Same Signature: The method in the subclass must have the same name, return type (or a
subtype), and parameter list as the method in the superclass.
• @Override Annotation: Although not mandatory, it's a good practice to use the
@Override annotation above the overridden method. This helps catch errors at compile
time if the method signature doesn't match the superclass method.
• Access Modifier: The access level of the overridden method in the subclass cannot be
more restrictive than the access level of the method in the superclass. For example, if the
superclass method is public, the subclass method cannot be protected or private.
• Checked Exceptions: The overridden method can throw fewer or no checked exceptions,
but it cannot throw new or broader checked exceptions than those declared by the
superclass method.
• Dynamic Method Dispatch: When a method is overridden, the version of the method
that gets executed is determined by the object's actual type, not the reference type. This
is known as dynamic method dispatch and is a form of runtime polymorphism.
Benefits of Overriding
• Polymorphism: Overriding allows a single method call to behave differently
based on the object it is acting upon, providing flexibility and dynamic
behavior in code.
• Code Reusability: Subclasses can use the same method name and provide
specific behavior, promoting code reuse.
• Runtime Behavior: Overriding allows decisions to be made at runtime
about which method implementation to execute, making it possible to
write more dynamic and flexible code.
Rules of Overriding
• The overriding method must have the same or a compatible return type
(covariant return type) as the method it overrides.
• The overriding method must have the same or less restrictive access level
than the overridden method.
• The overriding method can throw any runtime exceptions, but the checked
exceptions it throws must not be new or broader than those thrown by the
overridden method.
Rules of Overriding
• final Methods: A method declared as final cannot be overridden.
• static Methods: Static methods are not subject to overriding because they
belong to the class, not to instances of the class.
CSC409
Thank you!!!!!