0% found this document useful (0 votes)
147 views50 pages

Sololearn Java

Java is a popular, platform-independent programming language used to develop various applications. The basic "Hello World" Java program prints text to the screen using println and requires every program to have a main method. Java supports primitive data types, operators, conditionals, loops, and user input through the Scanner class. Key features include object-oriented design, bytecode compilation, and the ability to write code once and run it on any system.
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
Download as docx, pdf, or txt
0% found this document useful (0 votes)
147 views50 pages

Sololearn Java

Java is a popular, platform-independent programming language used to develop various applications. The basic "Hello World" Java program prints text to the screen using println and requires every program to have a main method. Java supports primitive data types, operators, conditionals, loops, and user input through the Scanner class. Key features include object-oriented design, bytecode compilation, and the ability to write code once and run it on any system.
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1/ 50

Basic Concepts

Java is a high level, modern programming language designed in the early 1990s by Sun
Microsystems, and currently owned by Oracle.
Java is Platform Independent, which means that you only need to write the program once to be
able to run it on a number of different platforms. Java is portable, robust, and dynamic, with the
ability to fit the needs of virtually any type of application. Write Once, Run Anywhere.
More than 3 billion devices run Java, it is used to develop apps for Google’s Android OS, various
Desktop Applications, such as media players, antivirus programs, web applications, enterprise
applications, and more.
“Hello World” program:
class MyClass {
public static void main(String[] args) {
System.out.println(“Hello World”);
}
}
In Java every program must have a class and every Java program starts from the main method. A
method is a collection of statements that are grouped together to perform an operation.
public: anyone can access it
static: method can be run without creating an instance of the class containing the main method
void: method doesn’t return any value
main: the name of the method
This code declares a method called test, does not return anything and has no parameters:
Void test()
The method’s parameters are declared inside the parentheses that follow the name of the method.
For main, it’s an array of strings called args.
The println method prints a line of text to the screen. The System class and its out stream are
used to access the println method. In classes, methods, and other flow-control structures code is
always enclosed in curly brackets { }.
In Java, each code statement must end with a semicolon, however do not use semicolons after
method and class declarations that follow with the body defined using the curly braces.
The purpose of including comments in your code is to explain what the code is doing. All
comments are ignored by compiler.
A single-line comment starts with two forward slashes and continues until it reaches the end of the
line:
// this is a single-line comment
Comments provide clarification and understanding when you need to refer back to it as well as for
others who might need to read it.
Multi-line comments, or block comments, are a forward slash followed by an asterisk, with it
ending with an asterisk followed by a forward shash
/* Comment spanning
Multiple lines */
Java does not support multi-line comments.
Documentation comments are special comments that have the appearance of multi-line comments
with the difference being that they generate external documentation of your source code. They
begin with a forward slash followed by two asterisks, and end with an asterisk followed by a
forward slash.
/** Documentation
Comment **/
Javadoc is a tool which comes with JDK and it is used for generating Java code documentation in
HTML format from Java source code which has required documentation in a predefined format.
When a documentation comment begins with more than two asterisks, Javadoc assumes that you
want to create a ”box” around the comments in the source code.
Variable store data for processing. A variable is given a name that uniquely identifies that variable,
and a value can be assigned to the variable that can be retrieved.
Multiple types like int, double and String.
String name = “David”;
Creates a variable called name of type String, and assigns it the value “David”.
char stands for character and holds a single character.
Boolean can only have two values: true and false or 1 and 0.
A value used on either side of an operator is called an operand. For example:
int x = 6 + 3;
arithmetic operators: +, -, *, /, %
int num = 12 / 5; // will give 2
int num = 12 / 5.0; // will give an error
int num = 12.0 / 5.0; // will give an error
double num = 12 / 5; // will give 2.0
double num = 12 / 5.0; // will give 2.4
double num = 12.0 / 5.0; // will give 2.4
Use double to retrieve a value with a decimal point.
The modulo math operation performs an integer division of one value by another, and returns the
remainder of that division.
int res = 23 % 6 // res is 5
An increment or decrement operator provides a more convenient and compact way to increase or
decrease the value of a variable by one.
int test = 5;
++text; // test is now 6
The decrement operator is used to decrease the value of a variable by one.
Int test = 5;
--test; // test is now 4
Use these to avoid calculation mistakes.
Two forms prefix and postfix, can be used with both the increment and decrement operators.
With prefix form, the operator appears before the operand, while in postfix form, the operator
appears after the operand.
Prefix: Increments the variable’s value and uses the new value in the expression.
int x =34;
int y = ++x; // y is 35
Postfix: The variable’s value is first used in the expression and is then increased.
int x =34;
int y = x++; // y is 34
x is first assigned to y, and then incremented by one with postfix, Therefore, x become 35, while y
is assigned the value of 34. Same for decrement.
Java supports Addition and assignment (+=) and all other versions like -=, *=, /= and %=.
A String is an object that represents a sequence of characters.
String s = “SoloLearn”;
You are allowed to define an empty string.
The char data type represents a single character.
Char s = ‘S’;
The + operator between string adds them together to make a new string. This is called
concatenation.
System.out.println(“Hello” + “ “ + “World”);
The Scanner object is the most common method for getting user input. Import the Scanner class
to use it.
import java.util.Scanner;
In order to use the Scanner class, create an instance of the class by using syntax:
Scanner myVar = new Scanner(System.in);
You can now read in different kinds of input data that the user enters. Here are some methods
available through the Scanner class:
nextByte() - Read a byte
nextShort() – Read a short
nextInt() – Read an int
nextLong() – Read a long
nextFloat() – Read a float
nextDouble() – Read a double
nextBoolean() – Read a Boolean
nextLine() – Read a complete line
next() – Read a word
Example of a program used to get user input:
import java.util.Scanner;

class MyClass {
public static void main(String[] args) {
Scanner myVar = new Scanner(System.in);
System.out.println(myVar.nextLine());
}
}
This will wait for the user to input something and print that input.
Scanner looks for the next token in the stream, and it does not care if it is a space or a new line.
The valueOf method returns the relevant Number object holding the value of the argument
passed. The argument can be a primitive data type, String, etc. It is a static method, and can take
two arguments: one is a String and the other a radix, the number of digits utilized in a positional
number system.
public static void main(String args[]) {
Integer x =Integer.valueOf(9);
Double c = Double.valueOf(5);
Float a = Float.valueOf("80");
Integer b = Integer.valueOf("444",16);
//Output:
System.out.println(x); // 9
System.out.println(c); // 5.0
System.out.println(a); // 80.0
System.out.println(b); // 1092
}
See:
https://github.com/makotogo/Scanner101/blob/master/src/com/makotogo/learn/
ChangeJarAdvanced.java
Conditionals and Loops
Conditional statements are used to perform different actions based on different conditions. The if
statement is one of the most frequently used conditional statements.
if (condition) {
//Executes when true
} else if(condition) {
//Executes when true
} else { //The else and elif are optional
//Executes when all other if statements are false
}
Can use any of the standard comparison operators to form the condition:
<, >, !=, ==, <=, >=
A single equal sign is the assignment operator, use == to test for equality.
If statements can be nested.

Logical operators are used to combine multiple conditions. For example you can use the AND
logical operator (&&) rather than nested if statements for multiple conditions.
The AND operator (&&) checks if all of the conditions is true.
if (age > 18 && money > 500) {
System.out.println(“Welcome!”);
}
Only true if both operands are true.
The OR operator (||) checks if any one of the conditions is true.
if (age > 18 || money > 500) {
System.out.println(“Welcome!”);
}
Only true if any of the operands are true.
The NOT (!) logical operator is used to reverse the logical state of its operand. If a condition is
true, the NOT logical operator will make it false.
if (!(age > 18)) {
System.out.println(“Too Young”);
}
Means if age is NOT greater than 18
Java ternary operator syntax:
result = testStatement ? value1 : value2;
If the first operand is true than java ternary returns second operand else it returns third operand.
public class EvenOrOdd {
public static String even_or_odd(int number) {
return (number & 1) == 0 ? "Even" : "Odd";
}
}

This function returns whether the number is even or odd.


A switch statement tests a variable for equality against a list of values. Each value is called a case,
and the variable being switched on is checked for each case. Syntax:
switch (expression) {
case value1:
//Statements
break; //optional
case value2:
//Statements
break; //optional
//You can have any number of case statements
default: //optional
//Statements
}
When the variable being switched on is equal to a case, the statements following that case will
execute until a break statement is reached.
When a break statement is reached, the switch terminates, and the flow of control jumps to the
next line after the switch statement.
Not every case needs to contain a break. If no break appears, the flow of control will fall through to
subsequent cases until a break is reached.
Each case is followed by the comparison value and a colon.
The default case can be used for performing a task when none of the cases is matched. No break
is needed in the default case; it is always the last statement in the switch.
A switch works with byte, short, char and int primitive data types. It also works with enumerated
types (enables for a variable to be a set of predefined constants), String class, and a few others.
Enum types are used when you need to represent a fixed set of constants:
Public enum Day { SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THRUSDAY, FIRDAY,
SATURDAY }
The enum declaration defines a class, called a enum type. The class body can include methods
and other fields. The compiler automatically adds some special methods to it when it is created.

A loop statement allows to repeatedly execute a statement or group of statements.


A while loop statement repeatedly executes a target statement as long as a given condition is true.
while(x>0) {
System.out.println(x);
x--;
} //this will output 3 2 1
The while loops check for the condition x>0. If it is true, it executes the statements within its body.
Then it checks for the statement again and repeats. x--decrements x each time the loop runs, and
makes the loop stop when x reaches 0. Otherwise it would run forever.
In a while loop when the expression is tested and the result is false, the loop body is skipped and
first statement after the while loop is executed.
while(x<10) {
System.out.println(x);
X++;
}
System.out.println(“Loop ended”);
// prints: 6 7 8 9 Loop ended
A for loop allows you to efficiently write a loop that needs to execute a specific number of times.
Syntax:
for (initialization; condition; increment/decrement) {
statement(s)
}
Initialization: Expression executes only once during the beginning of loop.
Condition: Is evaluated each time the loop iterates. The loop executes the statement repeatedly,
until this condition returns false.
Increment/Decrement: Executes after each iteration of the loop.

for(int x=1; x<=5; x++) {


System.out.println(x);
} // Outputs: 1 2 3 4 5
Initializes x to the value of 1, and repeatedly prints the value of x, until the condition x<= becomes
false. On each iteration, the statement x++ is executed, incrementing x by one.
You can have any type of condition and any type of increment statements in the for loop. The
example below prints only the even values between 0 and 10:
for(int x=0; x<=10; x=x+2) {
System.out.println(x);
} // prints 0 2 4 6 8 10
A for loop is best when the starting and ending numbers are known.
A do…while loop is similar to a while loop, except that a do…while loop is guaranteed to execute
at least one time. Example:
do {
System.out.println(x);
x++;
} while(x<5); // prints 1 2 3 4
The condition appears at the end of the loop, so the statements in the loop execute once before it
is tested.
The break and continue statements change the loop’s execution flow.
The break statement terminates the loop and transfers execution to the statement immediately
following the loop.
The continue statement causes the loop to skip the remainder of its body and then immediately
retest its condition prior to reiterating. In other words, it makes the loop skip to its next iteration.
Arrays
An array is a collection of variables of the same type. You can store a list of variables in an array.
To declare an array, you need to define the type of the elements with square brackets:
int[] arr;
The name of the array is arr. The type of elements is int. Use the keyword new to define the
array’s capacity:
int[] arr = new int[5];
Declares an array of 5 integers. In an array, the elements are ordered and each has a specific and
constant position, which is called an index. To reference elements in an array, type the name of
the array followed by the index position within a pair of square brackets.
arr[2] = 42; //Assigns the value of 42 to the index 2 inside array ‘arr’
First element’s index is 0.
Java provides a shortcut for instantiating arrays of primitive types and strings. You can use an
array literal if you already know what to insert:
String[] myNames = {“A”,”B”,”C”,”D”};
System.out.println(myNames[2]); //Outputs “C”
Place the values in a comma-separated list, enclosed in curly braces.
You can access the length of an array via its length property:
System.out.println(intArr.length); //Outputs length of array ‘intArr’

Using loops we can calculate the sum of all elements in an array. The for loop is the most used
loop when working with arrays, so we can use the length of the array to determine how many
times to run the loop.
int[] myArr = {6,42,3,7}; //Initialise array
int sum=0; //initialise sum
for(int x=0; x<myArr.length; x++) { //loop through each item in the
array
sum+=myArr[x]; //add each item to sum
}
System.out.println(sum); //Outputs 58
Condition is x<myArr.length, as the last element’s index is myArr.length-1
The enhanced for loop, or “for each” loop, is used to traverse elements in arrays. The advantages
are that it eliminates the possibility of bugs and makes the code easier to read.
int[] primes = {2,3,5,7};
for (int t: primes) {
System.out.println(t);
} //Outputs 2 3 5 7
The enhanced for loop declares a variable of a type compatible with the elements of the array
being accessed. The variable will be available within the for block, and its value will be the same
as the current array element. So, on each iteration of the loop, the variable t will be equal to the
corresponding element in the array.
Multidimensional arrays are arrays that can contain other arrays. The two-dimensional array is the
most basic multi-dimensional array. To create multidimensional arrays, place each array within its
own set of square brackets:
int[][] sample = {{1,2,3},{4,5,6}};
This declares an array with two arrays as its elements.
To access an element in the two-dimensional array, provide two indexes, one for the array, and
another for the element inside that array.
System.out.println(sample[1][0]);
The array’s two indexes are called the row index and column index.
You can get and set a multidimensional array’s elements using the same pair of square brackets.
In Java, you’re not limited to just two-dimensional arrays. Arrays can be nested within arrays to as
many levels as your program needs. All array members must be of the same type.
Classes and Objects
Object-Oriented Programming (OOP) is a programming style that is intended to make thinking
about programming closer to thinking about the real world.
In OOP, each object is an independent unit with a unique identity, just as objects in the real world
are. Objects also have characteristics, which are used to describe them. For example, a car can
be red or blue. These characteristics are also called attributes. An attribute describes the current
state of an object. In the real world, each object behaves in its own way. The car moves, phone
rings, etc. The same applies to objects: behaviour is specific to the object’s type.
In summary, each object has three dimensions: Identity, attributes and behaviour. Attributes
describe the object’s current state, and what the object is capable of doing is demonstrated
through the object’s behaviour.

A class describes what the object will be, but is separate from the object itself. Classes can be
described as blueprints, descriptions, or definitions for an object. You can use the same class as a
blueprint for creating multiple objects. Each class has a name, and each is used to define
attributes and behaviour. An object is an instance of a class.

Methods define behaviour. A method is a collection of statements that are grouped together to
perform an operation. System.out.println() is an example of a method.
Static void sayHello() {
System.out.println(“Hello World!”);
}

public static void main(String[] args) {


sayHello();
} // Outputs “Hello World!”
The code above declares a method called “sayHello”, which is called in main.
To call a method, type its name and follow the name with a set of parentheses.
You can call a method as many times as necessary. When a method runs, the code jumps down
to where the method is defined, executes the code inside of it, then goes back and proceeds to the
next line.
Parameters are data that a method can take in when it is called. These are written in the method’s
parentheses.
Static void sayHello(String name) {
System.out.println(“Hello “+name);
}
sayHello() has been modified to take a String called name as a parameter, which is used in the
method’s body. Separate parameters with commas. Advantage of methods include code reuse
and allows for parameters.
The return keyword can be used to return a value.
static int sum(int val1, int val2) {
return val1+val2;
}
In the method definition, we defined the return type before we defined the method name.
When you do not need to return any value from your method, use the keyword void. This means
the method will not return anything.
A method can have one type of parameter and return another, different type. For example it can
take two doubles and return an int.
public class Animal {
void bark() {
System.out.println(“Woof-Woof”);
}
}
Declaring a simple method in the class Animal.
In order to use the class and its methods, we need to declare an object of that class.
class MyClass {
public static void main(String[] args) {
Animal dog = new Animal();
dog.bark();
}
} // Outputs “Woof-Woof”
We have created a new object of our class. We can call its bark() method, using the name of the
object and a dot. The dot notation is used to access the object’s attributes and methods.
A class has attributes and methods. The attributes are basically variables within a class.
public class Vehicle {
int maxSpeed;
int wheels;
String color;
double fuelCapacity;

void horn() {
System.out.println(“Beep!”);
}
}
maxSpeed, wheels, color, and fuelCapacity are the attributes of our Vechicle class, and horn() is
the only method.
We can then create multiple objects objects of our Vehicle class, and use dot syntax to access
attributes and methods.
class MyClass {
public static void main(String[] args) {
Vehicle v1 = new Vehicle();
Vehicle v2 = new Vehicle();
v1.color = “red”;
v2.horn();
}
}
The public keyword in front of main method is an access modifier, meaning that it is used to set
the level of access. You can use access modifiers for classes, attributes, and methods.
For classes, the available modifiers are public or default (left blank), as described below:
public: class is accessible by any other class.
default: class is accessible only by classes in the same package.
The following choices are available for attributes and methods:
default: A variable or method declared with no access control modifier is available to any other
class in the same package.
public: Accessible from any other class.
protected: Provides the same access as the default access modifier, with the addition that
subclasses can access protected methods and variables of the superclass.
private: Accessible only within the declared class itself.

Public visibility means that this method ca be accessed anywhere in the program so long as you
have an instance of this class to call it from.
Private visibility means that his method can’t be accessed anywhere other than inside of this class.
Protected visibility means that this method can only be accessed inside of this package and from
subclasses of this class.
Default visibility means that this method can only be accessed inside of this package.
public class Vehicle {
private int maxSpeed;
private int wheels;
private String color;
private double fuelCapacity;

public void horn() {


System.out.println(“Beep!”);
}
}
It is best practice to keep the variables within a class private. The variables are accessible and
modified using Getters and Setters.
Getters and Setters are used to effectively protect your data. For each variable, the get method
returns its value, while the set method sets the value.
Getters start with get, followed by the variable name, with the first letter of the variable name
capitalized.
Setters start with set, followed by the variable name, with the first letter of the variable name
capitalized.
public class Vechicle {
private String color;
// Getter
public String getColor() {
return color;
}
// Setter
public void setColor(String c) {
this.color = c;
}
}
The keyword this is used to refer to the current object. Basically, this.color is the color attribute of
the current object.
Once our getter and setter have been defined, we can use it in our main:
public static void main(String[] args) {
Vehicle v1 = new Vehicle();
v1.setColor(“Red”);
System.out.println(v1.getColor());
} //Outputs “Red”
Getters and setters allow us to have control over the values. For example by validating.
Getters and setters are the fundamental building blocks for encapsulation.

Constructors are special methods invoked when an object is created and are used to initialize
them. A constructor can be used to provide initial values for object attributes.
- A constructor name must be the same as its class name.
- A constructor must have no explicit return type.
public class Vehicle {
private String color;
Vehicle() {
color = "Red";
}
}
The Vehicle() method is the constructor of our class, so whenever an object or that class is
created, the color attribute will be set to “Red”.
A constructor can also take parameters to initialize attributes.
public class Vehicle {
private String color;
Vehicle(String c) {
color = c;
}
}
You can think of constructors as methods that will set up your class be default, so you don’t need
to repeat the same code every time.
The constructor is called when you create an object using the new keyword.
public class MyClass {
public static void main(String[] args) {
Vehicle v = new Vehicle("Blue");
}
}
This will call the constructor, which will set the color attribute to “Blue”
A single class can have multiple constructors with different numbers of parameters. The setter
methods inside the constructors can be used to set the attribute values.
public class Vehicle {
private String color;

Vehicle() {
this.setColor("Red");
}
Vehicle(String c) {
this.setColor(c);
}
// Setter
public void setColor(String c){
this.color = c;
}
}
The class above has two constructors; one without any parameters setting the color attribute to a
default value of “Red”, and another constructor that accepts a parameter and assigns it to the
attribute.
Now, we can use the constructors to create objects of our class.
//color will be "Red"
Vehicle v1 = new Vehicle();
//color will be "Green"
Vehicle v2 = new Vehicle("Green");
Java automatically provides a default constructor, so all classes have a constructor whether one is
specifically defined or not.
Values types are the basic types, and include byte, short, int, long, float, double, boolean, and
char. These data types store the values assigned to them in the corresponding memory locations.
So, when you pass them to a method, you basically operate on the variable’s value, rather than on
the variable itself.
public class MyClass {
public static void main(String[] args) {
int x = 5;
addOneTo(x);
System.out.println(x);
}
static void addOneTo(int num) {
num = num + 1;
}
} // Outputs "5"
The method from the example above takes the value of its parameter, which is why the original
variable is not affected and 5 remains as its value.
A reference type stores a reference to the memory location where the corresponding data is
stored. When you create an object using the constructor, you create a reference variable. For
example, consider having a Person class defined:
public class MyClass {
public static void main(String[] args) {
Person j;
j = new Person("John");
j.setAge(20);
celebrateBirthday(j);
System.out.println(j.getAge());
}
static void celebrateBirthday(Person p){
p.setAge(p.getAge()+1);
}
} //Outputs "21"
The method makeBrithday takes a Person object as its parameter, and increments its attribute.
Because j is a reference type, the method affects the object itself, and is able to change the actual
value of its attribute. Arrays and Strings are also reference data types.
The JDK defines a number of useful classes, one of the being the Math class, which provides
predefined methods for mathematical operations. You do not need to create an object of the Math
class to use it. To access it, just type in Math. And the corresponding method.
Math.abs() returns the absolute value of its parameter.
Math.ceil() rounds a floating point value up to the nearest integer value. Returns as a double.
Math.floor() rounds a floating point value down to the nearest integer value. Returns as a double.
Math.max() returns the largest of its parameters.
Math.min() returns the smallest of its parameters.
Math.pow() takes two parameters and returns the first parameter to the power of the second
parameter.
Math.sqrt() returns the correctly rounded positive square root of a double
Math.sin() returns the trigonometric sin of an angle
Math.cos() returns the trigonometric cosine of an angle
Math.tan() returns the trigonometric tangent of an angle
public class MyClass {
public static void main(String[] args) {
int a = Math.abs(10); // 10
int b = Math.abs(-20); // 20
double c = Math.ceil(2.7); // 3.0
double d = Math.ceil(2.2); // 3.0
double e = Math.floor(2.7); // 2.0
double f = Math.floor(2.2); // 2.0
int g = Math.max(10,20); // 20
int h = Math.min(10,20); // 10
double i = Math.pow(2,3); // 8.0
double j = Math.sqrt(25); // 5.0
}
}
When you declare a variable or a method as static, it belongs to the class, rather than to a specific
instance. This means that only one instance of a static member exists, even if you create multiple
objects of the class, of if you don’t create any. It will be shared by all objects.
public class Counter {
public static int COUNT=0;
Counter() {
COUNT++;
}
}
The COUNT variable will be shared by all other objects of that class.
Now, we can crate objects of our Counter class in main, and access the static variable.
public class MyClass {
public static void main(String[] args) {
Counter c1 = new Counter();
Counter c2 = new Counter();
System.out.println(Counter.COUNT);
}
} //Outputs "2"
The output is 2, because the COUNT variable is static and gets incremented by one each time a
new object of the Counter class is created. In the code above, we created 2 objects. You can also
access the static variable using any object of that class, such as c1.COUNT.
It is common practice to use upper case when naming a static variable.
The same concept applies to static methods:
public class Vehicle {
public static void horn() {
System.out.println("Beep");
}
}
Now, the horn method can be called without creating an object.
public class MyClass {
public static void main(String[] args) {
Vehicle.horn();
}
}
Another example of static methods are those of the Math class, which is why you can call them
without creating a Math object. The main method must always be static.
final is used to mark a variable constant, so that it can be assigned only once.
public class MyClass {
public static final double PI = 3.14;
public static void main(String[] args) {
System.out.println(PI);
}
}
PI is now a constant. Any attempt to assign it a value will cause an error.
Methods and classes can also be marked final. This serves to restrict methods so that they can’t
be overridden and classes so that they can’t be subclassed.
Packages are used to avoid name conflicts and to control access to classes. A package can be
defined as a group made up of similar types of classes, along with sub-packages.
To create package in Java click on your src directory and click New->Package. Give it a name and
finish. You will notice that the new package appears in the project directory. Now you can move
and create classes inside that package. We have moved our Vehicle, Counter and Animal classes
to package samples.
When you move/create a class in your package, the following code will appear at the top of the list
of files.
package samples;
This indicates the package to which the class belongs. Now, we need to import the classes that
are inside a package in our main to be able to use them. The following example shows how to use
the Vehicle class of the samples package.
import samples.Vehicle;

class MyClass {
public static void main(String[] args) {
Vehicle v1 = new Vehicle();
v1.horn();
}
}
Two major results occur when a class is placed in a package. First, the name of the package
becomes a part of the name of the class. Second, the name of the package must match the
directory structure where the corresponding class file resides.
Use a wildcard to import all classes in a package. For example, import samples.* will import all
classes in the samples package.
More on Classes
There are 4 core concepts in OOP: encapsulation, inheritance, polymorphism, and abstraction.
The idea behind encapsulation is to ensure that implementation details are not visible to users.
The variables of one class will be hidden from the other classes, accessible only through the
methods of the current class. This is called data hiding.
To achieve encapsulation in Java, declare the class’ variables as private and provide public setter
and getter methods to modify and view the variables’ values.
class BankAccount {
private double balance=0;
public void deposit(double x) {
if(x>0) {
balance+=x;
}
}
}
This implementation hides the balance variable, enabling access to it only through the deposit
method, which validates the amount to be deposited before modifying the variable.
In summary, encapsulation provides the following benefits:
- Control of the way data is accessed or modified
- More flexible and easily changed code
- Ability to change one part of the code without affecting other parts.
Inheritance is the process that enables one class to acquire the properties of another. With
inheritance, the information is placed in a more manageable, hierarchical order.
The class inheriting the properties of another is the subclass; the class whose properties are
inherited is the superclass.
To inherit from a class, use the extends keyword.
This example shows how to have the class Dog to inherit from the class Animal:
class Dog extends Animal {
// some code
}
Here, Dog is the subclass, and Animal is the superclass.

When one class is inherited from another class, it inherits all of the superclass’ non-private
variables and methods.
class Animal {
protected int legs;
public void eat() {
System.out.println("Animal eats");
}
}

class Dog extends Animal {


Dog() {
legs = 4;
}
}
As you can see the Dog class inherits the protected legs variable from the Animal class.
We can now declare a Dog object and call the eat method of its superclass:
class MyClass {
public static void main(String[] args){
Dog d = new Dog():
d.eat();
}
}
Recall the protected access modifier, which makes the members visible only to the subclasses.
Constructors are not member methods, and so are not inherited by subclasses. However, the
constructor of the superclass is called when the subclass is instantiated.
class A {
public A() {
System.out.println("New A");
}
}
class B extends A {
public B() {
System.out.println("New B");
}
}
class Program {
public static void main(String[] args){
B obj = new B();
}
}
// Outputs "New A" "New B"
You can access the superclass from the subclass using the super keyword. For example,
super.var accesses the var member of the superclass.
Polymorphism, which refers to the idea of “having many forms”, occurs when there is a hierarchy
of classes related to each other through inheritance. A call to a member method will cause a
different implementation to be executed, depending on the type of the object invoking the method.
Here is an example: Dog and Cat are classes that inherit from the Animal class. Each class has its
own implementation of the makeSound() method.
class Animal {
public void makeSound() {
System.out.println("Grr...");
}
}
class Cat extends Animal {
public void makeSound() {
System.out.println("Meow");
}
}
class Dog extends Animal {
public void makeSound() {
System.out.println("Woof");
}
}
As all Cat and Dog objects are Animal objects, we can do the following in main:
public static void main(String[] args){
Animal a = new Dog();
Animal b = new Cat();
}
We’ve created two reference variables of type Animal, and pointed them to the Cat and Dog
objects. Now we can call the makeSound() methods.
a.makeSound();
//Outputs "Woof"
b.makeSound();
//Outputs "Meow"
As the reference variable a contains a Dog object, the makeSound() method of the Dog class will
be called, same applies for b variable.
This demonstrates that you can use the Animal variable without actually knowing that it contains
an object of the subclass. This is very useful when you have multiple subclasses of the
superclass.
The super keyword is a reference variable which is used to refer to immediate parent class object.
Whenever you create the instance of subclass, an instance of parent class is created implicitly
which is referred by super reference variable.
super is used to refer to immediate parent class instance variable:

1. class Animal{  //Animal and Dog both have a common property, super.color can let Dog access
2. String color="white";  //The color field of its parent property
3. }  
4. class Dog extends Animal{  
5. String color="black";  
6. void printColor(){  
7. System.out.println(color);//prints color of Dog class  
8. System.out.println(super.color);//prints color of Animal class  
9. }  
10. }  
11. class TestSuper1{  
12. public static void main(String args[]){  
13. Dog d=new Dog();  
14. d.printColor();   // Outputs: ‘black’ ‘white’
15. }}  

super can be used to invoke parent class method:

1. class Animal{  
2. void eat(){System.out.println("eating...");}  
3. }  
4. class Dog extends Animal{  
5. void eat(){System.out.println("eating bread...");}  
6. void bark(){System.out.println("barking...");}  
7. void work(){  
8. super.eat();   // This calls the parent class eat() method if it exists
9. bark();  
10. }  
11. }  
12. class TestSuper2{  
13. public static void main(String args[]){  
14. Dog d=new Dog();  
15. d.work();  
16. }}   // Output ‘eating…’ ‘barking…’
super is used to invoke parent class constructor:

1. class Animal{  
2. Animal(){System.out.println("animal is created");}  
3. }  
4. class Dog extends Animal{  
5. Dog(){  
6. super();  // calls the parent constructor method
7. System.out.println("dog is created");  
8. }  
9. }  
10. class TestSuper3{  
11. public static void main(String args[]){  
12. Dog d=new Dog();  
13. }}  // Output: ‘animal is created’ ‘dog is created’

super() is added in each class constructor automatically by compiler if there is no super() or this()
super() is added as the first statement.
Method overriding is when a subclass can define a behaviour that’s specific to the subclass type,
meaning that a subclass can implement a parent class method based on its requirement.
Method overriding, in OOP, is a language 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
class. So when you call a specific method with zero parameters it will select one of the methods
that alternatives that have zero parameters.
class Animal {
public void makeSound() {
System.out.println("Grr...");
}
}
class Cat extends Animal {
public void makeSound() {
System.out.println("Meow");
}
}
In the code above, the Cat class overrides the makeSound() method of its superclass Animal.
Rules for Method Overriding:
- Should have the same return type and arguments
- The access level cannot be more restrictive than the overridden method’s access level
- A method declared final or static cannot be overridden
- If a method cannot be inherited, it cannot be overridden
- Constructors cannot be overridden.
Method overriding is also known as runtime polymorphism (means that a call to a member method
will cause a different method to be executed depending on the type of object that invokes the
method)
If subclass has the same method as declared in the parent class, it is known as method overriding
in Java. In other words if a subclass provides the specific implementation of the method that has
been declared by one of its parent class, it is known as method overriding.
Method overriding is used to provide the specific implementation of a method which is already
provided by its superclass. Method overriding is used for runtime polymorphism.
Rules: The method must have the same name and the same parameters as its parent class.
There must be an IS-A relationship (inheritance)
Static methods cannot be overridden, because the static method is bound with class whereas
instance method is bound with an object. Static belongs to the class area, and an instance
belongs to the heap area. The access level cannot be more restrictive than the parent method.
If the superclass method does not declare an exception, subclass overridden method cannot
declare the checked exception.
Method overloading is when methods have the same name, but different parameters. This can be
very useful when you need the same method functionality for different types of parameters.
The following example illustrates a method that returns the maximum of its two parameters.
int max(int a, int b) {
if (a>b) {
return a;
} else {
return b;
}
}
The method shown above will only work for parameters of type integer.
However we might want to use it for doubles, as well. For that you need to overload the max
method:
double max(double a, double b) {
if (a>b) {
return a;
} else {
return b;
}
}
Now our max method will also work with doubles. An overloaded method must have a different
argument list; the parameters should differ in their type, number, or both.
Another name for method overloading is compile-time polymorphism.
Method overloading is when a class has multiple methods with the same name but having different
parameters. If we have to perform only one operation, having same name of methods increases
the readability of the program. Suppose you have to perform addition of the given numbers but
there can be any number of arguments, if you write the method such as a(int,int) for two
parameters, and b(int,int,int) for three parameters than it may be difficult for you as well as other
programmers to understand the behaviour of the method because its name differs. Method
overloading makes it more readable. The main advantage is that it increases the readability of the
program. There are two different ways to overload the method in Java, by changing the number of
arguments or by changing the data type. However it is not possible by changing the return type of
the method only. Method overloading is not possible by changing the return type of the method
only because of ambiguity, the quality of being open to more than one interpretation.
By method overloading you can have any number of main methods in a class by method
overloading. But JVM calls main() method which receives string array as arguments only.
One type is promoted to another implicitly if no matching datatype is found. Let’s understand the
concept by the figure below:
byte can be promoted to:
short, int, long, float or double
short can be promoted to:
int, long, float, or double
char can be promoted to:
int, long, float, or double
int can be promoted to:
long, float or double
long can be promoted to:
float or double
float can be promoted to:
double
1. class OverloadingCalculation1{  
2.   void sum(int a,long b){System.out.println(a+b);}  
3.   void sum(int a,int b,int c){System.out.println(a+b+c);}  
4.   
5.   public static void main(String args[]){  
6.   OverloadingCalculation1 obj=new OverloadingCalculation1();  
7.   obj.sum(20,20);//now second int literal will be promoted to long  
8.   obj.sum(20,20,20);  
9.   
10.   }  
11. }  //Outputs: 40 60

If there are matching type arguments in the method, type promotion is not performed.
If there are no matching type arguments in the method, and each method promotes similar
number of arguments, there will be ambiguity.

1. class OverloadingCalculation3{  
2.   void sum(int a,long b){System.out.println("a method invoked");}  
3.   void sum(long a,int b){System.out.println("b method invoked");}  
4.   
5.   public static void main(String args[]){  
6.   OverloadingCalculation3 obj=new OverloadingCalculation3();  
7.   obj.sum(20,20);//now ambiguity  
8.   }  

No Method Overloading Method Overriding


.

1) Method overloading is used to increase the readability of Method overriding is used to provide the
the program. specific implementation of the method
that is already provided by its super
class.

2) Method overloading is performed within class. Method overriding occurs in two classes
that have IS-A (inheritance) relationship

3) In case of method overloading, parameter must be In case of method overriding, parameter


different. must be same.

4) Method overloading is the example of compile time Method overriding is the example of run
polymorphism. time polymorphism.

5) In java, method overloading can't be performed by Return type must be same or covariant
changing return type of the method only. Return type can in method overriding.
be same or different in method overloading. But you must
have to change the parameter.

9. }  //Outputs: Compile Time Error


In Compile time Polymorphism, call is resolved by the compiler. In Run time Polymorphism, call
is not resolved by the compiler.
Covariant return type refers to return type of an overriding method. It allows to narrow down return
type of an overridden method without any need to cast the type or check the return type. Covariant
return type works only for non-primitive return types.
Data abstraction provides the outside world with only essential information, in a process of
representing essential features without including implementation details. A good real-world
example is a book. When you hear the term book, you don’t know the exact specifics, such as the
page count, the color, or the size, but you do understand the idea, or abstraction, of a book.
The concept of abstraction is that we focus on essential qualities, rather than the specific
characteristics of one particular example.
In Java, abstraction is achieved using abstract classes and interfaces.
An abstract class is defined using the abstract keyword.
- If a class is declared abstract is cannot be instantiated, cannot create objects of that type
- To use an abstract class, you have to inherit it from another class.
- Any class that contains an abstract method should be defined as abstract.
An abstract method is a method that is declared without an implementation, without braces, and
followed by a semicolon: abstract void walk();
For example, we can defined our Animal class as abstract:
abstract class Animal {
int legs = 0;
abstract void makeSound();
}
The makeSound method is also abstract, as it has no implementation in the superclass.
We can inherit from the Animal class and define the makeSound() method for the subclass:
class Cat extends Animal {
public void makeSound() {
System.out.println("Meow");
}
}
Every Animal makes a sound, but each has a different way to do it. That’s why we define an
abstract class Animal, and leave the implementation of how they make sounds to the subclasses.
This is used when there is no meaningful definition for the method in superclass.
A class which is declared with the abstract keyword is known as an abstract class in Java. It can
have abstract and non-abstract methods. Abstraction is the process of hiding the implementation
details and showing only functionality to the user. It shows only essential things to the user and
hides the internal details, for example with sending SMS you don’t know the internal processing
about message delivery. Abstraction lets you focus on what the object does instead of how it does
it. You can achieve abstraction in java with either an abstract class, 0 to 100%, or an Interface,
100%.
A abstract class is a class which is declared as abstract. It can have abstract and non-abstract
methods. It needs to be extended and its method implemented. It cannot be instantiated.
An abstract class must be declared with an abstract keyword.
It can have abstract and non-abstract methods.
It cannot be instantiated.
It can have constructors and static methods.
It can have final methods which will force the subclass not to change the body of the method.
A method which is declared as abstract and does not have implementation is known as an
abstract method.
abstract void printStatus(); //no method body and abstract
In this example, Shape is the abstract class, and its implementation is provided by the Rectangle
and Circle classes. Mostly, we don’t know about the implementation class, which is hidden to end
user, and an object of the implementation class is provided by the factory method. A factory
method is a method that returns the instance of the class.

1. abstract class Shape{  
2. abstract void draw();  
3. }  
4. //In real scenario, implementation is provided by others i.e. unknown by end user  
5. class Rectangle extends Shape{  
6. void draw(){System.out.println("drawing rectangle");}  
7. }  
8. class Circle1 extends Shape{  
9. void draw(){System.out.println("drawing circle");}  
10. }  
11. //In real scenario, method is called by programmer or user  
12. class TestAbstraction1{  
13. public static void main(String args[]){  
14. Shape s=new Circle1();//In a real scenario, object is provided through method
15. s.draw();  
16. }  
17. }  

An abstract class can have a data member, abstract method, method body, constructor and even
main() method. If there is an abstract method in a class, that class must be abstract. If you are
extending an abstract class that has an abstract method, you must either provide the
implementation of the method or make this class abstract.
The abstract class can also be used to provide some implementation of the interface.

An interface is a completely abstract class that contains only abstract methods.


Some specifications for interfaces:
- Defined using the interface keyword.
- May contain only static final variables.
- Cannot contain a constructor because interfaces cannot be instantiated.
- Interfaces can extend other interfaces.
- A class can implement any number of interfaces.
An example of a simple interface:
interface Animal {
public void eat();
public void makeSound();
}
Interfaces have the following properties:
- An interface is implicitly abstract. You do not need to use the abstract keyword while declaring an
interface.
- Each method in an interface is also implicitly abstract, so the abstract keyword is not needed.
- Methods in an interface are implicitly public.
A class can inherit from just one superclass, but can implement multiple interfaces.

Use the implements keyword to use an interface with your class.


class Cat implements Animal {
public void makeSound() {
System.out.println("Meow");
}
public void eat() {
System.out.println("omnomnom");
}
}
When you implement an interface, you need to override all of its methods.
An interface in java is a blueprint of a class. It has static constraints and abstract methods. The
interface in Java is a mechanism to achieve abstraction. There can only be abstract methods in
the Java interface, not method body. It is used to achieve abstraction and multiple inheritance in
Java. In other words, you can say that interfaces can have abstract methods and variables. It
cannot have a method body. Java Interface also represents the IS-A relationship. Like the abstract
class it cannot be instantiated. It can have default and static methods and can have private
methods.
Interfaces are used to achieve abstraction, to support the functionality of multiple inheritance and it
can be used to achieve loose coupling.
An interface is declared using the interface keyword. It provides total abstraction; means all the
methods in an interface are declared with the empty body, and all fields are public, static and final
by default. A class the implements an interface must implement all the methods declared in the
interface.

1. nterface <interface_name>{  
2.       
3.     // declare constant fields  
4.     // declare methods that abstract   
5.     // by default.  
6. }  

The Java compiler adds public and abstract keywords before the interface method. Moreover, it
adds public, static and final keywords before data members. In other words, Interface fields are
public, static and final by default, and the methods are public and abstract.

A class extends another class, an interface extends another interface but a class implements an
interface:
Printable interface has only one method, and its implementation is provided in the A6 class.

1. interface printable{  
2. void print();  
3. }  
4. class A6 implements printable{  
5. public void print(){System.out.println("Hello");}  
6.   
7. public static void main(String args[]){  
8. A6 obj = new A6();  
9. obj.print();  
10.  }  // Outputs Hello
11. }  

In this example, the Drawable interface has only one method. Its implementation is provided by
Rectangle and Circle classes. In a real scenario, an interface is defined by someone else, but its
implementation is provided by different implementation providers. Moreover, it is used by someone
else. The implementation part is hidden by the user who uses the interface.

1. //Interface declaration: by first user  
2. interface Drawable{  
3. void draw();  
4. }  
5. //Implementation: by second user  
6. class Rectangle implements Drawable{  
7. public void draw(){System.out.println("drawing rectangle");}  
8. }  
9. class Circle implements Drawable{  
10. public void draw(){System.out.println("drawing circle");}  
11. }  
12. //Using interface: by third user  
13. class TestInterface1{  
14. public static void main(String args[]){  
15. Drawable d=new Circle();//In real scenario, object is provided by method e.g. getDrawable()  
16. d.draw();  
17. }}  //Output: drawing circle

If a class implements multiple interfaces, or an interface extends multiple interfaces, it is known as


multiple inheritance.
You cannot extend multiple classes however like:
Class Dog extends Animal, Canine{} //This gives compile time error
Example:

1. interface Printable{  
2. void print();  
3. }  
4. interface Showable{  
5. void show();  
6. }  
7. class A7 implements Printable,Showable{  
8. public void print(){System.out.println("Hello");}  
9. public void show(){System.out.println("Welcome");}  
10.   
11. public static void main(String args[]){  
12. A7 obj = new A7();  
13. obj.print();  
14. obj.show();  
15.  }  
16. }  //Output: Hello Welcome

Multiple inheritance is not supported through class in java, but is possible by interface, why?
Multiple inheritance is not supported in the case of class because of ambiguity. However with
interfaces there is no ambiguity, this is because its implementation is provided by the
implementation class. For example:

1. interface Printable{  
2. void print();  
3. }  
4. interface Showable{  
5. void print();  
6. }  
7.   
8. class TestInterface3 implements Printable, Showable{  
9. public void print(){System.out.println("Hello");}  
10. public static void main(String args[]){  
11. TestInterface3 obj = new TestInterface3();  
12. obj.print();  
13.  }  
14. }   //Output: Hello

As you can see in the above example, Printable and Showable have the same methods but its
implementation is provided by class TestTnterface1, so there is no ambiguity.
A class implements an interface, but one interface extends another interface.

1. interface Printable{  
2. void print();  
3. }  
4. interface Showable extends Printable{  
5. void show();  
6. }  
7. class TestInterface4 implements Showable{  
8. public void print(){System.out.println("Hello");}  
9. public void show(){System.out.println("Welcome");}  
10.   
11. public static void main(String args[]){  
12. TestInterface4 obj = new TestInterface4();  
13. obj.print();  
14. obj.show();  
15.  }  
15. }   //Output: Hello Welcome

We can have the method body in interface. But we need to make it default method. Like:

1. interface Drawable{  
2. void draw();  
3. default void msg(){System.out.println("default method");}  
4. }  
5. class Rectangle implements Drawable{  
6. public void draw(){System.out.println("drawing rectangle");}  
7. }  
8. class TestInterfaceDefault{  
9. public static void main(String args[]){  
10. Drawable d=new Rectangle();  
11. d.draw();  
12. d.msg();  
13. }}  //Output: drawing rectangle default method
We can have static method in an interface. Like:

1. interface Drawable{  
2. void draw();  
3. static int cube(int x){return x*x*x;}  
4. }  
5. class Rectangle implements Drawable{  
6. public void draw(){System.out.println("drawing rectangle");}  
7. }  
8.   
9. class TestInterfaceStatic{  
10. public static void main(String args[]){  
11. Drawable d=new Rectangle();  
12. d.draw();  
13. System.out.println(Drawable.cube(3));  
14. }}  //Output: drawing rectangle 27

What is marker or tagged interface?


An interface which has no member is known as a marker or tagged interface, for example,
Serializable, Cloneable, Remote, etc. They are used to provide some essential information to the
JVM so that JVM may perform some useful operation.

1. //How Serializable interface is written?  
2. public interface Serializable{  
3. }  

An interface can have another interface nested inside, known as a nested interface. Like:

1. interface printable{  
2.  void print();  
3.  interface MessagePrintable{  
4.    void msg();  
5.  }  
6. }  
Abstract class and interface both are used to achieve abstraction where we can declare the
abstract methods. Abstract class and interface both can’t be instantiated. Differences:

Abstract class Interface

1) Abstract class can have abstract and non- Interface can have only abstract methods. Since
abstract methods. Java 8, it can have default and static
methods also.

2) Abstract class doesn't support multiple Interface supports multiple inheritance.


inheritance.

3) Abstract class can have final, non-final, Interface has only static and final variables.
static and non-static variables.

4) Abstract class can provide the Interface can't provide the implementation of


implementation of interface. abstract class.

5) The abstract keyword is used to declare The interface keyword is used to declare interface.


abstract class.

6) An abstract classcan extend another Java An interface can extend another Java interface only.
class and implement multiple Java interfaces.

7) An abstract classcan be extended using An interface classcan be implemented using


keyword "extends". keyword "implements".

8) A Javaabstract classcan have class Members of a Java interface are public by default.
members like private, protected, etc.

9)Example: Example:
public abstract class Shape{ public interface Drawable{
public abstract void draw(); void draw();
} }

Abstract class achieves partial abstraction (0-100%), whereas interface achieves full abstraction
(100%)
Type Casting is assigning a value of one type to a variable of another type.
To cast a value to a specific type place the type in parentheses and position it in front of the value:
int a = (int) 3.14;
System.out.println(a);
//Outputs 3
The code above is casting the value 3.14 to an integer, with 3 as the resulting value. Another:
double a = 42.571;
int b = (int) a;
System.out.println(b);
//Outputs 42
Java supports automatic type casting of integers to floating points, since there is no loss of
precision. On the other hand, type casting is mandatory when assigning floating point values to
integer variables.

For classes, there are two types of casting:


Upcasting
You can cast an instance of a subclass to its superclass.
Consider the following example, assuming that Cat is a subclass of Animal:
Animal a = new Cat();
Java automatically upcasted the Cat type variable to the Animal type.
Downcasting
Casting an object of a superclass to its subclass is called downcasting.
Animal a = new Animal();
((Cat)a).makeSound();
This will try to cast the variable a to the Cat type and call its makeSound() method.
Why is upcasting automatic, downcasting manual? Upcasting can never fail. But if you have a
group of different Animals and want to downcast them all to a Cat, then there’s a chance that
some of these Animals are actually Dogs, so the process fails.
Upcasting is casting to a supertype, while downcasting is casting to a subtype. Upcasting is
always allowed but downcasting involves a type check and can throw a ClassCastException.A
cast from Dog to Animal is an upcast, because a Dog is-a Animal. In general, you upcast
whenever there is an is-a relationship between two classes. Downcasting like this:
Animal animal = new Dog();
Dog castedDog = (Dog) animal;
Basically what you’re doing is telling the compiler that you know what the runtime type of the
object really is. The compiler will allow the conversion, but will still insert a runtime sanity check to
make sure that the conversion makes sense. In this case, the cast is possible because at runtime
animal is actually a Dog even though the static type of animal is animal. However if you were to do
this:
Animal animal = new Animal();
Dog notADog = (Dog) animal;

You’d get a ClassCastException. This is because animal’s runtime type is Animal, and so when
you tell the runtime to perform the cast it sees that animal isn’t really a Dog and so throws a
ClassCastException. To call a superclass’s method you can do super.method() or by performing
the upcast. To call a subclass’s method you have to do a downcast. As shown above, you
normally risk a ClassCastException by doing this; however, you can use the instanceof operator to
check the runtime type of the object before performing the cast, which allows you to prevent
ClassCastException s:
Animal animal = getAnimal(); // Maybe a Dog? Maybe a Cat? Maybe an
Animal?
if (animal instanceof Dog) {
// Guaranteed to succeed, barring classloader shenanigans
Dog castedDog = (Dog) animal;
}

Anonymous classes are a way to extend the existing classes on the fly. Consider having a class
Machine:
class Machine {
public void start() {
System.out.println(“Starting…”);
}
}
When creating the Machine object, we change the start method on the fly.
public static void main(String[ ] args) {
Machine m = new Machine() {
@Override public void start() {
System.out.println("Wooooo");
}
};
m.start();
} //Outputs "Wooooo"
After the constructors call, we have opened the curly braces and have overridden the start
method’s implementation on the fly. The @Override annotation is used to make your code easier
to understand, because it makes it more obvious when methods are overridden.
The modification is applicable only to the current object, and not to the class itself. So if we create
another object of that class, the start method’s implementation will be the one defined in the class.
class Machine {
public void start() {
System.out.println("Starting...");
}
}
public static void main(String[ ] args) {
Machine m1 = new Machine() {
@Override public void start() {
System.out.println("Wooooo");
}
};
Machine m2 = new Machine();
m2.start();
} //Outputs "Starting..."
Anonymous class enable you to make your code more concise. They enable you to declare and
instantiate a class at the same time. They are like local classes except that they do not have a
name. Use them if you need to use a local class only once.

Java supports nesting classes; a class can be a member of another class. Creating an inner class
is quite simple. Just write a class within a class. Unlike a class, an inner class can be private, like
a method. This means it cannot be accessed from an object outside the class.
class Robot {
int id;
Robot(int i) {
id = i;
Brain b = new Brain();
b.think();
}
private class Brain {
public void think() {
System.out.println(id + " is thinking");
}
}
}
The class Robot has an inner class Brain. The inner class can access all of the member variables
and methods of its outer class, but it cannot be accessed from any outside class.

Remember that when you create objects, the variable store references to the objects. So when
you compare objects using the equality testing operator (==), it actually compares the references
and not the object values.
class Animal {
String name;
Animal(String n) {
name = n;
}
}

class MyClass {
public static void main(String[ ] args) {
Animal a1 = new Animal("Robby");
Animal a2 = new Animal("Robby");
System.out.println(a1 == a2);
}
} //Outputs false
Despite having two objects with the same name, the equality testing returns false, because we
have two different objects, two different references or memory locations. == does not refer to the
value or string type, but rather where in memory the object is located. We can test for reference
equality with "==", and two objects are only reference-equal if they occupy the same space in
memory, that is, if it’s really just one object being compared with itself.
Each object has a predefined equals() method that is used to check for semantical equality
testing, testing whether two objects “look” the same or have similar meaning. But, to make it work
for our classes, we need to override it and check the conditions we need. There is a simple and
fast way of generating the equals() method, other than writing it manually. Just right click in your
class, go to Source->Generate hashCode() and equals()...

This will automatically create the necessary methods.


class Animal {
String name;
Animal(String n) { //this is constructor
name = n;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Animal other = (Animal) obj;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
The automatically generated hashCode() method is used to determine where to store the object
internally. Whenever you implement equals, you MUST also implement hashCode. We can run the
test again, using the equals method:
public static void main(String[] args) {
Animal a1 = new Animal("Robby");
Animal a2 = new Animal("Robby");
System.out.println(a1.equals(a2));
} //Outputs true
You can use the same menu to generate other useful methods, such as getters and setters for
your class attributes.

An Enum is a special type used to define collections of constants. Example:


enum Rank {SOLDIER, SERGEANT, CAPTAIN}
Note that the values are comma-separated. You can refer to the constants in the enum above with
dot syntax.
Rank a = Rank.SOLDIER;
Basically, Enums define variables that represent members of a fixed set.
After declaring an Enum, we can check for the corresponding values with, for example, a switch
statement:
Rank a = Rank.SOLDIER;
switch(a) {
case SOLDIER:
System.out.println("Soldier says hi!");
break;
case SERGEANT:
System.out.println("Sergeant says Hello!");
break;
case CAPTAIN:
System.out.println("Captain says Welcome!");
break;
} //Outputs “Soldier says hi!”
You should always use Enums when a variable can only be one out of a small set of possible
values. If you use Enums instead of integers, or String codes, you increase compile-time checking
and avoid errors from passing in invalid constants, and you document which values are legal to
use. Enum examples could be month names, days of the week, deck of cards, etc.

The Java API, application programming interface, is a collection of classes and interfaces that
have been written for you to use. The Java API Documentation with all of the available APIs can
be located on the Oracle website at http://docs.oracle.com/javase/7/docs/api/.
Once you locate the package you want to use, you need to import it into your code. The package
can be imported using the import keyword.
import java.awt.*;
The awt package contains all of the classes for creating user interfaces and for painting graphics
and images. The wildcard character (*) is used to import all of the classes in the package.

Exceptions, Lists, Threads & Files


An exception is a problem that occurs during program execution. Exceptions cause abnormal
termination of the program. Exception handling is a powerful mechanism that handles runtime
errors to maintain normal application flow.
An exception can occur for many different reasons:
- Invalid data entered
- File cannot be found/does not exist
- Network connection lost
- Insufficient memory.
As you can see, exceptions are caused by user error, programmer error, or physical resource
issues. However, a well-written program should handle all possible exceptions.
Exceptions can be caught using a combination of try and catch keywords. A try/catch block is
placed around the code that might generate an exception, like:
try {
//some code
} catch (Exception e) {
//some code to handle errors
}
A catch statement involves declaring the type of exception you are trying to catch. If an exception
occurs in the try block, the catch block that follows the try is checked. If the type of exception that
occurred is listed in a catch block, the exception is passed to the catch block much as an
argument is passed into a method parameter.
The exception type can be used to catch all possible exceptions.
Example below demonstrates exception handling when trying to access an array index that does
not exist:
try {
int a[] = new int[2];
System.out.println("Access element three :" + a[3]);
} catch (ArrayIndexOutOfBoundsException e)
{ System.out.println("Exception thrown :" + e);
} //catches specific exception, use ‘Exception e’ to catch all exception
Without the try/catch block this code should crash the program as a[3] does not exist.
The throw keyword allows you to manually generate exceptions from your methods. Some of the
numerous available exception types include the IndexOutOfBoundsException,
IllegalArguementException, ArithmeticException, and so on. We can throw an ArithmeticException
in our method when the parameter is 0.
static int div(int a, int b) throws ArithmeticException {
if(b == 0) {
throw new ArithmeticException("Division by Zero");
} else {
return a / b;
}
}
The throws statement in the method definition defines the type of Exception(s) the method can
throw. Next, the throw keyword throws the corresponding exception, along with a custom
message. If we call the div method with the second parameter equal to 0, it will throw an
ArithmeticException with the message “Division by Zero”.
Multiple exceptions can be defined in the throws statement using a comma-separated list.

A single try block can contain multiple catch blocks that handle different exceptions separately.
Example:
try {
//some code
} catch (ExceptionType1 e1) {
//Catch block
} catch (ExceptionType2 e2) {
//Catch block
} catch (ExceptionType3 e3) {
//Catch block
}
All catch blocks should be ordered from most specific to most general. Following the specific
exceptions, you can use the Exception type to handle all other exceptions as the last catch.

Java is a multi-threaded programming language. This means that our program can make optimal
use of available resources by running two or more components concurrently, with each component
handling a different task.
You can subdivide specific operations within a single application into individual threads that all run
in parallel. The following diagram shows the life-cycle of a thread:

There are two ways to create a thread:


1. Extend the Thread class
Inherit from the Thread class, override its run() method, and write the functionality of the thread in
the run() method. Then you create a new object of your class and call it’s start method to run the
thread. Example:
class Loader extends Thread {
public void run() {
System.out.println("Hello");
}
}

class MyClass {
public static void main(String[ ] args) {
Loader obj = new Loader();
obj.start();
}
}
As you can see, our Loader class extends the Thread class and overrides its run() method. When
we create the obj object and call its start() method, the run() method statements execute on a
different thread. Every Java thread is prioritized to help the operating system determine the order
in which to schedule threads. The priorities range from 1 to 10, with each thread defaulting to
priority 5. You can set the thread priority with the setPriority() method.
2. Implementing the Runnable interface
Implement the run() method. Then, create a new Thread object, pass the Runnable class to its
constructor, and start the Thread by calling the start() method. Example:
class Loader implements Runnable {
public void run() {
System.out.println("Hello");
}
}

class MyClass {
public static void main(String[ ] args) {
Thread t = new Thread(new Loader());
t.start();
}
}
The Thread.sleep() method pauses a Thread for a specified period of time. For example, calling
Thread.sleep(1000); pauses the thread for one second. Keep in mind that Thread.sleep() throws
an InterruptedException, so be sure to surround it with a try/catch block.
It may seem that implementing the Runnable interface is a bit more complex than extending from
the Thread class. However, implementing the Runnable interface is the preferred way to start a
Thread, because it enables you to extend from another class, as well.
https://www.geeksforgeeks.org/multithreading-in-java/
Multithreading is a Java feature that allows concurrent execution of two or more parts of a program
for maximum utilization of the CPU. Each part of such program is called a thread. So, threads are
light-weight processes within a process.
If we extend the Thread class, our class cannot extend any other class because Java doesn’t
support multiple inheritance. But, if we implement the Runnable interface, our class can still extend
other base classes.
We can achieve basic functionality of a thread by extending Thread class because it provides
some inbuilt method like yield(), interrupt ext. that are not available in Runnable interface.
https://www.tutorialspoint.com/java/java_multithreading.htm
A multi-threaded program contains two or more parts that can run concurrently and each part and
handle a different task at the same time making optimal use of the available resources specially
when your computer has multiple CPUs. Multitasking is when multiple processes share common
processing resources such as a CPU. Multi-threading extends the idea of multitasking into
application where you can subdivide specific operations within a single application into individual
threads. Each of the threads can run in parallel. The OS divides processing time not only among
different applications, but also among each thread within an application. Multi-threading enables
you to write in a way where multiple activities can proceed concurrently in the same program.
When we start two or more threads within a program, there may be a situation when multiple
threads try to access the same resource and finally they can product unforeseen result due to
concurrency issues. For example, if multiple threads try to write within a same file then they may
corrupt the data because one of the threads can override data or while one thread is opening the
same file at the same time another thread might be closing the same file.
So there is a need to synchronize the action of multiple threads and make sure that only one
thread can access the resource at a given point in time. This is implemented using a concept
called monitors. Each object in Java is associated with a monitor, which a thread can lock or
unlock. Only one thread at a time may hold a lock on a monitor.
Java programming language provides a very handy way of creating threads and synchronizing
their task by using synchronized blocks. You keep shared resources within this block.
General form of synchronized statement:

synchronized(objectidentifier) {
// Access shared variables and other shared resources
}

Here the objectidentifier is a reference to an object whose lock associates with the monitor that the
synchronized statement represents. Now we are going to see two examples where we will print a
counter using two different threads. When threads are not synchronized, they print counter value
which is not in sequence, but when we print counter by putting inside synchronized() block, then it
prints counter very much in sequence for both the threads.

There are two exception types, checked and unchecked (also called runtime). The main difference
is that checked exceptions are checked when compiled, while unchecked exceptions are checked
at runtime. As mentioned in our previous lesson, Thread.sleep() throws an InterruptedException.
This is an example of a checked exception. Your code will not compile until you’ve handled the
exception.
public class MyClass {
public static void main(String[] args) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
//some code
}
}
}
We have seen examples of unchecked exceptions, which are checked at runtime, in previous
lessons. Example:
public class MyClass {
public static void main(String[] args) {
int value = 7;
value = value / 0;
}
}
/*
Exception in thread "main" java.lang.ArithmeticException: / by zero
at MyClass.main(MyClass.java:4)
*/
It is good to know the types of exceptions because they can help you debug your code faster.
The Java API provides special classes to store and manipulate groups of objects. One such class
is the ArrayList. Standard Java arrays are of a fixed length, which means that after they are
created, they cannot expend or shrink. On the other hand, ArrayLists are created with an initial
size, but when the size is exceeded, the collection is automatically enlarged. When objects are
removed, the ArrayList may shrink in size. Note that the ArrayList class is in the jave.util package,
so it’s necessary to import it before using it. Create an ArrayList as you would any object:
import java.util.ArrayList;
//...
ArrayList colors = new ArrayList();
You can optionally specify a capacity and type of objects the ArrayList will hold:
ArrayList<String> colors = new ArrayList<String>(10);
The code above defines an ArrayList of Strings with 10 as its initial size.
ArrayList store objects. Thus, the type specified must be a class types. You cannot pass, for
example, int as the objects’ type. Instead, use the special class types that correspond to the
desired value type, such as Integer for int, Double for double and so on.
The ArrayList class provides a number of useful methods for manipulating its objects. The add()
method adds new objects to the ArrayList. Conversely, the remove() methods remove objects from
the ArrayList. Example:
import java.util.ArrayList;

public class MyClass {


public static void main(String[] args) {
ArrayList<String> colors = new ArrayList<String>();
colors.add("Red");
colors.add("Blue");
colors.add("Green");
colors.add("Orange");
colors.remove("Green");
System.out.println(colors);
}
} // Output: [Red, Blue, Orange]
Other useful methods include:
- contains(): Returns true if the list contains the specified element
- get(int index): Returns the element at the specified position in the list
- size(): Returns the number of elements in the list
- clear(): Removes all of the elements from the list
Note: As with arrays, the indexing starts with 0
The LinkedList is very similar in syntax to the ArrayList. A Linked List is a data structure consisting
of a group of nodes which together represent a sequence. Each node is composed of data and a
link to the next node in the sequence. Nodes are linked using these pointers and addresses. Due
to the dynamicaity and ease of insertions and deletions, they are preferred over the arrays. It also
has few disadvantages like nodes cannot be accessed directly, we need to start form the head
and follow through the link to reach to a node we need to access.
You can easily change an ArrayList to a LinkedList by changing the objects type.
import java.util.LinkedList;

public class MyClass {


public static void main(String[] args) {
LinkedList<String> c = new LinkedList<String>();
c.add("Red");
c.add("Blue");
c.add("Green");
c.add("Orange");
c.remove("Green");
System.out.println(c);
}
} // Outputs [Red, Blue, Orange]
You cannot specify an initial capacity for the LinkedList.
The most notable difference between the LinkedList and the ArrayList is in the way they store
objects. The ArrayList is better for storing and accessing data, as it is very similar to a normal
array. The LinkedList is better for manipulating data, such as making numerous inserts and
deletions.
In addition to storing the object, the LinkedList stores the memory address of the element that
follows it. It’s called a LinkedList because each element contains a link to the neighbouring
element. You can use the enhanced for loop to iterate over its elements:
LinkedList<String> c = new LinkedList<String>();
c.add("Red");
c.add("Blue");
c.add("Green");
c.add("Orange");
c.remove("Green");

for(String s: c) {
System.out.println(s);
}
/* Output:
Red
Blue
Orange
*/
Summary:
- Use an ArrayList when you need rapid access to your data.
- Use a LinkedList when you need to make a large number of inserts and/or deletions.
Arrays and Lists store elements as ordered collections, with each element given an integer index.
HashMap is used for storing data collections as key and value pairs. One object is used as a key
(index) to another object (the value).
The put, remove, and get methods are used to add, delete, and access values in the HashMap.
Example:
import java.util.HashMap;
public class MyClass {
public static void main(String[] args) {
HashMap<String, Integer> points = new HashMap<String, Integer>();
points.put("Amy", 154);
points.put("Dave", 42);
points.put("Rob", 733);
System.out.println(points.get("Dave"));
}
}// Outputs 42
We have created a HashMap with Strings as its keys and Integers as its values.
Use the get method and the corresponding key to access the HashMap elements.
A HashMap cannot contain duplicate keys. Adding a new item with a key that already exists
overwrites the old element. The HashMap class provides containsKey and containsValue methods
that determine the presence of a specified key or value. If you try to get a value that is not present
in your map, it returns the value of null.

A Set is a collection that cannot contain duplicate elements. It models the mathematical set
abstraction. One of the implementations of the Set is the HashSet class. Example:
import java.util.HashSet;

public class MyClass {


public static void main(String[] args) {
HashSet<String> set = new HashSet<String>();
set.add("A");
set.add("B");
set.add("C");
System.out.println(set);
}
} // Output: [A, B, C]
You can use the size() method to get the number of elements in the HashSet.
The HashSet class does not automatically retain the order of the elements as they’re added. To
order the elements, use a LinkedHashSet, which maintains a linked list of the set’s elements in the
order in which they were inserted.
A hash table stores information through a mechanism called hashing, in which a key’s
informational content is used to describe a unique value called a hash code. So, basically, each
element in the HashSet is associated with its unique hash code.
You’ve learned about the various collection types that are available in Java, including Lists, Maps,
and Sets. The choice of which one to use is specific to the data you need to store and manipulate.
For the manipulation of data in different collection types, the Java API provides a Collections
class, which is included in the java.util package. One of the most popular Collections class
methods is sort(), which sorts the elements of your collection type. The methods in the Collections
class are static, so you don’t need a Collections object to call them. Example:
public class MyClass {
public static void main(String[] args) {
ArrayList<String> animals = new ArrayList<String>();
animals.add("tiger");
animals.add("cat");
animals.add("snake");
animals.add("dog");
Collections.sort(animals);
System.out.println(animals);
}
}
/* Outputs:
[cat, dog, snake, tiger]
*/
As you can see the elements have been sorted alphabetically.
You can call the sort() methods on different types of Lists, such as Integers.
import java.util.ArrayList;
import java.util.Collections;

public class MyClass {


public static void main(String[] args) {
ArrayList<Integer> nums = new ArrayList<Integer>();
nums.add(3);
nums.add(36);
nums.add(73);
nums.add(40);
nums.add(1);
Collections.sort(nums);
System.out.println(nums);
}
}
/* Outputs:
[1, 3, 36, 40, 73]
*/
Other useful methods in the Collections class:
max(Collection c): Returns the maximum element in c as determined by natural ordering.
min(Collection c): Returns the minimum element in c as determined by natural ordering
reverse(List list): Reverses the sequence in list.
shuffle(List list): Shuffles (i.e., randomizes) the elements in the list.
An iterator is an object that enables you to cycle through a collection, obtain or remove elements.
Before you can access a collection through an iterator, you must obtain one. Each of the collection
classes provides an iterator() method that returns an iterator to the start of the collection. By using
this iterator object, you can access each element in the collection one element at a time.
The iterator class provides the following methods:
hasNext(): Returns true if there is at least one more element; otherwise, it returns false.
next(): Returns the next object and advances the iterator.
remove(): Removes the last object that was returned by next from the collection.
The iterator class must be imported from the java.util package. Example:
import java.util.Iterator;
import java.util.LinkedList;

public class MyClass {


public static void main(String[] args) {
LinkedList<String> animals = new LinkedList<String>();
animals.add("fox");
animals.add("cat");
animals.add("dog");
animals.add("rabbit");
Iterator<String> it = animals.iterator();
String value = it.next();
System.out.println(value);
}
} //Outputs "fox"
it.next() returns the first element in the list and them moves the iterator on to the next element.
Each time you call it.next(), the iterator moves to the next element of the list.
Typically, iterators are used in loops. At each iteration of the loop, you can access the
corresponding list element. Example:
import java.util.Iterator;
import java.util.LinkedList;

public class MyClass {


public static void main(String[] args) {
LinkedList<String> animals = new LinkedList<String>();
animals.add("fox");
animals.add("cat");
animals.add("dog");
animals.add("rabbit");
Iterator<String> it = animals.iterator();
while(it.hasNext()) {
String value = it.next();
System.out.println(value);
}
}
}
/*
fox
cat
dog
rabbit */
Here, the while loop determines whether the iterator has additional elements, prints the value of
the element, and advances the iterator to the next.
The java.io package includes a File class that allows you to work with files. To start, create a File
object and specify the path of the file in the constructor.
import java.io.File;
...
File file = new File("C:\\data\\input-file.txt");
With the exists() method, you can determine whether a file exists.
import java.io.File;

public class MyClass {


public static void main(String[] args) {
File x = new File("C:\\sololearn\\test.txt");
if(x.exists()) {
System.out.println(x.getName() + "exists!");
} else {
System.out.println("The file does not exist");
}
}
}
The code above prints a message stating whether or not the file exists at the specified path.
The getName() method returns the name of the file. Note that we used double backslashes in the
path, as one backslash should be escaped in the path String.
Files are useful for storing and retrieving data, and there are a number of ways to read from a file.
One of the simplest ways is to use the Scanner class from the java.util package.
The constructor of the Scanner can take a File object as input. To read the contents of a text file at
the path “C:\\sololearn\\test.txt”, we would need to create a File object with the corresponding path
and pass it to the Scanner object.
try {
File x = new File("C:\\sololearn\\test.txt");
Scanner sc = new Scanner(x);
}
catch (FileNotFoundException e) {

}
We surround the code with a try/catch block, because there’s a chance that the file may not exist.
The Scanner class inherits form the Iterator, so it behaves like one. We can use the Scanner
object’s next() method to read the file’s contents.
try {
File x = new File("C:\\sololearn\\test.txt");
Scanner sc = new Scanner(x);
while(sc.hasNext()) {
System.out.println(sc.next());
}
sc.close();
} catch (FileNotFoundException e) {
System.out.println("Error");
}
The file’s contents are output word by word, because the next() method returns each word
separately. It is always good practice to close a file when finished working with it. One way to do
this is to use the Scanner’s close() method.
Formatter, another useful class in the java.util package, is used to create content and write it to
files. Example:
import java.util.Formatter;

public class MyClass {


public static void main(String[] args) {
try {
Formatter f = new Formatter("C:\\sololearn\\test.txt");
} catch (Exception e) {
System.out.println("Error");
}
}
}
This creates an empty file at the specified path. If the file already exists, this will overwrite it.
Again you should surround the code with a try/catch block, as the operation can fail.
Once the file is created, you can write content to it using the same Formatter object’s format()
method. Example:
import java.util.Formatter;

public class MyClass {


public static void main(String[ ] args) {
try {
Formatter f = new Formatter("C:\\sololearn\\test.txt");
f.format("%s %s %s", "1","John", "Smith \r\n");
f.format("%s %s %s", "2","Amy", "Brown");
f.close();
} catch (Exception e) {
System.out.println("Error");
}
}
}
The format() method formats its parameters according to its first parameter. %s mean a string and
get’s replaced by the first parameter after the format. The second %s get’s replaced by the next
one and so on. So, the format %s %s %s denotes three strings that are separated with spaces.
Note: \r\n is the newline symbol in Windows.
The code above creates a file with the following content:
1 John Smith
2 Amy Brown
Don’t forget to close the file once you’re finished writing to it!

You might also like