Module 1
An Overview of Java:
Object-Oriented Programming
Object-oriented programming (OOP) is at the core of Java.
Two Paradigms
All computer programs can be conceptually organized around its code or around its data. These are the two
paradigms that govern how a program is constructed.
The first way is called the process-oriented model. This approach characterizes a program as a series of
linear steps (that is, code). The process-oriented model can be thought of as code acting on data. Procedural
languages such as C employ this model to considerable success.
To manage increasing complexity, the second approach, called object-oriented programming, was
conceived. Object-oriented programming organizes a program around its data (that is, objects) and a set of
well-defined interfaces to that data. An object-oriented program can be characterized as data controlling
access to code.
Abstraction
An essential element of object-oriented programming is abstraction. Humans manage complexity through
abstraction. For example, people do not think of a car as a set of tens of thousands of individual parts. They
think of it as a well-defined object with its own unique behavior. This abstraction allows people to use a
car to drive to the grocery store without being overwhelmed by the complexity of the parts that form the
car. They can ignore the details of how the engine, transmission, and braking systems work. Instead, they
are free to utilize the object as a whole.
Abstraction is the process of taking away or removing characteristics from something in order to reduce it
to a set of essential [Link] the process of abstraction, a programmer hides all but the
relevant data about an object in order to reduce complexity and increase efficiency.
The Three OOP Principles
All object-oriented programming languages provide mechanisms that help you implement the object-
oriented model. They are encapsulation, inheritance, and polymorphism.
Encapsulation
Encapsulation is the mechanism that binds together code and the data it manipulates, and keeps both safe
from outside interference and misuse. One way to think about encapsulation is as a protective wrapper that
prevents the code and data from being arbitrarily accessed by other code defined outside the wrapper.
In Java, the basis of encapsulation is the class. A class defines the structure and behavior (data and code)
that will be shared by a set of objects. Each object of a given class contains the structure and behavior
defined by the class, as if it were stamped out by a mold in the shape of the class. For this reason, objects
are sometimes referred to as instances of a class. Thus, a class is a logical construct; an object has physical
reality. When you create a class, you will specify the code and data that constitute that class.
Collectively, these elements are called members of the class. Specifically, the data defined by the class are
referred to as member variables or instance variables. In properly written Java programs, the methods
define how the member variables can be used. This means that the behavior and interface of a class are
defined by the methods that operate on its instance data. Since the purpose of a class is to encapsulate
complexity, there are mechanisms for hiding the complexity of the implementation inside the class. Each
method or variable in a class may be marked private or public
The public interface of a class represents everything that external users of the class need to know, or may
know.
The private methods and data can only be accessed by code that is a member of the class. Therefore, any
other code that is not a member of the class cannot access a private method or variable. Since the private
members of a class may only be accessed by other parts of your program through the class’ public methods,
you can ensure that no improper actions take place.
Inheritance
Inheritance is the process by which one object acquires the properties of another object. By use of
inheritance, an object need only define those qualities that make it unique within its class. It can inherit its
general attributes from its parent. It is the mechanism in Java by which one class is allowed to inherit
the features(fields and methods) of another class. In Java, Inheritance means creating new classes based
on existing ones. A class that inherits from another class can reuse the methods and fields of that class.
In addition, you can add new fields and methods to your current class as well.
• Super Class/Parent Class: The class whose features are inherited is known as a superclass (or a
base class or a parent class).
• Sub Class/Child Class: The class that inherits the other class is known as a subclass (or a derived
class, extended class, or child class). The subclass can add its own fields and methods in addition
to the superclass fields and methods.
The syntax of Java Inheritance
1. class Subclass-name extends Superclass-name
2. {
3. //methods and fields
4. }
The extends keyword indicates that you are making a new class that derives from an existing class. The
meaning of "extends" is to increase the functionality.
Polymorphism
The word polymorphism means having many forms. In simple words, we can define polymorphism as
the ability of a message to be displayed in more than one form.
Real-life Illustration Polymorphism: A person at the same time can have different characteristics.
Like a man at the same time is a father, a husband, and an employee. So the same person possesses
different behavior in different situations. This is called polymorphism.
Polymorphism allows us to perform a single action in different ways. In other words, polymorphism
allows you to define one interface and have multiple implementations. The word “poly” means many
and “morphs” means forms, So it means many forms.
When properly applied, polymorphism, encapsulation, and inheritance combine to produce a programming
environment that supports the development of far more robust and scaleable programs than does the
process-oriented model. A well-designed hierarchy of classes is the basis for reusing the code in which you
have invested time and effort developing and testing. Encapsulation allows you to migrate your
implementations over time without breaking the code that depends on the public interface of your classes.
Polymorphism allows you to create clean, sensible, readable, and resilient code.
Using Blocks of Code
Java allows two or more statements to be grouped into blocks of code, also called code blocks. This is done
by enclosing the statements between opening and closing curly braces. Once a block of code has been
created, it becomes a logical unit that can be used any place that a single statement can. For example, a
block can be a target for Java’s if and for statements.
Consider this if statement:
If (x < y) { // begin a block
x = y;
y = 0;
} // end of block
Here, if x is less than y, then both statements inside the block will be executed. Thus, the two statements
inside the block form a logical unit, and one statement cannot execute without the other also executing. The
key point here is that whenever you need to logically link two or more statements, you do so by creating a
block.
Let’s look at another example.
class BlockTest {
public static void main(String args[]) {
int x, y;
y = 20;
// the target of this loop is a block
for(x = 0; x<10; x++) {
[Link]("This is x: " + x);
[Link]("This is y: " + y);
y = y - 2;
}
}
}
The output generated by this program is shown here:
This is x: 0
This is y: 20
This is x: 1
This is y: 18
This is x: 2
This is y: 16
This is x: 3
This is y: 14
This is x: 4
This is y: 12
This is x: 5
This is y: 10
This is x: 6
This is y: 8
This is x: 7
This is y: 6
This is x: 8
This is y: 4
This is x: 9
This is y: 2
In this case, the target of the for loop is a block of code and not just a single statement. Thus, each time the
loop iterates, the three statements inside the block will be executed. This fact is, of course, evidenced by
the output generated by the program.
Lexical Issues
Java programs are a collection of whitespace, identifiers, literals, comments, operators, separators, and
keywords.
1. Whitespace
Java is a free-form language. This means that you do not need to follow any special indentation rules. For
instance, the Example program could have been written all on one line or in any other strange way you felt
like typing it, as long as there was at least one whitespace character between each token that was not already
delineated by an operator or separator. In Java, whitespace is a space, tab, or newline.
2. Identifiers
Identifiers are used to name things, such as classes, variables, and methods. An identifier may be any
descriptive sequence of uppercase and lowercase letters, numbers, or the underscore and dollar-sign
characters. (The dollar-sign character is not intended for general use.) They must not begin with a number,
lest they be confused with a numeric literal. Again, Java is case-sensitive, so VALUE is a different identifier
than Value. Some examples of valid identifiers are
AvgTemp count a4 $test this_is_ok
Invalid identifier names include these:
2count high-temp Not/ok
3. Literals
A constant value in Java is created by using a literal representation of it. For example, here are some literals:
100 98.6 ‘X’ “This is a test”
Left to right, the first literal specifies an integer, the next is a floating-point value, the third is a character
constant, and the last is a string. A literal can be used anywhere a value of its type is allowed.
4. Comments
There are three types of comments defined by Java.
1. Single-line
//
2. Multiline.
/*
--
--
--
*/
[Link] comment.
This type of comment is used to produce an HTML file that documents your program.
/**
--
---
*/
5. Separators
In Java, there are a few characters that are used as separators.
6. The Java Keywords
There are 50 keywords currently defined in the Java language . These keywords, combined with the
syntax of the operators and separators, form the foundation of the Java language. These keywords cannot
be used as [Link], they cannot be used as names for a variable, class, or method.
Data Types, Variables, and Arrays:
The Primitive Types
Java defines eight primitive types of data: byte, short, int, long, char, float, double, and boolean. These
can be put in four groups:
• Integers : This group includes byte, short, int, and long, which are for whole-valued signed numbers.
• Floating-point numbers : Floating-point numbers, also known as real numbers, are used when evaluating
expressions that require fractional precision. There are two kinds of floating-point types, float and double,
which represent single- and double-precision numbers, respectively. Their width and ranges are shown
here:
• Characters : In Java, the data type used to store characters is char. This data type is used to store
a single character. The character must be enclosed within single quotes, like ‘E’ or ‘e’. Alternatively, you
can also use ASCII values to display certain characters. Let’s take a small example and see how it works.
1 char alpha = 'J';
2
3 char a = 65, b = 66, c = 67;
4 [Link](alpha); // prints J
5
6 [Link](a); // Displays 65
7 [Link](b); // Displays 66
[Link](c); // Displays 67
8
• Boolean : A boolean data type comprises of a bit of information and can store only true or false values.
This data type is used to track true/false conditions. Now let’s write a small program and understand how
it works.
1 class booleanDataType{
2 public static void main(String args[]){
3 // Setting the values for boolean data type
4
boolean Java = true;
5
boolean Python = false;
6 [Link](Java); // Output will be true
7 [Link](Python); // Output will be
8 false
9 }
}
10
Variables
A variable is defined by the combination of an identifier, a type, and an optional initializer. In addition, all
variables have a scope, which defines their visibility, and a lifetime.
Declaring a Variable
In Java, all variables must be declared before they can be used. The basic form of a variable declaration is
shown here:
type identifier [ = value ][, identifier [= value ] …];
Here, type is one of Java’s atomic types, or the name of a class or [Link] identifier is the name of the
variable. You can initialize the variable by specifying an equal sign and a value.
To declare more than one variable of the specified type, use a comma-separated list.
Here are several examples of variable declarations of various types. Note that some
include an initialization.
int a, b, c; // declares three ints, a, b, and c.
int d = 3, e, f = 5; // declares three more ints, initializing
// d and f.
byte z = 22; // initializes z.
double pi = 3.14159; // declares an approximation of pi.
char x = 'x'; // the variable x has the value 'x'.
Dynamic Initialization
Java allows variables to be initialized dynamically, using any expression valid at the time the variable is
declared. In this method, the variable is assigned a value at the run-time. The value is either assigned by the
function in the program or by the user at the time of running the program. The value of these variables can be
altered every time the program runs.
class DynInit {
public static void main (String args[])
// a is dynamically initialized
double a = [Link](25);
[Link](“Sqrt of 25 is: ” +a );
}
}
Output:
Sqrt of 25 is: 5
The Scope and Lifetime of Variables
Java allows variables to be declared within any block. a block is begun with an opening curly brace and
ended by a closing curly brace. A block defines a scope. Thus, each time you start a new block, you are
creating a new scope. A scope determines what objects are visible to other parts of your program. It also
determines the lifetime of those objects.
The scope defined by a method begins with its opening curly brace. However, if that method has parameters,
they too are included within the method’s scope. variables declared inside a scope are not visible (that is,
accessible) to code that is defined outside that scope. Thus, when you declare a variable within a scope, you
are localizing that variable and protecting it from unauthorized access and/or modification. Scopes can be
nested. For example, each time you create a block of code, you are creating a new, nested scope. When this
occurs, the outer scope encloses the inner scope. This means that objects declared in the outer scope will
be visible to code within the inner
scope. However, the reverse is not true. Objects declared within the inner scope will not be visible outside
it.
To understand the effect of nested scopes, consider the following program:
// Demonstrate block scope.
class Scope {
public static void main(String args[]) {
int x; // known to all code within main
x = 10;
if(x == 10) { // start new scope
int y = 20; // known only to this block
// x and y both known here.
[Link]("x and y: " + x + " " + y);
x = y * 2;
}
y = 100; // Error! y not known here
// x is still known here.
[Link]("x is " + x);
}
}
As the comments indicate, the variable x is declared at the start of main( )’s scope and is accessible to all
subsequent code within main( ). Within the if block, y is declared. Since a block defines a scope, y is only
visible to other code within its block. y is not visible outside of its block. Within the if block, x can be used
because code within a block (that is, a nested scope) has access to variables declared by an enclosing scope.
If you declare a variable at the end of a block, it is effectively useless, because no code will have access to
it. For example, this fragment is invalid because count cannot be used prior to its declaration:
// This fragment is wrong!
count = 100; // oops! cannot use count before it is declared!
int count;
If a variable declaration includes an initializer, then that variable will be reinitialized each time the block
in which it is declared is entered. For example, consider the next program:
// Demonstrate lifetime of a variable.
class LifeTime {
public static void main(String args[]) {
int x;
for(x = 0; x < 3; x++) {
int y = -1; // y is initialized each time block is entered
[Link]("y is: " + y); // this always prints -1
y = 100;
[Link]("y is now: " + y);
}
}
}
The output generated by this program is shown here:
y is: -1
y is now: 100
y is: -1
y is now: 100
y is: -1
y is now: 100
As you can see, y is reinitialized to –1 each time the inner for loop is entered. Even though it is subsequently
assigned the value 100, this value is lost. One last point: Although blocks can be nested, you cannot declare
a variable to have the same name as one in an outer scope. For example, the following program is illegal:
// This program will not compile
class ScopeErr {
public static void main(String args[]) {
int bar = 1;
{ // creates a new scope
int bar = 2; // Compile-time error – bar already defined!
}
}
}
Type Conversion and Casting
If the two types are compatible, then Java will perform the conversion automatically. For example, it is
always possible to assign an int value to a long variable. However, not all types are compatible, and thus,
not all type conversions are implicitly allowed. For instance, there is no automatic conversion defined from
double to byte. Fortunately, it is still possible to obtain a conversion between incompatible types. To do
so, you must use a cast, which performs an explicit conversion between incompatible types.
Java’s Automatic Conversions
When one type of data is assigned to another type of variable, an automatic type conversion will take place
if the following two conditions are met:
• The two types are compatible.
• The destination type is larger than the source type.
For example, the int type is always large enough to hold all valid byte values, so no explicit cast statement
is required. The numeric types, including integer and floating-point types, are compatible with each other.
However, there are no automatic conversions from the numeric types to char or boolean. Also, char and
boolean are not compatible with each other.
Casting Incompatible Types
Although the automatic type conversions are helpful, they will not fulfill all needs. For example, what if
you want to assign an int value to a byte variable? This conversion will not be performed automatically,
because a byte is smaller than an int. This kind of conversion is sometimes called a narrowing conversion,
since you are explicitly making the value narrower so that it will fit into the target type.
To create a conversion between two incompatible types, you must use a cast. A cast is simply an explicit
type conversion. It has this general form:
(target-type) value
Here, target-type specifies the desired type to convert the specified value to. For example, the following
fragment casts an int to a byte. If the integer’s value is larger than the range of a byte, it will be reduced
modulo (the remainder of an integer division by the) byte’s range.
int a;
byte b;
// …
b = (byte) a;
The following program demonstrates some type conversions that require casts:
// Demonstrate casts.
class Conversion {
public static void main(String args[]) {
byte b;
int i = 257;
double d = 323.142;
[Link]("\nConversion of int to byte.");
b = (byte) i;
[Link]("i and b " + i + " " + b);
[Link]("\nConversion of double to int.");
i = (int) d;
[Link]("d and i " + d + " " + i);
[Link]("\nConversion of double to byte.");
b = (byte) d;
[Link]("d and b " + d + " " + b);
}
}
This program generates the following output:
Conversion of int to byte.
i and b 257 1
Conversion of double to int.
d and i 323.142 323
Conversion of double to byte.
d and b 323.142 67
Automatic Type Promotion in Expressions
Examine the following expression:
byte a = 40;
byte b = 50;
byte c = 100;
int d = a * b / c;
The result of the intermediate term a * b easily exceeds the range of either of its byte operands. To handle
this kind of problem, Java automatically promotes each byte, short, or char operand to int when evaluating
an expression. This means that the subexpression a*b is performed using integers—not bytes. Thus, 2,000,
the result of the intermediate expression, 50 * 40, is legal even though a and b are both specified as type
byte.
The Type Promotion Rules
Java defines several type promotion rules that apply to expressions. They are as follows: First, all byte,
short, and char values are promoted to int, as just described. If one operand is a long, float or double the
whole expression is promoted to long, float or double respectively. The following program demonstrates
how each value in the expression gets promoted to match the second argument to each binary operator:
class Promote {
public static void main(String args[]) {
byte b = 42;
char c = 'a';
short s = 1024;
int i = 50000;
float f = 5.67f;
double d = .1234;
double result = (f * b) + (i / c) - (d * s);
[Link]((f * b) + " + " + (i / c) + " - " + (d * s));
[Link]("result = " + result);
}
}
Let’s look closely at the type promotions that occur in this line from the program:
double result = (f * b) + (i / c) - (d * s);
In the first subexpression, f * b, b is promoted to a float and the result of the subexpression is float. Next,
in the subexpression i/c, c is promoted to int, and the result is of type int. Then, in d * s, the value of s is
promoted to double, and the type of the subexpression is double. Finally, these three intermediate values,
float, int, and double, are considered. The outcome of float plus an int is a float. Then the resultant float
minus the last double is promoted to double, which is the type for the final result of the expression.
What is an Array in Java?
An array refers to a data structure that contains homogeneous elements. This
means that all the elements in the array are of the same data type. Let's take an
example:
This is an array of seven elements. All the elements are integers and homogeneous.
The green box below the array is called the index, which always starts from zero and
goes up to n-1 elements. In this case, as there are seven elements, the index is from
zero to six. There are three main features of an array:
1. Dynamic allocation: In arrays, the memory is created dynamically, which reduces
the amount of storage required for the code.
2. Elements stored under a single name: All the elements are stored under one
name. This name is used any time we use an array.
3. Occupies contiguous location: The elements in the arrays are stored at adjacent
positions. This makes it easy for the user to find the locations of its elements.
Advantages of Arrays in Java
• Java arrays enable you to access any element randomly with the help of indexes
• It is easy to store and manipulate large data sets
Disadvantages of Arrays in Java
• The size of the array cannot be increased or decreased once it is declared—arrays have a fixed size
• Java cannot store heterogeneous data. It can only store a single type of primitives
Define an Array in Java
Arrays in Java are easy to define and declare. First, we have to define the array.
The syntax for it is:
Here, the type is int, String, double, or long. Var-name is the variable name of the
array.