Core Java Theory Interview Question​

byte, short, int, long, float, double, char, boolean.

The smallest individual unit in a program is known as a token. The five types of tokens are- :

a) Keywords:- public, static, void, import etc. (Java’s own terms)

b) Identifiers:- (variables) alphabets, digits, under score, dollar sign etc.

c) Literals:- (Constants) integer literals, floating literals, boolean literals, character literals, string literal, the null literal.

d) Punctuators (separators):- () {} [] ; ,

e) Operators = + – < >

A variable is a name for a location in memory used to store a data value.
We use variables to save and restore values or
the results of calculations.
The programmer has to tell Java what type of data will be store in the variable’s memory location. Its type cannot change.
During the program execution the data saved in the memory location can change; hence the term “variable”.

Before you can use a variable, you must declare its type and name.

You can declare a variable only once in a method.

Examples:

int numDimes;

double length;

char courseSection;

boolean done;

String lastName;

Declaring a variable instructs the compiler to set aside a portion of memory large enough to hold data of that type.

int count;

double length;

KodNest c

No value has be put in memory yet. That is, the variable is undefined.

Variables can be declared and initialized in one statement:

Example:

int numDimes = 4;
double length = 52.3;
char courseSection = 'J';
boolean done = true;
String lastName = "Reid-Miller";
int count = 3 + 2;

An expression is anything that result in a value.

It must have a type.

KodNest ar
KodNest div

The operators *, /, % are evaluated before the operators +, – because *, /, % have higher precedence than +, -.

KodNest

To change the order use parentheses:

Example: (2 + 4) * 5 evaluates to 30

When an expression contains more than one operator with the same level of precedence, they are evaluated from left to right.

An integer is a whole number — that is, a number with no fractional or decimal portion. Java has four integer types, which you can use to store numbers of varying sizes.

KodNest dt

The most commonly used integer type is int. You can use short or even byte when you know the variable won’t need to store large values, and you can use long when your program will require large values — for example, when calculating the federal deficit.

KodNest in

In Java, char is short for character. It is 16 bits in size, double that of a byte. Most of the time however, the actual data stored in the char data type doesn’t take up more than 8 bits; the reason Java allows 16 bits is so that all characters in all languages can be represented. This representation is in the Unicode format.

Unicode is a computer encoding methodology that assigns a unique number for every character. It doesn’t matter what language, or computer platform it’s on. This is important in a global, networked world, and for computer systems that must accommodate multiple languages and special characters. Unicode truly unifies all of these into a single standard.

In Unicode, all characters are represented by numeric values. For example, 65 is the letter A. 66 is B and so on. The lower-case letters start at 97. There are even special system-only characters in the list: carriage returns, tabs, etc. These can be useful in displaying text; while others are leftovers from older systems.

Examples: Declaring Char Variables

You’d think that a char could be any value from a to Z, and all the numbers. That is true, except for one key item. You can either declare a char variable with single quotes, e.g., setting a char’s value to the letter a. Or, you could omit the quotes, and set the Unicode representation of the value. Take a look at the following code for declaring a char variable equal to 77.

char eighty_eight = 77;

The output is not going to be 77, but the Unicode representation

Floating-point numbers are numbers that have fractional parts (usually expressed with a decimal point). You should use a floating-point type in Java programs whenever you need a number with a decimal, such as 19.95 or 3.1415.

Java has two primitive types for floating-point numbers:

float: Uses 4 bytes

double: Uses 8 bytes

In almost all cases, you should use the double type whenever you need numbers with fractional values.

The precision of a floating-point value indicates how many significant digits the value can have following its decimal point. The precision of a float type is only about six or seven decimal digits, which isn’t sufficient for most types of calculations.

If you use Java to write a payroll system, for example, you might get away with using float variables to store salaries for employees such as teachers or firefighters, but not for professional baseball players or corporate executives.

By contrast, double variables have a precision of about 15 digits, which is enough for most purposes.

Example:

double period = 99.0;

If you omit the decimal point, the Java compiler treats the literal as an integer. Then, when it sees that you’re trying to assign the integer literal to a double variable, the compiler converts the integer to a double value. This avoidable conversion step uses some precious processing time.

To save that time, you can add an F or D suffix to a floating-point literal to indicate whether the literal itself is of type float or double. For example:

float value1 = 199.33F;

double value2 = 200495.995D;

If you omit the suffix, D is assumed. As a result, you can usually omit the D suffix for double literals.

KodNest ft

Boolean is the primitive data type in Java. There are only two values that a boolean type can take they are: true or false. Boolean type is used when we want to test a particular condition during the execution of the program. Boolean values are often used in Selection statements and Iteration statements.

Boolean type is denoted by the keyword boolean and and their size is only ‘1-bit’ and not ‘1-byte’. The words true and false cannot be used as identifiers. Boolean is also the type required by conditional expression that govern the Control statements such as if condition and for loop.

Example:

boolean val=true;

Array is a set of similar data type.

Arrays objects store multiple variables with the same type.

It can hold primitive types and object references.

Arrays are always fixed

An Array is declared similar to how a variable is declared, but you need to add [] after the type.

Example: int []a;

We can declare Java array as a field, static field, a local variable, or parameter, like any other variable. An array is a collection of variables of that type. Here are a few more Java array declaration examples:

String [] sArray;

MyClass [] myClassArray;

Advantages:

1.We can put in place other data structures like stacks, queues, linked lists, trees, graphs, etc. in Array.

2.Arrays can sort multiple elements at a time.

3.We can access an element of Array by using an index.

Disadvantages:

1.We have to declare Size of an array in advance. However, we may not know what size we need at the time of array declaration.

2.The array is static structure. It means array size is always fixed, so we cannot increase or decrease memory allocation.

No we cannot change the array size.

No we cannot declare an array without assigning size.

If we declare an array without size, it will throw compile time error

Example: marks = new int []; //COMPILER ERROR

Any new Array is always initialized with a default value as follows

For byte, short, int, long – default value is zero (0).

For float, double – default value is 0.0.

For Boolean – default value is false.

For object – default value is null.

int schoolmarks [] = {25, 35, 55, 10, 5 };
System.out.println (Arrays.toString (schoolmarks));
Output is: [25, 35, 55, 10, 5]

If two arrays are of the same size & data type then comparison can be done by using Arrays.equals ()

Example:

int [] num1 = { 1, 2, 3 };
int[] num2 = { 4, 5, 6 };
System.out.println (Arrays. equals (num1, num2)); 
//output:false

Int [] num3 = {1, 2, 3};
System.out.println (Arrays.equals (num1, num3)); 
//output:true

Sorting of an array is possible using the in built static method “ Arrays. sort ()”

Example:

Int M [] = {12, 5, 7, 9};
Arrays.sort(M);
System.out.println(Arrays.toString(M));
//[5, 7, 9, 12]

No. We cannot declare the negative integer as an array size.

If we declare, there will be no compile-time error.

However, we will get NegativeArraySizeException at run time.

It is a runtime exception. For example, we can store only string elements in a String Array. If anybody tries to insert integer element in this String Array, then we will get ArrayStoreException at run time.

Anonymous array means array without any reference.

Example:

//Creating anonymous arrays

System.out.println(new int[]{11, 12, 13, 14, 15,16}.length); 
//Output : 6

System.out.println(new int[]{31, 94, 75, 64, 41,30}[1]); 
//Output : 94

No difference both are the legal statement

Yes we can assign provided they should the same type. The compiler will check the only type of the array, not the size.

Example:

int[] a = new int[30];
int[] d = new int[50];
a = d; 

//Compiler checks only type, not the size

No, We should not mention the size of the array when we are providing the array elements.

Below four tricks are available in java to copy an array.

Using “For loop”

Using “Arrays.copyOf()” method

Using “System.arraycopy()” method

Using “clone()” method

Jagged Arrays are Arrays the contains arrays of different length. Jagged arrays are also known as multidimensional arrays.

It will occur when the program tries to access invalid index of an array. Index higher than the size of the array or negative index.

We can use Arrays.binarySearch() method. This method uses binary search algorithm.

Using Brute Force Method:

In this method, we compare each element of an array with other elements.

If any two elements found equal or same, we declare them as duplicates.

Example:

public class DuplicatesInArray
 {
public static void main(String[] args) 
{
String[] strArray1 = {"abc1", "def1", "mno1", "xyz1", "pqr1", "xyz1", "def1"};
for (int i = 0; i < strArray1.length-1; i++)
 {
for (int j = i+1; j < strArray1.length; j++)
 {
if( (strArray1[i].equals(strArray1[j])) && (i != j) )
 {
System.out.println("Duplicates : "+strArray1[j]);
}
}
}
} 
}

Output: Duplicate Element is : def1
        Duplicate Element is: xyz1

No, we cannot use Generic with an array.

1) Using normal for loop

Example:

public class Class1
{
public static void main(String[] args)
{
int[] a1 = new int[]{46, 12, 78, 34, 89, 26};
//Iterating over an array using normal for loop
for (int i = 0; i < a1.length; i++)
{
System.out.println(a1[i]);
}
}
}

 2) Using extended new for loop

Example:

public class Class1
{
public static void main(String[] args)
{
int[] a2 = new int[]{4, 12, 78, 34, 89, 2};
//Iterating over an array using extended for loop
for (int i: a2){
System.out.println(i);
}
}
}

It is An array of an array in Java.

Example:

int[][] a = new int[3][3] which is a matrix of 3×3.

Yes, Java supports N-dimensional array.

Multi-dimensional array in Java is nothing but an array of arrays,

Example:  a 2-dimensional array is an array of 1-dimensional array.

Yes, we can make an array volatile in Java, but we only make the variable which is pointing to array volatile.

Solution to solve this problem is to calculate sum of all numbers in the array and compare with an expected sum, the difference would be the missing number.

int arr [] = new int[]{1,2,3,5,6,7};

Get the sum of numbers

total = n*(n+1)/2

Subtract all the numbers from sum and

you will get the missing number.

According to below logic sumOfNnumberss is 7*(7+1)/2=28

sumOfElements = 1+2+3+5+6+7=24

missing element is = 28-24=4

Code snippet:

int arr [] = new int[]{1,2,3,5,6,7};
int n = arr.length+1;
int total = n*(n+1)/2;
for(int i =0;i<arr.length;i++){
total -=arr[i];}
System.out.println(total);

Code snippit:

String str = "HI RAJU I AM FINE RAJU"; // String with a duplicate word.
String[] words = str.split(" "); // Splitting and converting to Array .
for(int i = 0; i < words.length; i++){ //iterating array inside for loop
for(int j = i+1; j < words.length; j++){ //iterating same array inside another for loop
if (words[i].equals(words[j])){ // Using equal method i am verifying which word is repeating . System.out.println( words[i]); // here it will print duplicate .
}
}

We use two variables to store largest and smallest number.

First, we initialize largest with Integer.MIN_VALUE and

Next, we initialize smallest with Integer.MAX_VALUE.

In each iteration of the for loop, we will compare present number with largest and smallest number, and we will update

If a number is larger than largest, then it cannot be smaller than smallest. That is it is not required check if the first condition is true,

We will use the if-else control construct, where else part will only execute if the first condition is false.

Code snippit:

import java.util.Arrays;
public class MaximumMinimumArrayExample{
public static void largestAndSmallest(int[] numbers) {
int largest = Integer.MIN_VALUE;
int smallest = Integer.MAX_VALUE;
for (int number : numbers) {
if (number > largest) {
largest = number;
}
else if (number < smallest) {
smallest = number;
}
 }
System.out.println("Largest is : " + largest);
System.out.println("Smallest is : " + smallest);
 }
 }

Declare a String Array String[] s = new String[]{“My”,”Leg”,”is”,”cut”};

Iterate it using for loop get all elements in reverse order means end point to start point.

Code Snippet:

Class Demo
{
public static void main(String[] args)
{
String[] s = new String[]{"My","Leg","is","injured"};
for(int i=s.length-1; i>=0; i--)
{
System.out.println("reverse "+s[i]);
}
}
}

Iterate the given array using for loop.

( if condition arr[i] > largest):

If current array value is greater than largest value then

Move the largest value to secondLargest and make current value as largest

( if condition arr[i] > secondLargest )

If the current value is smaller than largest and

greater than secondLargest then the current value becomes

code Snippet:

class Demo
{
public static void main(String[] args) 
{
int myArr[] = { 14, 46, 47, 86, 92, 52, 48, 36, 66, 85 };
int largest = myArr[0];
int secondLargest = myArr[0];
System.out.println("The given array is:" );
for (int i = 0; i < myArr.length; i++) {
System.out.print(myArr[i]+"\t");
}
for (int i = 0; i < myArr.length; i++) { if (myArr[i] > largest) {
secondLargest = largest;
largest = myArr[i];
} else if (myArr[i] > secondLargest) {secondLargest = myArr[i];
}
}
System.out.println("\nSecond largest number is:" + secondLargest);
}
}

Declare and assign variable sum as sum =0.

Iterate the given array using for loop.

Add all the array element and keep it in sum .

Code snippet:

Class Demo
{
Public static void main(String[] args) 
{
int my_array[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int sum = 0;
for (int i: my_array)
sum += i;
System.out.println("The sum is " + sum);
}
}

Insert an element in 3rd position of the array (index->2, value->5)

Iterate the given array in reverse order using for loop.

Now insert given position and value after for loop.

Class Demo
{
Public static void main(String[] args)
 {
int[] my_array = {25, 14, 56, 15, 36, 56, 77, 18, 29, 49};
int Index_position = 2;
int newValue = 5;
System.out.println("Original Array : "+Arrays.toString(my_array));
for(int i=my_array.length-1; i > Index_position; i--){
my_array[i] = my_array[i-1];
}
my_array[Index_position] = newValue;
System.out.println("New Array: "+Arrays.toString(my_array));
}
}

There are two ways to create string objects in java. One is using new operator and another one is using string literals. The objects created using new operator are stored in the heap memory and objects created using string literals are stored in string constant pool.

String s1 = new String("KODNEST");  //Creating string object using new operatorString      

s2 = "KODNEST";  //Creating string object using string literal

String objects are most used data objects in Java. Hence, java has a special arrangement to store the string objects. String Constant Pool is one such arrangement. String Constant Pool is the memory space in heap Segment specially allocated to store the string objects created using string literals. In String Constant Pool, there will be no two string objects having the same content.

Whenever you create a string object using string literal, JVM first checks the content of the object to be created. If there exists an object in the string constant pool with the same content, then it returns the reference of that object. It doesn’t create a new object. If the content is different from the existing objects then only it creates new object.

One special thing about string objects is that you can create string objects without using new operator i.e using string literals. This is not possible with other derived types (except wrapper classes). One more special thing about strings is that you can concatenate two string objects using ‘+’. This is the relaxation java gives to string objects as they will be used most of the time while coding. And also java provides string constant pool to store the string objects.

Immutable objects are like constants. You can’t modify them once they are created. They are final in nature. Where as mutable objects are concerned, you can perform modifications to them.

String objects created using java.lang.String class are immutable. Once they are created, they can not be modified. If you try to modify them, a new string object will be created with modified content. This property of String class may cause some memory issues for applications which need frequent modification of string objects. To overcome this behavior of String class, two more classes are introduced in Java to represent the strings. They are StringBuffer and StringBuilder. Both these classes are also members of  java.lang package same as String class.

The objects of String class are immutable in nature. i.e you can’t modify them once they are created. If you try to modify them, a new object will be created with modified content. This may cause memory and performance issues if you are performing lots of string modifications in your code. To overcome these issues, StingBuffer and StringBuilder classes are introduced in java.

String s1 = “KODNEST”;

String s2 = “KODNEST”;

Only one object will be created and this object will be stored in the string constant pool.

Using StringBuffer and StringBuilder classes. These classes provide mutable string objects.

I prefer equals() method because it compares two string objects based on their content. That provides more logical comparison of two string objects. If you use “==” operator, it checks only references of two objects are equal or not. It may not be suitable in all situations. So, rather stick to equals() method to compare two string objects.

Note: “==” operator compares the two objects on their physical address. That means if two references are pointing to same object in the memory, then comparing those two references using “==” operator will return true. For example, if s1 and s2 are two references pointing to same object in the memory, then invoking s1 == s2 will return true. This type of comparison is called “Shallow Comparison”.

equals() method, if not overrided, will perform same comparison as “==” operator does i.e comparing the objects on their physical address. So, it is always recommended that you should override equals() method in your class so that it provides field by field comparison of two objects. This type of comparison is called “Deep Comparison”.

In java.lang.String class, equals() method is overrided to provide the comparison of two string objects based on their contents. That means, any two string objects having same content will be equal according to equals() method. For example, if s1 and s2 are two string objects having the same content, then invoking s1.equals(s2) will return true.

hashCode() method returns hash code value of an object in the Integer form. It is recommended that whenever you override equals() method, you should also override hashCode() method so that two equal objects according to equals() method must return same hash code values. This is the general contract between equals() and hashCode() methods that must be maintained all the time.

In java.lang.String class, hashCode() method is also overrided so that two equal string objects according to equals() method will return same hash code values. That means, if s1 and s2 are two equal string objects according to equals() method, then invoking s1.hashCode() == s2.hashCode() will return true.

Let’s apply these three methods on string objects and try to analyse their output.

Define two string objects like below,

String s1 = “KODNEST”;

String s2 = “KODNEST”;

Now apply above methods on these two objects.

s1 == s2 —> will return true as both are pointing to same object in the constant pool.

s1.equals(s2) —> will also return true as both are referring to same object.

s1.hashCode() == s2.hashCode() —> It also returns true.

String s1 = new String("abc");
String s2 = "abc";

Here, two string objects will be created. Object created using new operator(s1) will be stored in the heap memory. The object created using string literal(s2) is stored in the string constant pool.

String object in the string constant pool is called as String Intern. You can create an exact copy of heap memory string object in string constant pool. This process of creating an exact copy of heap memory string object in the string constant pool is called interning. intern() method is used for interning

String s1 = new String("KODNEST");

String s2 = new String("KODNEST");

Two objects will be created and they will be stored in the heap memory.

Yes, we can call String class methods using string literals. Here are some examples,

"KODNEST".charAt(0)
"KODNEST".compareTo("KODNEST")
"KODNEST".indexOf('O')

1) Using replaceAll() Method.

In the first method, we use replaceAll() method of String class to remove all white spaces (including tab also) from a string. This is the one of the easiest method to remove all white spaces from a string. This method takes two parameters. One is the string to be replaced and another one is the string to be replaced with. We pass the string “\s” to be replaced with an empty string “”.

2) Without Using replaceAll() Method.

In the second method, we remove all white spaces (including tab also) from a string without using replaceAll() method. First we convert the given string to char array and then we traverse this array to find white spaces. We append the characters which are not the white spaces to StringBuffer object.

class RemoveWhiteSpaces
{
    public static void main(String[] args)
    {
        String str = "  Core Java jsp servlet  jdbc struts hibernate spring  ";
 
        //1. Using replaceAll() Method
 
        String strWithoutSpace = str.replaceAll("\\s", "");
 
        System.out.println(strWithoutSpace);         //Output : CoreJavajspservletsjdbcstrutshibernatespring
 
        //2. Without Using replaceAll() Method
 
        char[] strArray = str.toCharArray();
 
        StringBuffer sb = new StringBuffer();
 
        for (int i = 0; i < strArray.length; i++)
        {
            if( (strArray[i] != ' ') && (strArray[i] != '\t') )
            {
                sb.append(strArray[i]);
            }
        }
 
        System.out.println(sb);          
 //Output : CoreJavajspservletsjdbcstrutshibernatespring
    }
}

Write a java program to reverse a string with preserving the position of spaces. For example, if “I Am Not String” is the given string then the reverse of this string with preserving the position of spaces is “g ni rtS toNmAI”. Notice that the position of spaces in the original string are maintained in the reversed string also. That means, if the given string has a space at index 3, then there should be also a space in the reversed string at index 3.

First, we convert the given ‘inputstring’ to char array and call it as ‘inputStringArray’. We define one more char array called ‘resultArray’ with the same size as ‘inputStringArray’. In the first for loop, for every space in the ‘inputStringArray’, we insert space in the ‘resultArray’ at the corresponding positions. In the second for loop, we copy non-space characters of ‘inputStringArray’ starting from first to last into the ‘resultArray’ at ‘j’ position where ‘j’ will have value from length of resultArray to . Before copying, we check whether the ‘resultArray’ already contains a space at index ‘j’ or not. If it contains, we copy the character in the next position. See the below image for more clarity.

KodNest reverse 1
public class MainClass1
{    
    static void reverseString(String inputString)
    {
        //Converting inputString to char array 'inputStringArray'
         
        char[] inputStringArray = inputString.toCharArray();
         
        //Defining a new char array 'resultArray' with same size as inputStringArray
         
        char[] resultArray = new char[inputStringArray.length];
         
        //First for loop : 
        //For every space in the 'inputStringArray', 
        //we insert spaces in the 'resultArray' at the corresponding positions 
         
        for (int i = 0; i < inputStringArray.length; i++) 
        {
            if (inputStringArray[i] == ' ') 
            {
                resultArray[i] = ' ';
            }
        }
         
        //Initializing 'j' with length of resultArray
         
        int j = resultArray.length-1;
                 
        //Second for loop :
        //we copy every non-space character of inputStringArray 
        //from first to last at 'j' position of resultArray
         
        for (int i = 0; i < inputStringArray.length; i++) { if (inputStringArray[i] != ' ') { //If resultArray already has space at index j then decrementing 'j' if(resultArray[j] == ' ') { j--; } resultArray[j] = inputStringArray[i]; j--; } } System.out.println(inputString+" ---> "+String.valueOf(resultArray));
    }
     
    public static void main(String[] args)
    {
        reverseString("I Am Not String");
         
        reverseString("JAVA JSP ANDROID");
         
      }
}
Output:

I Am Not String —> g ni rtS toNmAI
JAVA JSP ANDROID —> DIOR DNA PSJAVAJ

Yes string is thread safe in Java as String is immutable.

StringBuffer class is the companion class of String. StringBuffer is a mutable(modifiable) sequence of characters which is in contrast to String class which is an immutable sequence of characters. Thus in case of StringBuffer length and content of the sequence can be changed through certain method calls.

Since StringBuffer is mutable a new String object is not created every time string is modified, which in turn results in less memory consumptions and not having lots of intermediate String object for garbage collection.

StringBuilder class (Added in Java 5),just like StringBuffer, is a mutable(modifiable) sequence of characters which is in contrast to String class which is an immutable sequence of characters. Thus in case of StringBuilder length and content of the sequence can be changed through certain method calls.

You can get the character at a particular index within a string by invoking the charAt() accessor method.

String str = "Example String";
char resChar = str.charAt(3);

Will give char ‘m’. If you want to get more than one consecutive character from a string, you can use the substring method. The substring method has two versions –

String substring(int beginIndex, int endIndex) – Returns a new string that is a substring of this string.

String substring(int beginIndex) – Returns a new string that is a substring of this string.

To find characters or substrings with in a string indexOf() and lastIndexOf() methods can be used.

You can also use contains() method

public boolean contains(CharSequence s) – Returns true if and only if this string contains the specified sequence of char values. Otherwise it returns false.

String provides a split method in order to split the string into one or more substring based on the given  regular expression.

As example If you have a string where one (or more) spaces are used and you want to split it around those spaces.

String str1 = "split example    program";

String[] strArray = str1.split("\s+");

With Java 8 join() method has been added in the String class which makes it very easy to join the multiple strings.

join method has two overloaded versions –

public static String join(CharSequence delimiter, CharSequence… elements) – Returns a new String composed of copies of the CharSequence elements joined together with a copy of the specified delimiter.

public static String join(CharSequence delimiter, Iterable<? extends CharSequence> elements) – Here elements is an Iterable that will have its elements joined together and delimiter is a sequence of characters that is used to separate each of the elements in the resulting String.

Prior to Java 8, you can use DateFormat or SimpleDateFormat class to convert a String to Date In Java or vice-versa. From Java 8 onwards, when you use the new Date and Time API, you can also use the DateTimeFormatter class to convert String to LocalDate, LocalTime, or LocalDateTime class in Java.

Even though both methods can be used to format String and they have same rules the key difference is that format() method returns a formatted String while printf() method print formatted String to console. So, if you need a formatted String, use format method and if you want to print, then use the printf() method.

There are two methods available in java to convert string to integer. One is Integer.parseInt() method and another one is Integer.valueOf() method. Both these methods are static methods of java.lang.Integer class. Both these methods throw NumberFormatException if input string is not a valid integer. The main difference between Integer.parseInt() and Integer.valueOf() method is that parseInt() method returns primitive int where as valueOf() method returns java.lang.Integer object.

Example1:

public class Demo1
{
    public static void main(String[] args) 
    {
        String s = "2015";
         
        int i = Integer.parseInt(s);
         
        System.out.println(i);          //Output : 2015
    }
}

Example2:

public class Demo2
{
    public static void main(String[] args) 
    {
        String s = "2015";
         
        int i = Integer.valueOf(s);
         
        System.out.println(i);          //Output : 2015
    }
}

You are also often need to do the reverse conversion i.e converting from integer to string. Java provides couple of methods to do that also. one is Integer.toString() method and another one is String.valueOf() method. Both these methods return string representation of the given integer.

Example1:

public class Demo1
{
    public static void main(String[] args) 
    {
        int i = 2015;
         
        String s = Integer.toString(i);
         
        System.out.println(s);     //Output : 2015
    }
}

Example2:

public class Demo2
{
    public static void main(String[] args) 
    {
        int i = 2015;
         
        String s = String.valueOf(i);
         
        System.out.println(s);     //Output : 2015
    }
}

Code Snippet:

class Demo 
{ 
    static String count(String str) 
    { 
        // Create an equivalent char array 
        // of given string 
        char[] ch = str.toCharArray(); 
        for (int i = 0; i < ch.length; i++) { 
  
            // k stores index of first character 
            // and i is going to store index of last  
            // character.  
            int k = i; 
            while (i < ch.length && ch[i] != ' ')  
                i++; 
              
            // Swapping 
            char temp = ch[k]; 
            ch[k] = ch[i - 1]; 
            ch[i - 1] = temp; 
  
            // We assume that there is only one space 
            // between two words. 
        } 
        return new String(ch); 
    }
 
    public static void main(String[] args) 
    { 
        String str = "kodnest for freshers"; 
        System.out.println(count(str)); 
    } 
}

When a class has more than one method with same name but different parameters, then we call those methods are overloaded. Overloaded methods will have same name but different number of arguments or different types of arguments.

Method signature is used by the compiler to differentiate the methods. Method signature consist of three things.

a) Method name

b) Number of arguments

c) Types of arguments

Yes. Overloaded methods can be either static or non static.

Compiler uses method signature to check whether the method is overloaded or duplicated. Duplicate methods will have same method signatures i.e same name, same number of arguments and same types of arguments. Overloaded methods will also have same name but differ in number of arguments or else types of arguments

No, compiler will give duplicate method error. Compiler checks only method signature for duplication not the return types. If two methods have same method signature, straight away it gives compile time error.

Yes. Overloaded methods can be synchronized.

Yes, we can overload main() method. A class can have any number of main() methods but execution starts from public static void main(String[] args) only.

Yes, we can declare overloaded methods as final.

public class A
{
    public A()
    {
        //-----> (1)
    }
 
    void A()
    {
        //-----> (2)
    }
}

None of them. It is neither constructor overloaded nor method overloaded. First one is a constructor and second one is a method.

False. Overloading is the best example for static binding.

Yes, we can override a method which is overloaded in super class

Compile-time polymorphism, as it is resolved at compile-time

Static binding, as it is resolved during compile-time

Compile-time polymorphism or Static binding

Access modifiers doesn’t affect method overloading, so overloaded methods can have same or different access levels

Reason is type ambiguity

First of all, we cannot have two same methods with exactly same input parameters. In this case, compiler throws error

It is a compile-time error, as it is resolved during compile-time

Also, it is very difficult for JVM to understand as to which version of overloaded methods to call

Suppose, if we want perform similar kind of tasks and their operation differ only by number of parameters or their data-types or both then method overloading is the best concept to apply

Maintains consistency with method naming for similar type of tasks Increases the readability of the program

This helps the developer to invoke method with same name but changing required arguments in required order with their corresponding data-types

Example: java.lang.String class from java.lang package contains 9 overloaded ‘valueOf()’ method with different number of input parameters or their data-types.

Constructor is a special method given in OOP language for creating and initializing object.

In java , constructor role is only initializing object , and new keyword role is crating object.

1.Constructor name should be same as class name.

2.It should not contain return type.

3.It should not contain Non Access Modifiers:

final ,static, abstract, synchronized

In it logic return statement with value is not allowed.

4.It can have all four accessibility modifiers:

private , public, protected, default

5.It can have parameters

6.It can have throws clause:

7.we can throw exception from constructor.

8.It can have logic, as part of logic it can have all java legal statement except return statement with value.

9.We can not place return in constructor.

Yes, it is allowed to define a method with same class name. No compile time error and no runtime error is raised, but it is not recommended as per coding standards.

No, because compiler and JVM considers it as a method.

By using return type , if there is a return type it is considered as a method else it is considered as constructor.

By using new keyword, if new keyword is used in calling then constructor is executed else method is executed.

As there is a possibility to define a method with same class name , return type is not allowed to constructor to differentiate constructor block from method block.

Every class object is created using the same new keyword , so it must have information about the class to which it must create object .

For this reason constructor name should be same as class name.

a.Yes we can declare constructor as private.

  b.All four access modifiers are allowed to constructor.

  c.We should declare constructor as private for not to allow user to create object from outside of our class.

  d.Basically we will declare private constructor in Singleton design pattern.

No, it is optional . If we do not define a constructor compiler will define a default constructor.

Because it obtain all its default properties from its class.

They are: 1. Its accessibility modifier is same as its class accessibility modifier

2. Its name is same as class name

3. It does not have parameters and logic

Only if there is no explicit constructor defined by developer.

If we want do execute some logic at the time of object creation, that logic may be object initialization logic or some other useful logic.

No. compiler places default constructor only if there is no explicit constructor.

Constructor without any arguments is called no-arg constructor. Default constructor in java is always known as no-arg constructor.

class MyClass

{

public MyClass()

{

//No-arg constructor

}
}

Constructor chaining is the process of calling one constructor from another constructor with respect to current object.

Constructor chaining can be done in two ways:

1.Within same class: It can be done using this() keyword for constructors in same class

2.From base class: by using super() keyword to call constructor from the base class.

Constructor chaining occurs through inheritance. A sub class constructor’s task is to call super class’s constructor first. This ensures that creation of sub class’s object starts with the initialization of the data members of the super class. There could be any numbers of classes in inheritance chain. Every constructor calls up the chain till class at the top is reached.

This process is used when we want to perform multiple tasks in a single constructor rather than creating a code for each task in a single constructor we create a separate constructor for each task and make their chain which makes the program more readable.

No, we can’t use this() and super() in a method.

class SuperClass
{
public SuperClass()
{
System.out.println("Super Class Constructor");
}
}
class SubClass extends SuperClass
{
public SubClass()
{
System.out.println("Sub Class Constructor");

}
void method()
{
this(); //Compile time error
super(); //Compile time error
}
}

‘New’ operator in Java creates the objects. Constructor comes in the later stage in object creation. Constructor’s job is to initialize the members after the object has reserved memory for itself.

“this” keyword is a reference to the current object and can be used for the following –

  •  Passing itself to another method.
  •  Referring to the instance variable when local variable has the same name.
  •  Calling another constructor in constructor chaining.

No. There is no way in java to call sub class constructor from a super class constructor.

It will be treated as a normal method. But compiler gives a warning saying that method has a constructor name.

class MyClass
{
    int MyClass()
    {
        return 0;    //No Compile time error but just a warning
    }
}

It is the technique of making the fields in a class private and providing access to these fields with the help of public methods. If a field is declared private, it cannot be accessed by anyone outside the class, thereby hiding the fields within the class. Therefore encapsulation is also referred to as data hiding.

The main benefit of encapsulation is the ability to modify the implemented code without breaking the code of others who use our code. It also provides us with maintainability, flexibility and extensibility to our code.

  • Abstraction solves the problem at design level while encapsulation solves the problem at implementation level.
  • Abstraction is used for hiding the unwanted data and provide only the required data. On the other hand encapsulation means hiding the code and data into a single unit to protect the data from outside world.
  •  Abstraction lets you focus on what the object does instead of how it does it while Encapsulation means hiding the internal details or mechanics of how an object does something.
  • For example: Outer Look of a Television i.e. it has a display screen and channel buttons to change channel explains ‘abstraction’ but inner implementation detail of a television i.e. how CRT and display screen are connected with each other using different circuits explains ‘encapsulation’.

Encapsulation means combining the data of our application and its manipulation at one place. Encapsulation allows the state of an object to be accessed and modified through behaviour. It reduces the coupling of modules and increases the cohesion inside them.

Encapsulation is nothing but protecting anything which is prone to change. Rational behind encapsulation is that if any functionality which is well encapsulated in code i.e maintained in just one place and not scattered around code is easy to change. This can be better explained with a simple example of encapsulation in Java. We all know that constructor is used to create object in Java and constructor can accept argument. Suppose we have a class ‘Loan’ which has a constructor and in various classes we have created instance of ‘loan’ using this constructor. Now requirements will change and you need to include ‘age of borrower’ as well while taking loan. Since this code is not well encapsulated i.e. not confined in one place you need to change at every place where you are calling this constructor i.e. for one change you need to modify several files instead of just one file which is more error prone and tedious. Though it can be done with refactoring feature of advanced IDE it would prove better if we only need to make change at one place. This is possible if we encapsulate ‘Loan’ creation logic in one method say ‘createLoan()’. The code written for client will call this method and this method internally creates ‘Loan’ object. in this case you only need to modify this method instead of the whole client code.

class Loan
{
private int duration; //private variables examples of encapsulation
private String loan;
private String borrower;
private String salary;

//public constructor can break encapsulation instead use factory method
private Loan(int duration, String loan, String borrower, String salary)
{
this.duration = duration;
this.loan = loan;
this.borrower = borrower;
this.salary = salary;
}

// create loan can encapsulate loan creation logic
public Loan createLoan(String loanType)
{
return loan;
}
}

Below mentioned are few advantages of using encapsulation while writing code in Java or any Object oriented programming language:

  • Encapsulated Code is more flexible and easy to change with inception of new requirements.
  • Encapsulation in Java makes unit testing easy.
  •  Encapsulation in Java allows you to control who can access what.
  •  Encapsulation also helps to write immutable class in Java which is a good choice in multi-threading environment.
  •  Encapsulation reduces coupling of modules and increases cohesion inside a module because all the pieces of one thing are encapsulated in one place.
  • Encapsulation allows you to change one part of code without affecting other part of code.

Anything which can be changed or which is more likely to be changed in near future is candidate of encapsulation. This also helps to write more specific and cohesive code. For instance object creation code, code which can be improved in future like sorting and searching logic.

  • “Whatever changes encapsulate it” is a famous design principle.
  • Encapsulation helps in loose coupling and high cohesion of code.
  • Encapsulation in Java is achieved using access modifiers private, protected and public.
  •  ‘Factory pattern’ and ‘singleton pattern’ in Java makes good use of encapsulation

To achieve encapsulation in Java:

• Declare the variables of a class as ‘private’.

• Provide public setter and getter methods to modify and view the variable’s values


public class EncapTest
{
private String name;
private String idNum;
private int age;
public int getAge()
{
return age;
}
public String getName()
{
return name;
}
public String getIdNum()
{
return idNum;
}
public void setAge( int newAge)
{
age = newAge;
}
public void setName(String newName)
{
name = newName;
}

public void setIdNum( String newId)
{
idNum = newId;
}
}

The command line argument is the argument passed to a program at the time when you run it. To access the command-line argument inside a java program is quite easy, they are stored as string in String array passed to the args parameter of main() method.

Example:

class cmd
{
  public static void main(String[] args)
  {
    for(int i=0;i< args.length;i++)
    {
    System.out.println(args[i]);
    }
  }
}
KodNest cmd

Static is a Non Access Modifier.

Static can be applied to variable, method, nested class and initialization blocks (static block).

A Static variable gets memory allocated only once during the time of class loading.

All the instance of the class share the same copy of the variable, a static variable can be accessed directly by calling “<>.<>” without need to create instance for the class.

value of a static variable will be common for all instances

example:

public class StaticVariableExample 
{
    static int a =10;
    public static void main(String args[]){
        StaticVariableExample s1 = new StaticVariableExample();
        StaticVariableExample s2 = new StaticVariableExample();
        System.out.println("s1.a value :"+s1.a);
        System.out.println("s2.a value :"+s2.a);
        //Change s1 a value alone
        s1.a=20;
        System.out.println("s1.a value :"+s1.a);
        System.out.println("s2.a value :"+s2.a);
    }
}
Output will be
s1.a value :10
s2.a value :10
s1.a value :20
s2.a value :20

note: Local variables cannot be assigned as static it will throw compile time error “illegal start of expression”, as the memory cannot be assigned during class load.

A static method belongs to class rather than object. It can be called directly by using the classname

“<>.<>”

A static method can access static varaibles directly and it cannot access non-staticvariables and can only call a static method directly and it cannot call a non-static method from it.

Only the main() method which is static will be called by the JVM automatically, Not all the static method will be called automatically.

Yes. You can have static block alone in the class without a main method.

Yes, you can overload a static method in Java.

No, you cannot override a static method in Java as there will not be any Run-time Polymorphism happening.

If our main() method is not declared as static then the JVM has to create object first and call which causes the problem of having extra memory allocation.

A static block, is a block of code inside a Java class that will be executed when a class is first loaded in to the JVM. Mostly the static block will be used for initializing the variables.

Static block will be called only one while loading and it cannot have any return type, or any keywords (this or super).

class test
{
	int val;
	static{
      val = 100;
    }
}

Yes, we can have more than one static block in our code. It will be executed in the same order it is written.

In Java only nested classes are allowed to be declared as static, a top level class cannot be declared as static.

Even though static classes are nested inside a class, they doesn’t need the reference of the outer class they act like outer class only.

In general a static method means that “The Method belong to class and not to any particular object” but a constructor is always invoked with respect to an object, so it makes no sense for a constructor to be static.

Suppose when you have a concrete method in a abstract class then that method can be static. Suppose we have a class like below

public class AbstractTest
{
    static void disp()
    {
        System.out.println("disp of static method");
    }
}

Then the disp() can be access by “AbstractTest.disp()”

However, for the same reason cannot be applied when you declare a static method to be abstract. Since static method can be called directly, making it abstract would make it possible to call an undefined method which is of no use, hence it is not allowed.

No, Interface cannot have static methods in it because all methods are implicitly abstract. This is why an interface cannot have a static method.

Yes, an abstract class can have static variables in it.

public class Test
{
    
    public static void main(String[] args)
    {
        welcome();
    }
    
    void welcome()
    {
        System.out.println("Welcom to JavaInterviewPoint");
    }
}

The welcome() method which we tried calling is an instance-level method, we do not have an instance to call it . static methods belong to the class, non-static methods belong to instances of the class and hence it throws the error ” non-static method cannot be referenced from a static context “.

class Test1 
{ 
public
    static void main(String[] args) 
    { 
        int x = 20; 
        System.out.println(x); 
    } 
    static
    { 
        int x = 10; 
        System.out.print(x + " "); 
    } 
}

Answer: 10 20

class Test1 
{ 
    int x = 10; 
public  static void main(String[] args) 
    { 
        System.out.println(x); 
    } 
    static
    { 
        System.out.print(x + " "); 
    } 
}

Answer:  Error

Because , If we are trying to print the instance variable inside the static block or static method without creating class instance then it will give the error : non-static variable x cannot be referenced from a static context.

class Test1 { 
    int x = 10; 
public
    static void main(String[] args) 
    { 
        Test1 t1 = new Test1(); 
        System.out.println(t1.x); 
    } 
    static
    { 
        int x = 20; 
        System.out.print(x + " "); 
    } 
}

Answer: 20 10

Because We can print the instance variable inside the static method after creating the class reference.

class Test1 { 
    int x = 10; 
public
    static void main(String[] args) 
    { 
        System.out.println(Test1.x); 
    } 
    static
    { 
        int x = 20; 
        System.out.print(x + " "); 
    } 
}

Answer: Error

Because We can not access the instance variable with class name. otherwise it will give the error : non-static variable x cannot be referenced from a static context


class Test1 { 
    static int x = 10; 
public
    static void main(String[] args) 
    { 
        Test1 t1 = new Test1(); 
        Test1 t2 = new Test1(); 
  
        t1.x = 20; 
        System.out.print(t1.x + " "); 
        System.out.println(t2.x); 
    } 
}

Answer: 20 20

Because static variable is class level variable. if we do update in any reference then automatically all pointing reference values are changed.

class Test1 { 
    static int i = 1; 
public static void main(String[] args) 
    { 
        for (int i = 1; i < 10; i++) { 
            i = i + 2; 
            System.out.print(i + " "); 
        } 
    } 
}

Answer: 3 6 9

Here local variables are printed after execution. If we want to execute static variables, then we write Test1.i or we write Test1 object.i.

class Test1 
{ 
    static int i = 1; 
public static void main(String[] args) 
    { 
        int i = 1; 
        for (Test1.i = 1; Test1.i < 10; Test1.i++) { 
            i = i + 2; 
            System.out.print(i + " "); 
        } 
    } 
}

Answer: 3 5 7 9 11 13 15 17 19

Because , Here, two different i copies of variable are declared, one is static and other one is local. If we write Test1.i then, static variable is executed and if we write only i, then local variable are executed.

class Test1 { 
    static int i = 1; 
public static void main(String[] args) 
    { 
        static int i = 1; 
        for (Test1.i = 1; Test1.i < 10; Test1.i++) { 
            i = i + 2; 
            System.out.print(i + " "); 
        } 
    } 
}

Answer:  Error

Because We can not declare the static variable inside the block. If we declare static variable inside the block, then we will get the compile time error : illegal start of expression.

class Test1
 { 
public static void main(String[] args) 
    { 
        static int arr1[] = { 11, 22, 33 }; 
        static int arr2[] = { 11, 22, 33, 44, 55 }; 
        static int ptr[]; 
        ptr = arr1; 
        arr1 = arr2; 
        arr2 = ptr; 
        System.out.print(arr1.length + " "); 
        System.out.println(arr2.length); 
    } 
}

Answer: Error

Because, Here we are trying to declare array as static type but we can not declare the local array as static type. If we will try to declare the local variable as static, then will get error : illegal start of expression.

Inheritance is an Object oriented feature which allows a class to inherit behavior and data from other class.

For example, a class Car can extend basic feature of Vehicle class by using Inheritance.

One of the most intuitive examples of Inheritance in the real world is Father-Son relationship, where Son inherits Father’s property.

Java supports single Inheritance, multi-level inheritance and at some extent multiple inheritances because Java allows a class to only extend another class, but an interface in Java can extend multiple inheritances.

Inheritance is used for code reuse and leveraging Polymorphism by creating a type hierarchy.

It’s better to use Inheritance for type declaration but for code reuse composition is a better option because it’s more flexible.

You can use Inheritance in Java by extending classes and implementing interfaces.

Java provides two keywords extends and implements to achieve inheritance. 

A class which is derived from another class is known as a subclass and an interface which is derived from another interface is called subinterface.

A class which implements an interface is known as implementation.

You can use either extends of implements keyword to implement Inheritance in Java. A class extends another class using extends keyword, an interface can extend another interface using extend keyword, and a class can implement an interface using implements keyword in Java.

Inheritance is an object oriented concept which creates a parent-child relationship.

It is one of the ways to reuse the code written for parent class but it also forms the basis of Polymorphism.

On the other hand, Encapsulation is an object oriented concept which is used to hide the internal details of a class e.g. HashMap encapsulate how to store elements and how to calculate hash values.

Abstraction is an object oriented concept which is used to simply things by abstracting details. It helps in the designing system.

On the other hand, Inheritance allows code reuse. You can reuse the functionality you have already coded by using Inheritance.

Both Polymorphism and Inheritance goes hand on hand, they help each other to achieve their goal. Polymorphism allows flexibility, you can choose which code to run at runtime by overriding.

  • The Composition is more flexible because you can change the implementation at runtime by calling setXXX() method, but Inheritance cannot be changed i.e. you cannot ask a class to implement another class at runtime.
  • Composition builds HAS-A relationship while Inheritance builds IS-A relationship e.g. A Room HAS A Fan, but Mango IS-A Fruit.
  • The parent-child relationship is best represented using Inheritance but If you just want to use the services of another class use Composition.

No, you cannot override a static method in Java because it’s resolved at compile time.

In order for overriding to work, a method should be virtual and resolved at runtime because objects are only available at runtime.

Yes, you can overload a static method in Java. Overloading has nothing to do with runtime but the signature of each method must be different. In Java, to change the method signature, you must change either number of arguments, type of arguments or order of arguments.

No, you cannot override a private method in Java because the private method is not inherited by the subclass in Java, which is essential for overriding. In fact, a private method is not visible to anyone outside the class and, more importantly, a call to the private method is resolved at compile time by using Type information as opposed to runtime by using the actual object.

Since the static method cannot be overridden in Java, but if you declare the same static method in subclass then that would hide the method from the superclass. It means, if you call that method from subclass then the one in the subclass will be invoked but if you call the same method from superclass then the one in superclass will be invoked. This is known as method hiding in Java.

Yes, A class can implement more than one interface in Java e.g. A class can be both Comparable and Serializable at the same time. This is why the interface should be the best use for defining Type as described in Effective Java. This feature allows one class to play a polymorphic role in the program.

No, a class can only extend just one more class in Java. Though Every class also, by default extend the java.lang.Object class in Java.

Yes, unlike classes, an interface can extend more than one interface in Java. There are several example of this behavior in JDK itself e.g. java.util.List interface extends both Collection and Iterable interface to tell that it is a Collection as well as it allows iteration via Iterator.

In this case, a conflict will arise because the compiler will not able to link a method call due to ambiguity. You will get a compile time error in Java.

Yes, you can pass that because subclass and superclass are related to each other by Inheritance which provides IS-A property.

The Liskov substitution principle is one of the five object-oriented design principles, collectively know as SOLID principles. This design principle is L of SOLID acronym. The Liskov substitution principle states that in an object oriented program if a function or method is expecting an object of base class then it should work fine with a derived class object as well. If it cannot function properly with derived class object then the derived class is violating the Liskov Substitution principle.

For example, if a method is expecting a List you can also pass ArrayList or LinkedList and it should work just fine because ArrayList and LinkedList both follow Liskov Substitution Principle, but the java.sql.Date which is a subclass of java.util.Date in Java violates Liskov Substitution Principle because you cannot pass an object of java.sql.Date class to a method which is expecting an object of java.util.Date, Why? because all time-related method will throw java.lang.UnsupportedOperationException.

Here is another example of violating The Liskov Substitution Principle, Square is a special type of Rectangle whose adjacent sides are equal but making Square extending Rectangle violates LSP principle.

You can call a method of the subclass by first casting the object hold by reference variable of  superclass into the subclass. Once you hold the object in subclass reference type, you can call methods from the subclass.

False. Abstract methods can also have concrete methods.

Not necessarily. Abstract class may or may not have abstract methods.

No. Constructor, Static Initialization Block, Instance Initialization Block and variables can not be abstract.

No, We can’t instantiate a class once it is declared as abstract even though it does not have abstract methods.

No. Abstract methods can not be private. If abstract methods are allowed to be private, then they will not be inherited to sub class and will not get enhanced.

It is because, we can’t create objects to abstract classes but we can create objects to their sub classes. From sub class constructor, there will be an implicit call to super class constructor. That’s why abstract classes should have constructors. Even if you don’t write constructor for your abstract class, compiler will keep default constructor.

No, abstract methods can not be static.

Yes, a class can have abstract class as it’s member.

True. Abstract classes can be nested i.e an abstract class can have another abstract class as it’s member.

No, abstract methods can not be declared as synchronized. But methods which override abstract methods can be declared as synchronized.

Yes. Local inner class can be abstract.

Yes. Abstract methods can be declared with throws clause.

There are mainly three reasons to use interface. They are given below.

• It is used to achieve fully abstraction.

• By interface, we can support the functionality of multiple inheritance.

• It can be used to achieve loose coupling.

An interface in java is a blueprint of a class. It has static constants and abstract methods only.

The interface in java is a mechanism to achieve fully abstraction. There can be only abstract methods in the java interface not method body. It is used to achieve fully abstraction and multiple inheritance in Java.

Java Interface also represents IS-A relationship.

It cannot be instantiated just like abstract class.

As shown in the figure given below, a class extends another class, an interface extends another interface but a class implements an interface.

KodNest cc

If a class implements multiple interfaces, or an interface extends multiple interfaces i.e. known as multiple inheritance

KodNest int

Example:

terface Printable{
void print();
}

interface Showable{
void show();
}

class A implements Printable,Showable{

public void print(){System.out.println("Hello");}
public void show(){System.out.println("Welcome");}

public static void main(String args[]){
A obj = new A();
obj.print();
obj.show();
}
}

Output: Hello
Welcome

Multiple inheritance is not supported in case of class. But it is supported in case of interface because there is no ambiguity as implementation is provided by the implementation class.

For example:

interface Printable{
void print();
}
interface Showable{
void print();
}

class TestTnterface1 implements Printable,Showable
{
public void print()
{
System.out.println("Hello");
}
public static void main(String args[])
{
TestTnterface1 obj = new TestTnterface1();
obj.print();
}
}


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

An interface that have no member is known as 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.

public interface Serializable
{
}

An interface can have another interface known as nested interface.

Example:

interface printable{
void print();
interface MessagePrintable{
void msg();
}
}

As stated above, S.O.L.I.D represents five principles of Java which are:

S: Single responsibility principle

O: Open-closed principle

L: Liskov substitution principle

I: Interface segregation principle

D: Dependency inversion principle

Single Responsibility Principle (SRP)

According to the single responsibility principle, there should be only one reason due to which a class has to be changed. It means that a class should have one task to do. This principle is often termed as subjective.

The principle can be well understood with an example. Imagine there is a class which performs following operations.

connected to a database

read some data from database tables

finally, write it to a file.

Have you imagined the scenario? Here the class has multiple reasons to change, and few of them are the modification of file output, new data base adoption. When we are talking about single principle responsibility, we would say, there are too many reasons for the class to change; hence, it doesn’t fit properly in the single responsibility principle.

Open Closed Principle

According to open closed principle, entities or objects should remain open for extension, but they should stay closed for modification. To be precise, according to this principle, a class should be written in such a manner that it performs its job flawlessly without the assumption that people in the future will simply come and change it. Hence, the class should remain closed for modification, but it should have the option to get extended. Ways of extending the class include:

1.Inheriting from the class

2.Overwriting the required behaviors from the class

3.Extending certain behaviors of the class

An excellent example of open closed principle can be understood with the help of browsers. Do you remember installing extensions in your chrome browser?

Basic function of chrome browser is to surf different sites. Do you want to check grammar when you are writing an email using chrome browser?If yes, you can simply use Grammarly extension, it provides you grammar check on the content.

This mechanism where you are adding things for increasing the functionality of the browser is an extension.  Hence, the browser is a perfect example of functionality that is open for extension but is closed for modification. In simple words, you can enhance the functionality by adding/installing plugins on your browser, but cannot build anything new.

Liskov Substitution Principle

Liskov substitution principle assumes q(x) to be a property, provable about entities of x which belongs to type T. Now, according to this principle, the q (y) should be now provable for objects y that belongs to type S, and the S is actually a subtype of T. Are you now confused and don’t know what Liskov substitution principle actually mean? The definition of it might be a bit complex, but in fact, it is quite easy. The only thing is that every subclass or derived class should be substitutable for their parent or base class.

You can say that it is a unique object-oriented principle. The principle can further be simplified by understanding this principle; a child type of a particular parent type without making any complication or blowing things up should have the ability to stand in for that parent.This principle is closely related to Liskov Substitution principle.

Interface Segregation Principle

According to interface segregation principle, a client, no matter what should never be forced to implement an interface that it does not use or the client should never be obliged to depend on any method, which is not used by them.

So basically, the interface segregation principles as you prefer the interfaces, which are small but client specific instead of monolithic and bigger interface.

In short, it would be bad for you to force the client to depend on a certain thing, which they don’t need.

Let us now again take an example to understand this.

Let’s take a simple example. You are implementing your own ArrayList and LinkedList in java. You create an interface called List which both classes will implement.

public interface List {
	public T get();
	public void add(T t);
	public T poll();
	public T peek();	
}

Let’s create LinkedList class now.

public class LinkedList implements List{
 
	@Override
	public Integer get() {
		// Implement this method
		return null;
	}
 
	@Override
	public void add(Integer t) {
		// Implement this method
	}
 
	@Override
	public Integer poll() {
		// Implement this method
		return null;
	}
 
	@Override
	public Integer peek() {
		// Implement this method
		return null;
	}
}
 
public class ArrayList implements List{
 
	@Override
	public Integer get() {
		// Implement this method
		return null;
	}
 
	@Override
	public void add(Integer t) {
		// Implement this method
	}
 
	@Override
	public Integer poll() {
		// ArrayList does not require this method
		return null;
	}
 
	@Override
	public Integer peek() {
		// ArrayList does not require this method
		return null;
	}
}
 

Do you see the problem, even though you do not require poll and peek method in ArrayList, we have implemented them.

The correct solution for above problem will be:

public interface Deque {
	public T poll();
	public T peek();	
}
 

And remove peek and poll from list interface.

public interface List {
	public T get();
	public void add(T t);	
}

Let’s change LinkedList class now.

public class LinkedList implements List,Deque{
 
	@Override
	public Integer get() {
		// Implement this method
		return null;
	}
 
	@Override
	public void add(Integer t) {
		// Implement this method
	}
 
	@Override
	public Integer poll() {
		// Implement this method
		return null;
	}
 
	@Override
	public Integer peek() {
		// Implement this method
		return null;
	}
}
 
Let’s change ArrayList class now.

public class ArrayList implements List{
 
	@Override
	public Integer get() {
		// Implement this method
		return null;
	}
 
	@Override
	public void add(Integer t) {
		// Implement this method
	}
}

As you can see, we have segregated two interface to achieve required functionality.

Dependency Inversion Principle

According to this, dependency inversion principle, entities should depend only on abstractions but not on concretions. According to it, the high-level module must never rely on any low-level module but should depend on abstractions. Let us again understand it through another practical example.

You go to a local store to buy something, and you decide to pay for it by using your debit card. So, when you give your card to the clerk for making the payment, the clerk doesn’t bother to check what kind of card you have given. Even if you have given a Visa card, he will not put out a Visa machine for swiping your card. The type of credit card or debit card that you have for paying does not even matter; they will simply swipe it. So, in this example, you can see that both you and the clerk are dependent on the credit card abstraction and you are not worried about the specifics of the card. This is what a dependency inversion principle is.

class X
{
    //Class X Members
}
 
class Y
{
    //Class Y Members
}
 
class Z extends X, Y
{
    //Class Z Members
}

Answer :

In Java, a class can not extend more than one class. Class Z is extending two classes – Class X and Class Y. It is a compile time error in java.

class A
{
    int i = 10;
}
 
class B extends A
{
    int i = 20;
}
 
public class MainClass
{
    public static void main(String[] args)
    {
        A a = new B();
 
        System.out.println(a.i);
    }
}

Answer :

10

class A
{
    {
        System.out.println(1);
    }
}
 
class B extends A
{
    {
        System.out.println(2);
    }
}
 
class C extends B
{
    {
        System.out.println(3);
    }
}
 
public class MainClass
{
    public static void main(String[] args)
    {
        C c = new C();
    }
}

Answer :

1

2

3

No. A class can not extend itself.

class A
{
    String s = "Class A";
}
 
class B extends A
{
    String s = "Class B";
 
    {
        System.out.println(super.s);
    }
}
 
class C extends B
{
    String s = "Class C";
 
    {
        System.out.println(super.s);
    }
}
 
public class MainClass
{
    public static void main(String[] args)
    {
        C c = new C();
 
        System.out.println(c.s);
    }
}

Answer :

Class A

Class B

Class C

class A
{
    static
    {
        System.out.println("THIRD");
    }
}
 
class B extends A
{
    static
    {
        System.out.println("SECOND");
    }
}
 
class C extends B
{
    static
    {
        System.out.println("FIRST");
    }
}
 
public class MainClass
{
    public static void main(String[] args)
    {
        C c = new C();
    }
}

Answer :

THIRD

SECOND

FIRST

class A
{
    public A()
    {
        System.out.println("Class A Constructor");
    }
}
 
class B extends A
{
    public B()
    {
        System.out.println("Class B Constructor");
    }
}
 
class C extends B
{
    public C()
    {
        System.out.println("Class C Constructor");
    }
}
 
public class MainClass
{
    public static void main(String[] args)
    {
        C c = new C();
    }
}

Answer :

Class A Constructor

Class B Constructor

Class C Constructor

false. Private members are not inherited to sub class.

class X
{
    static void staticMethod()
    {
        System.out.println("Class X");
    }
}
 
class Y extends X
{
    static void staticMethod()
    {
        System.out.println("Class Y");
    }
}
 
public class MainClass
{
    public static void main(String[] args)
    {
        Y.staticMethod();
    }
}

Answer :

Class Y


class X
{
    public X(int i)
    {
        System.out.println(1);
    }
}
 
class Y extends X
{
    public Y()
    {
        System.out.println(2);
    }
}

Answer :

Write explicit calling statement to super class constructor in Class Y constructor.

Correction code is given below.

class X
{
    public X(int i)
    {
        System.out.println(1);
    }
}
 
class Y extends X
{
    public Y()
    {
        super(10);          //Correction
 
        System.out.println(2);
    }
}

Polymorphism is the ability of an object to take on many forms. The most common use of polymorphism in OOP occurs when a parent class’s reference is used to refer to a child class object.

Method overloading increases the readability of the program. On the other hand, method overriding provides the specific implementation of the method that is already provided by its super class. Parameter must be different in case of overloading whereas it must be same in case of overriding.

ava has excellent support of polymorphism in terms of ‘inheritance’, ‘method overloading’ and ‘method overriding’.

‘Method overriding’ allows Java to invoke method based on a particular object at run-time instead of declared type while coding

Example:

public class TradingSystem{
public String getDescription(){
return "electronic trading system";
    }
  }
public class DirectMarketAccessSystem extends TradingSystem{
public String getDescription(){
return "direct market access system";
   }
 }
public class CommodityTradingSystem extends TradingSystem{
public String getDescription(){
 return "Futures trading system";
 }
 }

Here we have a super class called ‘TradingSystem’ and there two implementation ‘DirectMarketAccessSystem’ and ‘CommodityTradingSystem’. Here we will write a code which is flexible enough to work with. Any future implementation of ‘TradingSystem’ can be achieved by using Polymorphism in Java .

Its common practice to always replace concrete implementation with interface, but it’s not that easy and it comes with practice but here are some common places where we can check for polymorphism:

1) Method argument:

Always use super type in method argument that will give you leverage to pass any implementation while invoking method. For example:

public void showDescription(TradingSystem tradingSystem)
{
tradingSystem.description();
}

2) Variable names:

Always use Super type while you are storing reference returned from any Factory method in Java. This gives you flexibility to accommodate any new implementation from Factory. Here is an example of polymorphism while writing Java code which you can use while retrieving reference from Factory:

String systemName = Configuration.getSystemName();

TradingSystem system = TradingSystemFactory.getSystem(systemName);

3) Return type of method

Return type of any method is another place where you should be using interface to take advantage of Polymorphism in Java. In fact this is a requirement of Factory design pattern in Java to use interface as return type for factory method.

public TradingSystem getSystem(String name){
//code to return appropriate implementation
}

You cannot override a private or static method in Java. If you create a similar method with same return type and same method arguments in child class then it will hide the super class method; this is known as method hiding. Similarly, you cannot override a private method in sub class because it’s not accessible there. What you can do is create another private method with the same name in the child class.

Example:

class Base {
private static void display() {
System.out.println("Static or class method from Base");
}
public void print() {
System.out.println("Non-static or instance method from Base");
}
class Derived extends Base {
private static void display() {
System.out.println("Static or class method from Derived");
}
public void print() {
System.out.println("Non-static or instance method from Derived");
}
public class test {
public static void main(String args[])
{
Base obj= new Derived();
obj1.display();
obj1.print();
}
}

Association is a relationship where all object have their own lifecycle and there is no owner. Let’s take an example of Teacher and Student. Multiple students can associate with a single teacher and a single student can associate with multiple teachers but there is no ownership between the objects and both have their own lifecycle. These relationship can be one to one, One to many, many to one and many to many.

Aggregation is a specialized form of Association where all object have their own lifecycle but there is ownership and child object can not belongs to another parent object. Let’s take an example of Department and teacher. A single teacher can not belongs to multiple departments, but if we delete the department teacher object will not destroy.

Composition is again specialized form of Aggregation and we can call this as a “death” relationship. It is a strong type of Aggregation. Child object dose not have their lifecycle and if parent object deletes all child object will also be deleted. Let’s take again an example of relationship between House and rooms. House can contain multiple rooms there is no independent life of room and any room can not belongs to two different house if we delete the house room will automatically delete.

Aggregation represents the weak relationship whereas composition represents the strong relationship. For example, the bike has an indicator (aggregation), but the bike has an engine (composition).

By using final keyword we can make

• Final class

• Final method

• Final variables

• If we declare any class as final we can not extend that class

• If we declare any method as final it can not be overridden in sub class

• If we declare any variable as final its value unchangeable once assigned

Abstract methods must be overridden in sub class where as final methods can not be overridden in sub class.

  •  If a class needs some security and it should not participate in inheritance in this scenario we need to use final class.
  • We can not extend final class.
  • No. Its not possible to declare a final variable without initial value assigned.
  • While declaring itself we need to initialize some value and that value can not be change at any time.

No.Constructors can not be final.

No We can not declare interface as final because interface should be implemented by some class so its not possible to declare interface as final.

Compile time error will come :Cannot override the final method from Super class.

Yes we can create object for final class.

final keyword in java is used to make any class or a method or a field as unchangeable. You can’t extend a final class, you can’t override a final method and you can’t change the value of a final field. final keyword is used to achieve high level of security while coding.

Uninitialized final field is called blank final field.

Whenever necessary especially if you want to do equality check or want to use your object as key in HashMap.

Yes, we can change the state of an object to which a final reference variable is pointing, but we can’t re-assign a new object to this final reference variable.

Abstract methods must be overridden in the sub classes and final methods are not at all eligible for overriding.

A final class is very useful when you want a high level of security in your application. If you don’t want inheritance of a particular class, due to security reasons, then you can declare that class as a final.

No, we can’t change the value of an interface field. Because interface fields, by default, are final and static. They remain constant for whole execution of a program.

final class is a class that can not be extended.

final method is a method that can not be overridden in the sub class.

final variable is a variable that can not change it’s value once it is initialized.

No. Only final local variables can be used inside a local inner class.

No, constructors can not be final.

Exception is an abnormal condition which occurs during the execution of a program and disrupts normal flow of the program. This exception must be handled properly. If it is not handled, program will be terminated abruptly.

Exceptions in java are handled using try, catch and finally blocks.

try block : The code or set of statements which are to be monitored for exception are kept in this block.

catch block : This block catches the exceptions occurred in the try block.

finally block : This block is always executed whether exception is occurred in the try block or not and occurred exception is caught in the catch block or not.

Errors are mainly caused by the environment in which an application is running. For example, OutOfMemoryError happens when JVM runs out of memory. Where as exceptions are mainly caused by the application itself. For example, NullPointerException occurs when an application tries to access null object.

No. We shouldn’t write any other statements in between try, catch and finally blocks. They form a one unit.

try
{
    // Statements to be monitored for exceptions
}
  
//You can't keep statements here
  
catch(Exception ex)
{
    //Cathcing the exceptions here
}
  
//You can't keep statements here
  
finally
{
    // This block is always executed
}

No, It shows compilation error. The try block must be followed by either catch or finally block. You can remove either catch block or finally block but not both.

When you are keeping multiple catch blocks, the order of catch blocks must be from most specific to most general ones. i.e sub classes of Exception must come first and super classes later. If you keep super classes first and sub classes later, compiler will show unreachable catch block error.

public class ExceptionHandling
{
    public static void main(String[] args)
    {
        try
        {
            int i = Integer.parseInt("abc");   //This statement throws NumberFormatException
        }
  
        catch(Exception ex)
        {
            System.out.println("This block handles all exception types");
        }
  
        catch(NumberFormatException ex)
        {
            //Compile time error
            //This block becomes unreachable as
            //exception is already caught by above catch block
        }
    }
}
KodNest EH

Throwable class is the super class of all the exception types. Below Throwable class there are two subclasses which denotes two distinct branches of exceptions –

Exception – An Exception indicates that a problem has occurred, but it is not a serious system problem. The user programs you write will throw and catch Exceptions.

Error – It defines exceptions that are not expected to be caught by your program. Exceptions of type Error are used by the Java run-time system to indicate errors having to do with the run-time environment, itself.

Examples of error are StackOverflowError, OutOfMemoryError etc.

Below Exception there is a distinct subclass RunTimeExcpetion – RunTimeExcpetion and its descendants denote the exceptional conditions that are external to the application, and the application usually cannot anticipate or recover from them.

The exceptions which occur at run time are called as run time exceptions. These exceptions are unknown to compiler. All sub classes of java.lang.RunTimeException and java.lang.Error are run time exceptions. These exceptions are unchecked type of exceptions. For example, NumberFormatException, NullPointerException, ClassCastException, ArrayIndexOutOfBoundException, StackOverflowError etc.

OutOfMemoryError is the sub class of java.lang.Error which occurs when JVM runs out of memory.

Checked exceptions are the exceptions which are known to compiler. These exceptions are checked at compile time only. Hence the name checked exceptions. These exceptions are also called compile time exceptions. Because, these exceptions will be known during compile time.

Unchecked exceptions are those exceptions which are not at all known to compiler. These exceptions occur only at run time. These exceptions are also called as run time exceptions. All sub classes of java.lang.RunTimeException and java.lang.Error are unchecked exceptions.

No, it gives unreachable code error. Because, control is returning from the finally block itself. Compiler will not see the statements after it. That’s why it shows unreachable code error.

Yes, finally block will be always executed no matter whether try or catch blocks are returning the control or not.

Yes, we can throw an exception manually using throw keyword.

Example:

try
{
    NumberFormatException ex = new NumberFormatException();    
//Creating an object to NumberFormatException explicitly throw ex;
//throwing NumberFormatException object explicitly using throw keyword } catch(NumberFormatException ex) { System.out.println("explicitly thrown NumberFormatException object will be caught here"); }

Exceptions raised in the try block are handled in the catch block. If it is unable to handle that exception, it can re-throw that exception using throw keyword. It is called re-throwing an exception.

try
{
    String s = null;
    System.out.println(s.length());  //This statement throws nullPointerException
}
catch(NullPointerException ex)
{
    System.out.println("NullPointerException is caught here");
  
    throw ex;     //Re-throwing NullPointerException
}

Because finally block is always executed whether exceptions are raised in the try block or not and raised exceptions are caught in the catch block or not. By keeping the clean up operations in finally block, you will ensure that those operations will be always executed irrespective of whether exception is occurred or not.

No. If a super class method is throwing an unchecked exception, then it can be overridden in the sub class with same exception or any other unchecked exceptions but can not be overridden with checked exceptions.

StackOverflowError is an error which is thrown by the JVM when stack overflows.

No. If a super class method is throwing an unchecked exception, then it can be overridden in the sub class with same exception or any other unchecked exceptions but can not be overridden with checked exceptions.

java.lang.Throwable is the super class for all types of errors and exceptions in java.

1) 
try { 
      //try block 
     } 
catch(Exception ex) {
 //catch block 
} 
2) try {
         //try block
       } 
finally 
       { 
        //finally block
        } 
3) try { 
//try block
 } 
catch(Exception ex) {
 //catch block
 }
 finally { 
   //finally block 
}

printStackTrace() method is used to print the detailed information about the exception occurred.

ClassNotFoundException, SQLException, IOException

NullPointerException, ArrayIndexOutOfBoundsException, NumberFormatException.

Exception and Error classes are both subclasses of the Throwable class. The Exception class is used for exceptional conditions that a user’s program should catch. The Error class defines exceptions that are not excepted to be caught by the user program.

The throw keyword is used to explicitly raise a exception within the program. On the contrary, the throws clause is used to indicate those exceptions that are not handled by a method. Each method must explicitly specify which exceptions does not handle, so the callers of that method can guard against possible exceptions. Finally, multiple exceptions are separated by a comma.

A finally block will be executed whether or not an exception is thrown and is used to release those resources held by the application. Finalize is a protected method of the Object class, which is called by the Java Virtual Machine (JVM) just before an object is garbage collected.

A try-catch-finally block can reside inside another try-catch-finally block that is known as nested try statement.

public class NestedTryDemo {
    public static void main(String[] args) {
        try{
            System.out.println("In Outer try block");
            try{
                System.out.println("In Inner try block");
                int a = 7 / 0;
            }catch (IllegalArgumentException e) {
                System.out.println("IllegalArgumentException caught");
            }finally{
                System.out.println("In Inner finally");
            }
        }catch (ArithmeticException e) {
            System.out.println("ArithmeticException caught");
        }finally {
            System.out.println("In Outer finally");
        }
    }
}

There might be a case when a code enclosed with in a try block throws more than one exception. To handle these types of situations, two or more catch clauses can be specified where each catch clause catches a different type of exception. When an exception is thrown, each of the catch statement is inspected in order, and the first one whose type matches that of the thrown exception is executed.

Example : code snippet

int a[] = {0};
 try{
     int b = 7/a[i];
 }catch(ArithmeticException aExp){
     aExp.printStackTrace();
 }catch(ArrayIndexOutOfBoundsException aiExp){
     aiExp.printStackTrace();
 }

When an exceptional condition occurs within a method, the method (where the exception occurred) creates an Exception Object and throws it. The created exception object contains information about the error, its type and the state of the program when the error occurred.

The method where the exception is thrown may handle that exception itself or pass it on. In case it passes it on, run time system goes through the method hierarchy that had been called to get to the current method to search for a method that can handle the exception.

If your program is not able to catch any particular exception, that will ultimately be processed by the default handler. This process of going through the method stack is known as Exception propagation.

final – final keyword is used to restrict in some way. It can be used with variables, methods and classes. When a variable is declared as final, its value can not be changed once it is initialized. Except in case of blank final variable, which must be initialized in the constructor.

If you make a method final in Java, that method can’t be overridden in a sub class.

If a class is declared as final then it can not be sub classed.

finally – finally is part of exception handling mechanism in Java. finally block is used with try-catch block. finally block is always executed whether any exception is thrown or not and raised exception is handled in catch block or not. Since finally block always executes thus it is primarily used to close the opened resources like database connection, file handles etc.

finalize() – finalize() method is a protected method of java.lang.Object class. Since it is in Object class thus it is inherited by every class. This method is called by garbage collector thread before removing an object from the memory. This method can be overridden by a class to provide any cleanup operation and gives object final chance to cleanup before getting garbage collected.

protected void finalize() throws Throwable
{
    //resource clean up operations
}

There are certain restrictions while overriding a method in case of exception handling in Java.

1.If superclass method has not declared any exception using throws clause then subclass overridden method can’t declare any checked exception though it can declare unchecked exception.

2.If superclass method has declared an exception using throws clause then subclass overridden method can do one of the three things.

a) sub-class can declare the same exception as declared in the super-class method.

b)subclass can declare the subtype exception of the exception declared in the superclass method.

c) But subclass method can not declare any exception that is up in the hierarchy than the exception declared in the super class method.

subclass method can choose not to declare any exception at all.

class Parent{
   public void displayMsg() throws IOException{
     System.out.println("In Parent displayMsg()");
    throw new IOException("Problem in method - displayMsg - Parent");
   }
}
public class ExceptionOverrideDemo extends Parent
{
public void displayMsg() throws Exception
{  
System.out.println("In ExceptionOverrideDemo displayMsg()"); 
throw new Exception("Problem in method - displayMsg - ExceptionOverrideDemo");
}  
}

Here parent class had declared IOException where as subclass has declared Exception. Exception is the super class of IOException thus it is wrong according to the rules of method overriding and exception handling. Thus the code will give compiler error.

Before Java 7 multi-catch statement, if two or more exceptions were handled in the same way, we still had to write separate catch blocks for handling them.

catch(IOException exp){
    logger.error(exp);
    throw exp;
  }catch(SQLException exp){
    logger.error(exp);
    throw exp;
  }

With Java 7 and later it is possible to catch multiple exceptions in one catch block, which eliminates the duplicated code. Each exception type within the multi-catch statement is separated by Pipe symbol (|).

catch(IOException | SQLException exp){
    logger.error(exp);
    throw exp;
}

Java 7 introduced a new form of try known as try-with-resources for Automatic Resource Management (ARM). Here resource is an object that must be closed after the program is finished with it. Example of resources would be an opened file handle or database connection etc.

Before the introduction of try-with-resources we had to explicitly close the resources once the try block completes normally or abruptly.

try {
    br = new BufferedReader(new FileReader("C:\test.txt"));
    System.out.println(br.readLine());
} catch (IOException e) {
    e.printStackTrace();
} finally {
    try {
        if (br != null){
            System.out.println("Closing the file");
            br.close();
        }
                    
    } catch (IOException ex) {
        ex.printStackTrace();
    }
}

try-with-resources helps in reducing such boiler plate code. Let’s see the same example using try-with-resources.

try(BufferedReader br = new BufferedReader(new FileReader("C:\test.txt"))) {            
    System.out.println(br.readLine());
} catch (IOException e) {
    e.printStackTrace();
}

According to Java Docs, you should write your own exception classes if you answer yes to any of the following questions; otherwise, you can probably use someone else’s.

1.Do you need an exception type that isn’t represented by those in the Java platform?

2.Would it help users if they could differentiate your exceptions from those thrown by classes written by other vendors?

3.Does your code throw more than one related exception?

4.if you use someone else’s exceptions, will users have access to those exceptions? A similar question is, should your package be independent and self-contained?

Exception matching is the process by which the the jvm finds out the matching catch block for the exception thrown from the list of catch blocks. When an exception is thrown, Java will try to find by looking at the available catch clauses in the top down manner. If it doesn’t find one, it will search for a handler for a supertype of the exception. If it does not find a catch clause that matches a supertype for the exception, then the exception is propagated down the call stack. This process is called as exception matching.

If a method does not throw a checked exception directly but calls a method that throws an exception then the calling method must handle the ‘throw’ exception or declare the exception in its ‘throws’ clause. If the calling method does not handle it and declares the exception, the exceptions is passed to the next method in the method stack. This is called as ducking the exception down the method stack. e.g. The code below will not compile as the getCar() method has not declared the ‘CarNotFoundException’ which is thrown by the getColor () method.

void getCar()
{
getColor();
}
void getColor()
{
throw new CarNotFoundException();
}
//Fix for the above code is
void getCar() throws CarNotFoundException
{
getColor();
}
void getColor()
{
throw new CarNotFoundException();
}

An empty catch block is considered legal by leaving the catch block without writing any actual code to handle the exception caught.

  • Thread are light weight process.
  • Threads consumes CPU in best possible manner, hence enables multi processing. Multi threading reduces idle time of CPU which improves performance of application.
  • A thread class belongs to java.lang package.
  • We can create multiple threads in java, even if we don’t create any Thread, one Thread at least  do exist i.e. main thread.
  • Multiple threads run parallely in java. 
  • Threads have their own stack.

One process can have multiple Threads,

Thread are subdivision of Process. One or more Threads runs in the context of process. Threads can execute any part of process. And same part of process can be executed by multiple Threads.

Processes have their own copy of the data segment of the parent process while Threads have direct access to the data segment of its process.

Processes have their own address while Threads share the address space of the process that created it.

Process creation needs whole lot of stuff to be done, we might need to copy whole parent process, but Thread can be easily created.

Processes can easily communicate with child processes but interprocess communication is difficult. While, Threads can easily communicate with other threads of the same process using wait() and notify() methods.

In process all threads share system resource like heap Memory etc. while Thread has its own stack.

Any change made to process does not affect child processes, but any change made to thread can affect the behaviour of the other threads of the process.

Threads can be created in two ways i.e. by

  1. implementing java.lang.Runnable interface or
  2. extending java.lang.Thread class and then overriding run method.

Thread has its own variables and methods, it lives and dies on the heap. But a thread of execution is an individual process that has its own call stack. Thread are lightweight process in java.

Thread creation by  implementingjava.lang.Runnableinterface.

We will create object of class which implements Runnable interface :

Example:

MyRunnable runnable=new MyRunnable();

Thread thread=new Thread(runnable);

 create Thread object by calling constructor and passing reference of Runnable interface i.e.  runnable object :

example:

Thread thread=new Thread(runnable);

Yes, Threads have their own stack. This is very interesting question, where interviewer tends to check your basic knowledge about how threads internally maintains their own stacks.

KodNest WE

Well the answer is you must extend Thread only when you are looking to modify run() and other methods as well.

If you are simply looking to modify only the run() method implementing Runnable is the best option (Runnable interface has only one abstract method i.e. run() ). 

Differences between implementing Runnable interface and extending Thread class –

Multiple inheritance in not allowed in java : When we implement Runnable interface we can extend another class as well, but if we extend Thread class we cannot extend any other class because java does not allow multiple inheritance.

 So, same work is done by implementing Runnable and extending Thread but in case of implementing Runnable we are still left with option of extending some other class. So, it’s better to implement Runnable.

Thread safety : When we implement Runnable interface, same object is shared amongst multiple threads, but when we extend Thread class each and every thread gets associated with new object.

Inheritance (Implementing Runnable is lightweight operation) : When we extend Thread unnecessary all Thread class features are inherited, but when we implement Runnable interface no extra feature are inherited, as Runnable only consists only of one abstract method i.e. run() method. So, implementing Runnable is lightweight operation.

Coding to interface : Even java recommends coding to interface. So, we must implement Runnable rather than extending thread. Also, Thread class implements Runnable interface.

Don’t extend unless you wanna modify fundamental behaviour of class, Runnable interface has only one abstract method i.e. run()  : We must extend Thread only when you are looking to modify run() and other methods as well. If you are simply looking to modify only the run() method implementing Runnable is the best option (Runnable interface has only one abstract method i.e. run() ). We must not extend Thread class unless we’re looking to modify fundamental behaviour of Thread class.

Flexibility in code when we implement Runnable : When we extend Thread first a fall all thread features are inherited and our class becomes direct subclass of Thread , so whatever action we are doing is in Thread class. But, when we implement Runnable we create a new thread and pass runnable object as parameter,we could pass runnable object to executorService & much more. So, we have more options when we implement Runnable and our code becomes more flexible.

ExecutorService : If we implement Runnable, we can start multiple thread created on runnable object  with ExecutorService (because we can start Runnable object with new threads), but not in the case when we extend Thread (because thread can be started only once).

The solution to question is quite simple, Thread behaviour is unpredictable because execution of Threads depends on Thread scheduler, thread scheduler may have different implementation on different platforms like windows, unix etc. Same threading program may produce different output in subsequent executions even on same platform.

To achieve we are going to create 2 threads on same Runnable Object, create for loop in run() method and start  both threads. There is no surety that which threads will complete first,  both threads will enter anonymously in for loop.

Threads are lightweight process only if threads of same process are executing concurrently. But if threads of different processes are executing concurrently then threads are heavy weight process.

Interviewers tend to know interviewees knowledge about Thread methods. So this is time to prove your point by answering correctly. We can use join() methodto ensure all threads that started from main must end in order in which they started and also main should end in last.In other words waits for this thread to die. Calling join() method internally calls join(0);

This is quite interesting question, it might confuse you a bit and at time may make you think is there really any difference between starting thread with run() and start() method.

When you call start() method, main thread internally calls run() method to start newly created Thread, so run() method is ultimately called by newly created thread.

When you call run() method main thread rather than starting run() method with newly thread it start run() method by itself.

Java allows threads to access shared variables. As a rule, to ensure that shared variables are consistently updated, a thread should ensure that it has exclusive use of such variables by obtaining a lock that enforces mutual exclusion for those shared variables.

If a field is declared volatile, in that case the Java memory model ensures that all threads see a consistent value for the variable.

Volatilecan be used as a keyword against the variable, we cannot use volatile against method declaration.

volatile void method1(){} //it’s illegal, compilation error.

While synchronization can be used in method declaration or we can create synchronization blocks (In both cases thread acquires lock on object’s monitor). Variables cannot be synchronized.

Synchronized method:

synchronized void method2(){} //legal

Synchronized block:


 void method2(){

 synchronized (this) {

 //code inside synchronized block.

 }

}

}

Synchronized variable (illegal):

synchronized int i;//it’s illegal, compilatiomn error.
  • Volatile does not acquire any lock on variable or object, but Synchronization acquires lock on method or block in which it is used
  • Volatile variables are not cached, but variables used inside synchronized method or block are cached.
  • When volatile is used will never create deadlock in program, as volatile never obtains any kind of lock . But in case if synchronization is not done properly, we might end up creating dedlock in program.
  • Synchronization may cost us performance issues, as one thread might be waiting for another thread to release lock on object. But volatile is never expensive in terms of performance.

No, we cannot start Thread again, doing so will throw runtimeException java.lang.IllegalThreadStateException. The reason is once run() method is executed by Thread, it goes into dead state.

Let’s take an example-

Thinking of starting thread again and calling start() method on it (which internally is going to call run() method) for us is some what like asking dead man to wake up and run. As, after completing his life person goes to dead state.

When more than one thread try to access same resource without synchronization causes race condition.

So we can solve race condition by using either synchronized block or synchronized method. When no two threads can access same resource at a time phenomenon is also called as mutual exclusion.

Threads can communicate with each other by using wait(), notify() and notifyAll() methods.

1)Every Object has a monitor, acquiring that monitors allow thread to hold lock on object. But Thread class does not have any monitors.

2)wait(), notify() and notifyAll()are called on objects only

When wait() method is called on object by thread it waits for another thread on that object to release object monitor by calling notify() or notifyAll() method on that object.

When notify() method is called on object by thread it notifies all the threads

which are waiting for that object monitor that object monitor is available now.

So, this shows that wait(), notify() and notifyAll() are called on objects only.

Note:

1)Wait(), notify() and notifyAll() method being in Object class allows all the threads created on that object to communicate with other.  .

2)As multiple threads exists on same object. Only one thread can hold object monitor at a time. As a result thread can notify other threads of same object that lock is available now. But, thread having these methods does not make any sense because multiple threads exists on object its not other way around (i.e. multiple objects exists on thread).

3)Now let’s discuss one hypothetical scenario, what will happen if Thread class contains wait(), notify() and notifyAll() methods?

Having wait(), notify() and notifyAll() methods means Thread class also must have their monitor.

Every thread having their monitor will create few problems –

a)Thread communication problem.

b)Synchronization on object won’t be possible- Because object has monitor, one object can have multiple threads and thread hold lock on object by holding object monitor. But if each thread will have monitor, we won’t have any way of achieving synchronization.

c)Inconsistency in state of object (because synchronization won’t be possible).

Yes, it’s mandatory to acquire object lock before calling these methods on object. As discussed above wait(), notify()  and notifyAll() methods are always called from Synchronized block only, and as soon as thread enters synchronized block it acquires object lock (by holding object monitor). If we call these methods without acquiring object lock i.e. from outside synchronize block then java.lang. IllegalMonitorStateException is thrown at runtime.

Wait() method needs to enclosed in try-catch block, because it throws compile time exception i.e. InterruptedException.

Deadlock is a situation where two threads are waiting for each other to release lock holded by them on resources.

Deadlock Formation Example

public class TestThread
 {
   public static Object Lock1 = new Object();
   public static Object Lock2 = new Object();
   
   public static void main(String args[]) {
      ThreadDemo1 T1 = new ThreadDemo1();
      ThreadDemo2 T2 = new ThreadDemo2();
      T1.start();
      T2.start();
   }
   
   private static class ThreadDemo1 extends Thread {
      public void run() {
         synchronized (Lock1) {
            System.out.println("Thread 1: Holding lock 1...");
            
            try { Thread.sleep(10); }
            catch (InterruptedException e) {}
            System.out.println("Thread 1: Waiting for lock 2...");
            
            synchronized (Lock2)
 {
               System.out.println("Thread 1: Holding lock 1 & 2...");
            }
         }
      }
   }
   private static class ThreadDemo2 extends Thread {
      public void run() {
         synchronized (Lock2) {
            System.out.println("Thread 2: Holding lock 2...");
            
            try { Thread.sleep(10); }
            catch (InterruptedException e) {}
            System.out.println("Thread 2: Waiting for lock 1...");
            
            synchronized (Lock1)
 {
               System.out.println("Thread 2: Holding lock 1 & 2...");
            }
         }
      }
   } 
}

When you compile and execute the above program, you find a deadlock situation

Output

Thread 1: Holding lock 1…

Thread 2: Holding lock 2…

Thread 1: Waiting for lock 2…

Thread 2: Waiting for lock 1…

Deadlock Solution

Example:

public class TestThread {
   public static Object Lock1 = new Object();
   public static Object Lock2 = new Object();
   
   public static void main(String args[]) {
      ThreadDemo1 T1 = new ThreadDemo1();
      ThreadDemo2 T2 = new ThreadDemo2();
      T1.start();
      T2.start();
   }
   
   private static class ThreadDemo1 extends Thread {
      public void run() {
         synchronized (Lock1) {
            System.out.println("Thread 1: Holding lock 1...");
            
            try {
               Thread.sleep(10);
            } catch (InterruptedException e) {}
            System.out.println("Thread 1: Waiting for lock 2...");
            
            synchronized (Lock2) {
               System.out.println("Thread 1: Holding lock 1 & 2...");
            }
         }
      }
   }
   private static class ThreadDemo2 extends Thread {
      public void run() {
         synchronized (Lock1) {
            System.out.println("Thread 2: Holding lock 1...");
           
            try {
               Thread.sleep(10);
            } catch (InterruptedException e) {}
            System.out.println("Thread 2: Waiting for lock 2...");
            
            synchronized (Lock2) {
               System.out.println("Thread 2: Holding lock 1 & 2...");
            }
         }
      }
   } 
}

So just changing the order of the locks prevent the program in going into a deadlock situation and completes with the following result

Output:

Thread 1: Holding lock 1…

Thread 1: Waiting for lock 2…

Thread 1: Holding lock 1 & 2…

Thread 2: Holding lock 1…

Thread 2: Waiting for lock 2…

Thread 2: Holding lock 1 & 2…

Thread have following states :

New

Runnable

Running

Waiting/blocked/sleeping

Terminated (Dead)

KodNest WAA

1.Runnable : When start() method is called on thread it enters runnable state.

2.Running : Thread scheduler selects thread to go fromrunnable to running state. In running state Thread starts executing by entering run() method.

3.Waiting/blocked/sleeping : In this state a thread is not eligible to run.

4.By calling wait()method thread go from running to waiting state. In waiting state it will wait for other threads to release object monitor/lock.

5.By calling sleep() methodthread go from running to sleeping state. In sleeping state it will wait for sleep time to get over.

6.Terminated (Dead) : A thread is considered dead when its run() method completes.

In preemptive scheduling, the highest priority thread executes until it enters into the waiting or dead state.

In time slicing, a thread executes for a certain predefined time and then enters runnable pool. Than thread can enter running state when selected by thread scheduler.

Daemon threads are low priority threads which runs intermittently in background for doing garbage collection.

features of daemon() threads

  • Thread scheduler schedules these threads only when CPU is idle.
  • Daemon threads are service oriented threads, they serves all other threads.
  • These threads are created before user threads are created and die after all other user threads dies.
  • Priority of daemon threads is always 1 (i.e. MIN_PRIORITY).
  • User created threads are non daemon threads.
  • JVM can exit when only daemon threads exist in system.
  • We can use isDaemon() method to check whether thread is daemon thread or not.
  • We can use setDaemon(boolean on) method to make any user method a daemon thread.
  • If setDaemon(boolean on) is called on thread after calling start() method than IllegalThreadStateException is thrown.
  • You may like to see how daemon threads work, for that you can use VisualVM or jStack.
  • I have provided Thread dumps over there which shows daemon threads which were intermittently running in background.

yield() is a native method it’s implementation in java 6 has been changed as compared to its implementation java 5. As method is native it’s implementation is provided by JVM

In java 5, yield() method internally used to call sleep() method giving all the other threads of same or higher priority to execute before yielded thread by leaving allocated CPU for time gap of 15 millisec.

But java 6, calling yield() method gives a hint to the thread scheduler that the current thread is willing to yield its current use of a processor. The thread scheduler is free to ignore this hint. So, sometimes even after using yield() method, you may not notice any difference in output.

Note:

  • yield() method when called on thread gives a hint to the thread scheduler that the current thread is willing to yield its current use of a processor.The thread scheduler is free to ignore this hint.
  • Thread state : when yield() method is called on thread it goes from running to runnable state, not in waiting state. Thread is eligible to run but not running and could be picked by scheduler at anytime.
  • Waiting time : yield() method stops thread for unpredictable time.
  • Static method : yield()is a static method, hence calling Thread.yield() causes currently executing thread to yield.
  • Native method : implementation of yield() method is provided by JVM.

1. wait() method is always called from synchronized block i.e. wait() method needs to lock object monitor before object on which it is called.

 But sleep() method can be called from outside synchronized block i.e. sleep() method doesn’t need any object monitor.

2. if wait() method is called without acquiring object lock than IllegalMonitorStateException is thrown at runtime, but sleep() method never throws such exception

3. wait() method belongs to java.lang.Object class but sleep() method belongs to java.lang.Thread class.

4. wait() method is called on objects but sleep() method is called on Threads not objects.

5. when wait() method is called on object, thread that holded object’s monitor goes from running to waiting state and can return to runnable state only when notify() or notifyAll()method is called on that object. And later thread scheduler schedules that thread to go from from runnable to running state.

when sleep() is called on thread it goes from running to waiting state and can return to runnable state when sleep time is up.

In multithreading environment it’s very important to write thread safe code, thread unsafe code can cause a major threat to your application

1. If method is exposed in multithreading environment and it’s not synchronized (thread unsafe) than it might lead us to race condition, we must try to use synchronized block and synchronized methods. Multiple threads may exist on same object but only one thread of that object can enter synchronized method at a time, though  threads on different object can enter same method at same time.

2. Even static variables are not thread safe, they are used in static methods and if static methods are not synchronized then thread on same or different object can enter method concurrently. Multiple threads may exist on same or different objects of class but only one thread can enter static synchronized method at a time, we must consider making static methods as synchronized.

3. If possible, try to use volatile variables. If a field is declared volatile all threads see a consistent value for the variable. Volatile variables at times can be used as alternate to synchronized methods as well.

4. Final variables are thread safe because once assigned some reference of object they cannot point to reference of other object.

By calling wait()method thread go from running to waiting state. In waiting state it will wait for other threads to release object monitor/lock.

Once notify() or notifyAll()method is called object monitor/lock becomes available and thread can again return to runnable state.

By calling sleep() methodthread go from running to sleeping state. In sleeping state it will wait for sleep time to get over. Once specified sleep time is up thread can again return to runnable state.

Suspend() method can be used to put thread in waiting state and resume() method is the only way which could put thread in runnable state.

Thread also may go from running to waiting state if it is waiting for some I/O operation to take place. Once input is available thread may return to running state.

When threads are in running state, yield()method can make thread to go in Runnable state.

When sleep() method is called Thread does not leaves object lock and goes from running to waiting state. Thread waits for sleep time to over and once sleep time is up it goes from waiting to runnable state.

When wait() method is called Thread leaves the object lock and goes from running to waiting state. Thread waits for other threads on same object to call notify() or notifyAll() and once any of notify() or notifyAll() is called it goes from waiting to runnable state and again acquires object lock.

When we call start() method on thread, it internally calls run() method with newly created thread. So, if we don’t override run() method newly created thread won’t be called and nothing will happen.

When we call start() method on thread, it internally calls run() method with newly created thread. So, if we override start() method, run() method will not be called until we write code for calling run() method.

Yes, here when thread is in synchronized method it must be holding lock on object’s monitor and using that lock thread can enter other synchronized method

class Runnable1 implements Runnable
{
 
    @Override
    public void run(){
           m1();
    }
 
    synchronized void m1()
{
           System.out.println("synchronized method1() started");
           m2();
           System.out.println("synchronized method1() ended");
    }
 
    synchronized void m2()
    {
           System.out.println("in synchronized method2()");
    }
    
}
 
 
public class Demo {
    public static void main(String args[]) throws InterruptedException{
           
           Runnable1 mRunnable1=new Runnable1();
           Thread thread1=new Thread(Runnable1,"Thread-1");
           thread1.start();        
           
    }
 
}

OUTPUT

synchronized method1() started

in synchronized method2()

synchronized method1() ended

Following example demonstrates how to solve the producer consumer problem using thread.

public class ProducerConsumerTest {
   public static void main(String[] args) {
      CubbyHole c = new CubbyHole();
      Producer p1 = new Producer(c, 1);
      Consumer c1 = new Consumer(c, 1);
      p1.start(); 
      c1.start();
   }
}
class CubbyHole {
   private int contents;
   private boolean available = false;
   
   public synchronized int get() {
      while (available == false) {
         try {
            wait();
         } catch (InterruptedException e) {}
      }
      available = false;
      notifyAll();
      return contents;
   }
   public synchronized void put(int value) {
      while (available == true) {
         try {
            wait();
         } catch (InterruptedException e) { } 
      }
      contents = value;
      available = true;
      notifyAll();
   }
}
class Consumer extends Thread {
   private CubbyHole cubbyhole;
   private int number;
   
   public Consumer(CubbyHole c, int number) {
      cubbyhole = c;
      this.number = number;
   }
   public void run() {
      int value = 0;
      for (int i = 0; i < 10; i++) {
         value = cubbyhole.get();
         System.out.println("Consumer #" + this.number + " got: " + value);
      }
   }
}
class Producer extends Thread {
   private CubbyHole cubbyhole;
   private int number;
   public Producer(CubbyHole c, int number) {
      cubbyhole = c;
      this.number = number;
   } 
   public void run() {
      for (int i = 0; i < 10; i++) {
         cubbyhole.put(i);
         System.out.println("Producer #" + this.number + " put: " + i);
         try {
            sleep((int)(Math.random() * 100));
         } catch (InterruptedException e) { }
      } 
   }
}

Producer #1 put: 0

Consumer #1 got: 0

Producer #1 put: 1

Consumer #1 got: 1

Producer #1 put: 2

Consumer #1 got: 2

Producer #1 put: 3

Consumer #1 got: 3

Producer #1 put: 4

Consumer #1 got: 4

Producer #1 put: 5

Consumer #1 got: 5

Producer #1 put: 6

Consumer #1 got: 6

Producer #1 put: 7

Consumer #1 got: 7

Producer #1 put: 8

Consumer #1 got: 8

Producer #1 put: 9

Consumer #1 got: 9

Following example demonstrates how to display different status of thread using isAlive() & getStatus() methods of Thread.

class MyThread extends Thread {
   boolean waiting = true;
   boolean ready = false;
   MyThread() {
   }
   public void run() {
      String thrdName = Thread.currentThread().getName();
      System.out.println(thrdName + " starting.");
      
      while(waiting) System.out.println("waiting:"+waiting);
      System.out.println("waiting...");
      startWait();
      try {
         Thread.sleep(1000);
      } catch(Exception exc) {
         System.out.println(thrdName + " interrupted.");
      }
      System.out.println(thrdName + " terminating.");
   }
   synchronized void startWait() {
      try {
         while(!ready) wait();
      } catch(InterruptedException exc) {
         System.out.println("wait() interrupted");
      }
   }
   synchronized void notice() {
      ready = true;
      notify();
   }
}
public class Main {
   public static void main(String args[]) throws Exception {
      MyThread thrd = new MyThread();
      thrd.setName("MyThread #1");
      showThreadStatus(thrd);
      
      thrd.start();
      Thread.sleep(50);
      showThreadStatus(thrd);
      
      thrd.waiting = false;
      Thread.sleep(50);
      showThreadStatus(thrd);
      
      thrd.notice();
      Thread.sleep(50);
      showThreadStatus(thrd);
      
      while(thrd.isAlive())
      System.out.println("alive");
      showThreadStatus(thrd);
   }
   static void showThreadStatus(Thread thrd) {
      System.out.println(thrd.getName()+" Alive:"+thrd.isAlive()+" State:" + thrd.getState() );
   }
}

Output:

MyThread #1 Alive:false State:NEW

MyThread #1 starting.

waiting:true

waiting:true

alive

alive

MyThread #1 terminating.

alive

MyThread #1 Alive:false State:TERMINATED

Following example demonstrates how to interrupt a running thread interrupt() method of thread and check if a thread is interrupted using isInterrupted() method.

public class GeneralInterrupt extends Object implements Runnable {
   public void run() {
      try {
         System.out.println("in run() - about to work2()");
         work2();
         System.out.println("in run() - back from work2()");
      } catch (InterruptedException x) {
         System.out.println("in run() - interrupted in work2()");
         return;
      }
      System.out.println("in run() - doing stuff after nap");
      System.out.println("in run() - leaving normally");
   }
   public void work2() throws InterruptedException {
      while (true) {
         if (Thread.currentThread().isInterrupted()) {
            System.out.println("C isInterrupted()="+ Thread.currentThread().isInterrupted());
            Thread.sleep(2000);
            System.out.println("D isInterrupted()="+ Thread.currentThread().isInterrupted());
         }
      }
   }
   public void work() throws InterruptedException {
      while (true) {
         for (int i = 0; i < 100000; i++) {
            int j = i * 2;
         }
         System.out.println("A isInterrupted()="+ Thread.currentThread().isInterrupted());
         if (Thread.interrupted()) {
            System.out.println("B isInterrupted()="+ Thread.currentThread().isInterrupted());
            throw new InterruptedException();
         }
      }
   }
   public static void main(String[] args) {
      GeneralInterrupt si = new GeneralInterrupt();
      Thread t = new Thread(si);
      t.start();
      try {
         Thread.sleep(2000);
      } catch (InterruptedException x) { }
		
      System.out.println("in main() - interrupting other thread");
      t.interrupt();
      System.out.println("in main() - leaving");
   }
}

Output:

in run() – about to work2()

in main() – interrupting other thread

in main() – leaving

C isInterrupted()=true

in run() – interrupted in work2()

ThreadPool is a pool of threads which reuses a fixed number of threads  to execute tasks.

At any point, at most nThreads threads will be active processing tasks. If additional tasks are submitted when all threads are active, they will wait in the queue until a thread is available.

Note:

Advantage of ThreadPool:

Instead of creating new thread every time for executing tasks, we can create ThreadPool which reuses a fixed number of threads for executing tasks.

As threads are reused, performance of our application improves drastically.

No, constructor cannot be synchronized. Because constructor is used for instantiating object, when we are in constructor object is under creation. So, until object is not instantiated it does not need any synchronization.

Enclosing constructor in synchronized block will generate compilation error.

And the error is-“Illegal modifier for the constructor , only public, protected & private are permitted”.

Thread Priority range is from 1 to 10.

Where 1 is minimum priority and 10 is maximum priority.

Thread class provides variables of final static int type for setting thread priority.

publicfinalstaticintMIN_PRIORITY= 1;

publicfinalstaticintNORM_PRIORITY= 5;

publicfinalstaticintMAX_PRIORITY= 10;

Thread with MAX_PRIORITY is likely to get more CPU as compared to low priority threads. But occasionally low priority thread might get more CPU. Because thread scheduler schedules thread on discretion of implementation and thread behaviour is totally unpredictable.

Thread with MIN_PRIORITY is likely to get less CPU as compared to high priority threads. But occasionally high priority thread might less CPU. Because thread scheduler schedules thread on discretion of implementation and thread behaviour is totally unpredictable.

setPriority()method is used for Changing the priority of thread.

getPriority()method returns the thread’s priority.

Collection Framework is a combination of classes and interface, which is used to store and manipulate the data in the form of objects. It provides various classes such as ArrayList, Vector, Stack, and HashSet, etc. and interfaces such as List, Queue, Set, etc. for this purpose.

Collection framework implements various interfaces, Collection interface and Map interface (java.util.Map) are the mainly used interfaces of Java Collection Framework. List of interfaces of Collection Framework is given below:

  1. Collection interface: Collection (java.util.Collection) is the primary interface, and every collection must implement this interface.
  2. List interface: List interface extends the Collection interface, and it is an ordered collection of objects. It contains duplicate elements. It also allows random access of elements.
  3. Set interface: Set (java.util.Set) interface is a collection which cannot contain duplicate elements. It can only include inherited methods of Collection interface
  4. Queue interface: Queue (java.util.Queue) interface defines queue data structure, which stores the elements in the form FIFO (first in first out).
  5. Dequeue interface: it is a double-ended-queue. It allows the insertion and removal of elements from both ends. It implants the properties of both Stack and queue so it can perform LIFO (Last in first out) stack and FIFO (first in first out) queue, operations.
  6. Map interface: A Map (java.util.Map) represents a key, value pair storage of elements. Map interface does not implement the Collection interface. It can only contain a unique key but can have duplicate elements. There are two interfaces which implement Map in java that are Map interface and Sorted Map.

BlockingQueue is an interface which extends the Queue interface. It provides concurrency in the operations like retrieval, insertion, deletion. While retrieval of any element, it waits for the queue to be non-empty. While storing the elements, it waits for the available space. BlockingQueue cannot contain null elements, and implementation of BlockingQueue is thread-safe.

If you change the value in the properties file, you don’t need to recompile the java class. So, it makes the application easy to manage. It is used to store information which is to be changed frequently. Consider the following example.

import java.util.*;  
import java.io.*;  
public class Test {  
public static void main(String[] args)throws Exception{  
    FileReader reader=new FileReader("db.properties");  
      
    Properties p=new Properties();  
    p.load(reader);  
      
    System.out.println(p.getProperty("user"));  
    System.out.println(p.getProperty("password"));  
}  
}  

Output

system

oracle

The equals method is used to check whether two objects are the same or not. It needs to be overridden if we want to check the objects based on the property.

For example, Employee is a class that has 3 data members: id, name, and salary. However, we want to check the equality of employee object by the salary. Then, we need to override the equals() method.

public static List synchronizedList(List l){}
public static Set synchronizedSet(Set s){}
public static SortedSet synchronizedSortedSet(SortedSet s){}
public static Map synchronizedMap(Map m){}
public static SortedMap synchronizedSortedMap(SortedMap m){}
  • There are three main advantages of using the generic collection.
  • If we use the generic class, we don’t need typecasting.
  • It is type-safe and checked at compile time.
  • Generic confirms the stability of the code by making it bug detectable at compile time.

Two different keys with the same hash value are known as hash-collision. Two separate entries will be kept in a single hash bucket to avoid the collision. There are two ways to avoid hash-collision.

Separate Chaining

Open Addressing

The Dictionary class provides the capability to store key-value pairs.

The default size of load factor is 0.75. The default capacity is computed as initial capacity * load factor. For example, 16 * 0.75 = 12. So, 12 is the default capacity of Map.

The Iterator in java which immediately throws ConcurrentmodificationException, if any structural modification occurs in, is called as a Fail-fast iterator. Fail-fats iterator does not require any extra space in memory.

There are two ways to remove duplicates from the ArrayList.

1.Using HashSet: By using HashSet we can remove the duplicate element from the ArrayList, but it will not then preserve the insertion order.

2.Using LinkedHashSet: We can also maintain the insertion order by using LinkedHashSet instead of HashSet.

The Process to remove duplicate elements from ArrayList using the LinkedHashSet:

Copy all the elements of ArrayList to LinkedHashSet.

Empty the ArrayList using clear() method, which will remove all the elements from the list.

Now copy all the elements of LinkedHashset to ArrayList.

To reverse an ArrayList, we can use reverse() method of Collections class. Consider the following example.

import java.util.ArrayList;  
import java.util.Collection;  
import java.util.Collections;  
import java.util.Iterator;  
import java.util.List;  
public class ReverseArrayList {  
public static void main(String[] args) {  
     List list = new ArrayList<>();  
     list.add(10);  
     list.add(50);  
     list.add(30);  
     Iterator i = list.iterator();  
     System.out.println("printing the list....");  
     while(i.hasNext())  
     {  
         System.out.println(i.next());  
     }  
     Iterator i2 = list.iterator();  
     Collections.reverse(list);  
     System.out.println("printing list in reverse order....");  
     while(i2.hasNext())  
     {  
         System.out.println(i2.next());  
     }  
    }  
} 

50

10

To sort the ArrayList in descending order, we can use the reverseOrder method of Collections class. Consider the following example.


import java.util.ArrayList;  
import java.util.Collection;  
import java.util.Collections;  
import java.util.Comparator;  
import java.util.Iterator;  
import java.util.List;  
  
public class ReverseArrayList {  
public static void main(String[] args) {  
     List list = new ArrayList<>();  
     list.add(10);  
     list.add(50);  
     list.add(30);  
     list.add(60);  
     list.add(20);  
     list.add(90);  
       
     Iterator i = list.iterator();  
     System.out.println("printing the list....");  
     while(i.hasNext())  
     {  
         System.out.println(i.next());  
     }  
      
    Comparator cmp = Collections.reverseOrder();  
    Collections.sort(list,cmp);  
     System.out.println("printing list in descending order....");  
     Iterator i2 = list.iterator();  
     while(i2.hasNext())  
     {  
         System.out.println(i2.next());  
     }  
       
}  
}  

Output:

printing the list….

10

50

30

60

20

90

printing list in descending order….

90

60

50

30

20

10

We can synchronize ArrayList in two ways.

Using Collections.synchronizedList() method

Using CopyOnWriteArrayList

LinkedLists are better to use for the update operations whereas ArrayLists are better to use for the search operations.

1.ArrayDeque and PriorityQueue

ArrayDequePriorityQueue
Internally uses array to store dataInternally usesminheap to store data
Order of insertion is preservedHighest priority element is  present at
the beginning of the queue
Highest priority element is not present at
the beginning of the queue
Order of insertion is not preserved
Iterators as well as descending iterators can be usedOnly iterators can be uses

2.Vector and ArrayList

VectorArrayList
Introduced from java 1.2Part of collections from the begining
Vector is a legacy classIt is not a legacy class
Vectors are synchronizedArrayLists are not synchronized
Thread safeNot thread safe
Performance is relatively lowPerformance is relatively high
FailFast error does not occurIt is failfast

3.ArrayList and Linked List

VectorArrayList
Introduced from java 1.2Part of collections from the begining
Vector is a legacy classIt is not a legacy class
Vectors are synchronizedArrayListsare not synchronized
Thread safeNot thread safe
Performance is relatively lowPerformance is relatively high
FailFast error does not occurIt is failfast

4.Array and ArrayList

ArrayArrayList
Holds primitive dataCan store objects
Is not dynamic in natureDynamic in nature
Can store homogeneous dataCan store heterogeneous data
Arrays does not provide methods Provides methods to perform various operations
Contents can be accepted using loopsCan accept using loops,iterator or listiterator
Present from beginning of javaIntroduced in java 1.2
Not part of collectionPart of collection

5.TreeSet and HashSet

TreeSetHashSet
Internally makes use of balanced binary search treeInternally makes use of hashing
Objects are stored in sorted orderObjects are not stored in sorted order
The time complexity for each operation is
O(log2n)
Time complexity of each operation is
O(1)
TreeSet has implemented from navigable setHashSet has been extended from
Abstract set
Descending Iterator can be applied on tree setDescending Iterator cannot be applied

6.HashSet and LinkedHashSet

HashSetLinkedHashSet
Order of insertion not preservedOrder of insertion preserved
Extends from abstract setExtends from HashSet

7.Comparable and Comparator

ComparableComparator
Expects the implementation of
compareTo()
Expectsthe implementation of compare()
General format of compareTo()
public intcompareTo(Object y)
General format of compare()
public intcompare(Object y,Object x)
This is used to refer to first objectThis is not used to refer to first object
Comparable interface is usefull if and
only if the source code of the class
is available and
open for modification
Comparator interface is usefulleven 
if the source code of the class is not available
and not open for modification

8.Collection and Collections

CollectionCollections
Collection is an interface
which can be implemented the 
List, Set,Sorted Set,and Queue
Collections is an utility class
which contain the utility methods such as sorting etc. 

9.Iterator and Enumeration

IteratorEnumeration
Iterator  allows to remove elements
from collection during traversal 
Enumeration doesn’t allow
More secure and safeLess secure and safe

10.Iterator and ListIterator

IteratorListIterator
Iterator is used for traversing
 List and Set both.
Used to traverse List only,
we cannot traverse Set using ListIterator.
We can traverse in only forward
direction using Iterator
Using ListIterator,
we can traverse a List in
both the directions (forward and Backward).
We cannot obtain indexes while
using Iterator
We can obtain indexes at any point of time
while traversing a list using ListIterator.
The methods nextIndex() and previousIndex()
are used for this purpose.
We cannot add element to collection
while traversing it using Iterator,
it throws ConcurrentModificationException
when you try to do it.
We can add element at any point of time
while traversing a list using ListIterator.
We cannot replace the existing
element value when using Iterator.
By using set(E e) method of ListIterator
we can replace the last element returned
by next() or previous() methods.

11.List and Set

ListSet
List is an ordered collection it
maintains the insertion order,
which means upon displaying
the list content it will display
the elements in the same order
in which they got inserted into the list.
Set is an unordered collection,
it doesn’t maintain any order.
There are few implementations of Set
which maintains the order
such as LinkedHashSet
(It maintains the elements in insertion order).
List allows duplicatesSet doesn’t allow duplicate elements.
All the elements of a Set should be unique
if you try to insert the duplicate element
in Set it would replace the existing value.
 List implementations:
 ArrayList, LinkedList and so on.
Set implementations:
 HashSet, LinkedHashSet , TreeSet and so on.
 List allows any number of null values.Set can have only a singlenull value at most.

12.Set and Map

SetMap
Set doesn’t allow duplicates.
Set and all of the classes which implements
Set interface should have unique elements.
Map stores the elements as key & value pair.
Map doesn’t allow duplicate keys
while it allows duplicate values.
Set allows single null value at most.Map can have single null key at most and
any number of null values.

13.HashSet and HashMap

HashSetHashMap
HashSet class implements the Set interfaceHashMap class implements the Map interface
In HashSet we store objects
(elements or values) 
HashMap is used for storing key & value pairs
HashSet permits to have a single null value.HashMap permits single null key and
any number of null values.
HashSet does not allow duplicate elements
that means you can not store duplicate
values in HashSet.
HashMap does not allow duplicate keys however
it allows to have duplicate values.

14.HashMap and TreeMap

HashMapTreeMap
HashMap returns unordered values TreeMap returns the elements in ascending order 
The performance of HashMap is higher Performance on the lower side

15.HashMap and HashTable

HashMapHashTable
 HashMap is non synchronized.
It is not-thread safe and can’t be shared
between many threads without
proper synchronization code.
Hashtable is synchronized.
It is thread-safe and
can be shared with many threads.
HashMap allows one null key and
multiple null values.
Hashtable doesn’t allow any
null key or value.
HashMap is a new class introduced in JDK 1.2.Hashtable is a legacy class.
 HashMap is fast.Hashtable is slow.
We can make the HashMap as
synchronized by calling this code
Map m = Collections.synchronizedMap(hashMap);
Hashtable is internally synchronized and
can’t be unsynchronized.
 HashMap is traversed by Iterator.Hashtable is traversed by
Enumerator and Iterator.
Iterator in HashMap is fail-fast.Enumerator in Hashtable is not fail-fast.
HashMap inherits AbstractMap class.Hashtable inherits Dictionary class.

The Iterator interface provides a number of methods that are able to iterate over any Collection. Each Java Collection contains the Iterator method that returns an Iterator instance. Iterators are capable of removing elements from the underlying collection during the iteration.

The Iterator’s fail-safe property works with the clone of the underlying collection and thus, it is not affected by any modification in the collection. All the collection classes in java.util package are fail-fast, while the collection classes in java.util.concurrent are fail-safe. Fail-fast iterators throw a ConcurrentModificationException, while fail-safe iterator never throws such an exception.

A HashMap in Java stores key-value pairs. The HashMap requires a hash function and uses hashCode and equals methods, in order to put and retrieve elements to and from the collection respectively. When the put method is invoked, the HashMap calculates the hash value of the key and stores the pair in the appropriate index inside the collection. If the key exists, its value is updated with the new value. Some important characteristics of a HashMap are its capacity, its load factor and the threshold resizing.

List their differences. Java provides the Comparable interface, which contains only one method, called compareTo). This method compares two objects, in order to impose an order between them. Specifically, it returns a negative integer, zero, or a positive integer to indicate that the input object is less than, equal or greater than the existing object. Java provides the Comparator interface, which contains two methods, called compare) and equals). The first method compares its two input arguments and imposes an order between them. It returns a negative integer, zero, or a positive integer to indicate that the first argument is less than, equal to, or greater than the second. The second method requires an object as a parameter and aims to decide whether the input object is equal to the comparator. The method returns true, only if the specified object is also a comparator and it imposes the same ordering as the comparator.

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
 
public class Quiz38 {
 
    public static void main(String[] args) {
 
        List list = new ArrayList();
        
        Integer[] arr = {2,10,3};
        
        list = Arrays.asList(arr);
        
        list.set(0, 3);
        
        System.out.println(list);
        
        list.add(1);
        
        System.out.println(list);
    }
 
}

 Answer:
Output :

[3,10,3], followed by exception

This is because Arrays.asList() returns a fixed-size list backed by the specified array. Therefore, the arraylist can’t grow.

So, when add() is called, an exception is thrown.

import java.util.ArrayList;
import java.util.List;
 
public class ArrayListDemo {
 
    public static void main(String[] args) {
 
        List list = new ArrayList();
        
        list.add(10);
        list.add(10);
        
        System.out.print(list.size());
        
        list.remove(new Integer(10));
        
        System.out.print(list.size());
    }
}

Answer:

Output:

21

This is because ArralyList can contain duplicate elements.

ArrayList remove() method only removes the first occurrence of a matching element.

import java.util.ArrayList;
import java.util.List;
 
public class ArrayListDemo {
 
    public static void main(String[] args) {
 
        List list = new ArrayList();
        
        list.add(10);
        list.add(10);
        
        System.out.print(list.size());
        
        list.remove(new Integer(10));
        
        System.out.print(list.size());
    }
}

Answer:

Output:

“Apple Apple Nokia Nokia”

Note:

PriorityQueue keeps elements sorted and it can have duplicates.

add() and offer() methods both offer same functionality.

poll() method removes the first element in queue and returns it, while peek() method returns the first element without removing it.

package com.Kodnest;
 
public class Student {
 
    int rollNumber;
    
    Student(int n){
        rollNumber = n;
    }
}

package com.Kodnest;
 
import java.util.HashSet;
import java.util.Set;
 
public class HashSetDemo {
 
    public static void main(String[] args) {
 
        Set students = new HashSet();
        
        students.add(new Student(1));
        students.add(new Student(3));
        students.add(new Student(4));
        students.add(new Student(1));
        students.add(new Student(3));
        
        System.out.println(students.size());
    }
 
}

Answer:

Output

5

Because  Student doesn’t override equals(), there are 5 objects in the HashSet.

package com.Kodnest;
 
public class Employee implements Comparable{
 
     int id;
    
     String name;
    
    Employee(int id, String name){
        this.id = id;
        this.name = name;
    }
 
    @Override
    public int compareTo(Employee emp) {
        return this.name.compareTo(emp.name);
    }    
}
import java.util.Comparator;
 
public class EmployeeComparator implements Comparator{
 
    @Override
    public int compare(Employee emp1, Employee emp2) 
{       
        return emp2.id - emp1.id;
    } 
}
import java.util.TreeSet;
 
public class TreeSetDemo{
 
    public static void main(String[] args) {
 
        TreeSet empTreeSet = new TreeSet(new EmployeeComparator());
        
        Employee emp1 = new Employee(20, "Clark");
        Employee emp2 = new Employee(24, "Bernie");
        Employee emp3 = new Employee(3, "Alex");        
        empTreeSet.add(emp1);
        empTreeSet.add(emp2);
        empTreeSet.add(emp3);        
        
        for(Employee emp : empTreeSet)
                    System.out.print(emp.name + " ");        
 
    } 
}

Answer:

Output :

Bernie Clark Alex

import java.util.HashSet;
 
public class MyHashSetCopy 
{ 
    public static void main(String a[])
{
        HashSet hs = new HashSet();
        //add elements to HashSet
        hs.add("first");
        hs.add("second");
        hs.add("third");
        System.out.println(hs);
        HashSet subSet = new HashSet();
        subSet.add("s1");
        subSet.add("s2");
        hs.addAll(subSet);
        System.out.println("HashSet content after adding another collection:");
        System.out.println(hs);
    }
}

Output:

[second, third, first]

HashSet content after adding another collection:

[s2, s1, second, third, first]

import java.util.HashSet; 
public class MyHashSetToArray
 { 
    public static void main(String a[])
{
        HashSet hs = new HashSet();
        //add elements to HashSet
        hs.add("first");
        hs.add("second");
        hs.add("third");
        System.out.println("HashSet content: ");
        System.out.println(hs);
        String[] strArr = new String[hs.size()];
        hs.toArray(strArr);
        System.out.println("Copied array content:");
        for(String str:strArr){
            System.out.println(str);
        }
    }
}

Output:

HashSet content:

[second, third, first]

Copied array content:

second

third

first

import java.util.HashSet;
 
public class MyDistElementEx {
 
    public static void main(String a[]){
         
        HashSet lhm = new HashSet();
        lhm.add(new Price("Banana", 20));
        lhm.add(new Price("Apple", 40));
        lhm.add(new Price("Orange", 30));
        for(Price pr:lhm){
            System.out.println(pr);
        }
        Price duplicate = new Price("Banana", 20);
        System.out.println("inserting duplicate object...");
        lhm.add(duplicate);
        System.out.println("After insertion:");
        for(Price pr:lhm){
            System.out.println(pr);
        }
    }
}
 
class Price{
     
    private String item;
    private int price;
     
    public Price(String itm, int pr){
        this.item = itm;
        this.price = pr;
    }
     
    public int hashCode(){
        System.out.println("In hashcode");
        int hashcode = 0;
        hashcode = price*20;
        hashcode += item.hashCode();
        return hashcode;
    }
     
    public boolean equals(Object obj){
        System.out.println("In equals");
        if (obj instanceof Price) {
            Price pp = (Price) obj;
            return (pp.item.equals(this.item) && pp.price == this.price);
        } else {
            return false;
        }
    }
     
    public String getItem() {
        return item;
    }
    public void setItem(String item) {
        this.item = item;
    }
    public int getPrice() {
        return price;
    }
    public void setPrice(int price) {
        this.price = price;
    }
     
    public String toString(){
        return "item: "+item+"  price: "+price;
    }
}


Output:

In hashcode

In hashcode

In hashcode

item: Apple  price: 40

item: Orange  price: 30

item: Banana  price: 20

inserting duplicate object…

In hashcode

In equals

After insertion:

item: Apple  price: 40

item: Orange  price: 30

item: Banana  price: 20

import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
 
public class MyLinkedListSort {
 
    public static void main(String a[]){
         
        LinkedList list = new LinkedList();
        list.add(new Empl("Ram",3000));
        list.add(new Empl("John",6000));
        list.add(new Empl("Crish",2000));
        list.add(new Empl("Tom",2400));
        Collections.sort(list,new MySalaryComp());
        System.out.println("Sorted list entries: ");
        for(Empl e:list){
            System.out.println(e);
        }
    }
}
 
class MySalaryComp implements Comparator{
 
    @Override
    public int compare(Empl e1, Empl e2) {
        if(e1.getSalary() < e2.getSalary()){
            return 1;
        } else {
            return -1;
        }
    }
}
 
class Empl{
     
    private String name;
    private int salary;
     
    public Empl(String n, int s){
        this.name = n;
        this.salary = s;
    }
     
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getSalary() {
        return salary;
    }
    public void setSalary(int salary) {
        this.salary = salary;
    }
    public String toString(){
        return "Name: "+this.name+"-- Salary: "+this.salary;
    }
}

Output:

Sorted list entries:

Name: John– Salary: 6000

Name: Ram– Salary: 3000

Name: Tom– Salary: 2400

Name: Crish– Salary: 2000

import java.util.Collections;
import java.util.LinkedList;
 
public class MyLinkedListReverse {
 
    public static void main(String a[]){
         
        LinkedList list = new LinkedList();
        list.add("Java");
        list.add("Cric");
        list.add("Play");
        list.add("Watch");
        list.add("Glass");
        Collections.reverse(list);
        System.out.println("Results after reverse operation:");
        for(String str: list){
            System.out.println(str);
        }
    }
}

Output:

Results after reverse operation:

Glass

Watch

Play

Cric

Java

import java.util.Collections;
import java.util.LinkedList;
 
public class MyLinkedListShuffle {
 
    public static void main(String a[]){
         
        LinkedList<String> list = new LinkedList<String>();
        list.add("Java");
        list.add("Cric");
        list.add("Play");
        list.add("Watch");
        list.add("Glass");
        list.add("Movie");
        list.add("Girl");
         
        Collections.shuffle(list);
        System.out.println("Results after shuffle operation:");
        for(String str: list){
            System.out.println(str);
        }
         
        Collections.shuffle(list);
        System.out.println("Results after shuffle operation:");
        for(String str: list){
            System.out.println(str);
        }
    }
}

Output:

Results after shuffle operation:

Movie

Girl

Watch

Glass

Java

Cric

Play

Results after shuffle operation:

Glass

Watch

Play

Girl

Cric

Movie

Java

import java.util.LinkedList;
import java.util.List;
 
public class MyListToCsvString {
 
    public String getListAsCsvString(List<String> list){
         
        StringBuilder sb = new StringBuilder();
        for(String str:list){
            if(sb.length() != 0){
                sb.append(",");
            }
            sb.append(str);
        }
        return sb.toString();
    }
     
    public static void main(String a[]){
         
        List<String> li1 = new LinkedList<String>(){
            {
                this.add("animal");
                this.add("nuts");
                this.add("java");
            }
        };
        MyListToCsvString mtc = new MyListToCsvString();
        System.out.println(mtc.getListAsCsvString(li1));
        List<String> li2 = new LinkedList<String>(){
            {
                this.add("java");
                this.add("unix");
                this.add("c++");
            }
        };
        System.out.println(mtc.getListAsCsvString(li2));
    }
}

Output:

animal,nuts,java

java,unix,c++

Note:

Below example shows how to remove or delete an element from LinkedList. LinkedList provides few methods to remove elements, those methods are:

remove(): Retrieves and removes the head (first element) of this list.

remove(index): Removes the element at the specified position in this list.

remove(object): Removes the first occurrence of the specified element from this list, if it is present.

removeFirst(): Removes and returns the first element from this list.

removeFirstOccurrence(object): Removes the first occurrence of the specified element in this list (when traversing the list from head to tail).

removeLast(): Removes and returns the last element from this list.

removeLastOccurrence(object): Removes the last occurrence of the specified element in this list (when traversing the list from head to tail).

public class MyAllRemoveOprs
 { 
    public static void main(String a[])
{         
        LinkedList<String> arrl = new LinkedList<String>();
        arrl.add("First");
        arrl.add("Second");
        arrl.add("Third");
        arrl.add("Random");
        arrl.add("four");
        arrl.add("five");
        arrl.add("six");
        arrl.add("seven");
        arrl.add("eight");
        arrl.add("nine");
        System.out.println(arrl);
        System.out.println("Remov() method:"+arrl.remove());
        System.out.println("After remove() method call:");
        System.out.println(arrl);
        System.out.println("remove(index) method:"+arrl.remove(2));
        System.out.println("After remove(index) method call:");
        System.out.println(arrl);
        System.out.println("Remov(object) method:"+arrl.remove("six"));
        System.out.println("After remove(object) method call:");
        System.out.println(arrl);
        System.out.println("removeFirst() method:"+arrl.removeFirst());
        System.out.println("After removeFirst() method call:");
        System.out.println(arrl);
        System.out.println("removeFirstOccurrence() method:"
                            +arrl.removeFirstOccurrence("eight"));
        System.out.println("After removeFirstOccurrence() method call:");
        System.out.println(arrl);
        System.out.println("removeLast() method:"+arrl.removeLast());
        System.out.println("After removeLast() method call:");
        System.out.println(arrl);
        System.out.println("removeLastOccurrence() method:"
                            +arrl.removeLastOccurrence("five"));
        System.out.println("After removeLastOccurrence() method call:");
        System.out.println(arrl);
    }
}

Output:

[First, Second, Third, Random, four, five, six, seven, eight, nine]

Remov() method:First

After remove() method call:

[Second, Third, Random, four, five, six, seven, eight, nine]

remove(index) method:Random

After remove(index) method call:

[Second, Third, four, five, six, seven, eight, nine]

Remov(object) method:true

After remove(object) method call:

[Second, Third, four, five, seven, eight, nine]

removeFirst() method:Second

After removeFirst() method call:

[Third, four, five, seven, eight, nine]

removeFirstOccurrence() method:true

After removeFirstOccurrence() method call:

[Third, four, five, seven, nine]

removeLast() method:nine

After removeLast() method call:

[Third, four, five, seven]

removeLastOccurrence() method:true

After removeLastOccurrence() method call:

[Third, four, seven]

import java.util.LinkedHashSet;
 
public class MyLhsRetainEx {
 
    public static void main(String a[]){
         
        LinkedHashSet<String> lhs = new LinkedHashSet<String>();
        //add elements to LinkedHashSet
        lhs.add("first");
        lhs.add("second");
        lhs.add("third");
        lhs.add("apple");
        lhs.add("rat");
        System.out.println(lhs);
        LinkedHashSet<String> subSet = new LinkedHashSet<String>();
        subSet.add("rat");
        subSet.add("second");
        subSet.add("first");
        lhs.retainAll(subSet);
        System.out.println("LinkedHashSet content:");
        System.out.println(lhs);
    }
}

Output:

[first, second, third, apple, rat]

LinkedHashSet content:

[first, second, rat]

import java.util.Comparator;
import java.util.TreeSet;
 
public class MySetWithCompr 
{ 
    public static void main(String a[])
{         
        TreeSet<String> ts = new TreeSet<String>(new MyComp());
        ts.add("RED");
        ts.add("ORANGE");
        ts.add("BLUE");
        ts.add("GREEN");
        System.out.println(ts);
    }
}
 
class MyComp implements Comparator<String>
{ 
    @Override
    public int compare(String str1, String str2)
 {
        return str1.compareTo(str2);
    }     
}

Output:

[BLUE, GREEN, ORANGE, RED]

import java.util.Comparator;
import java.util.Set;
import java.util.TreeSet;
 
public class MySetSublist {
 
    public static void main(String a[]){
         
        TreeSet<String> ts = new TreeSet<String>(new MyStrComp());
        ts.add("RED");
        ts.add("ORANGE");
        ts.add("BLUE");
        ts.add("GREEN");
        ts.add("WHITE");
        ts.add("BROWN");
        ts.add("YELLOW");
        ts.add("BLACK");
        System.out.println(ts);
        Set<String> subSet = ts.subSet("GREEN", "WHITE");
        System.out.println("sub set: "+subSet);
        subSet = ts.subSet("GREEN", true, "WHITE", true);
        System.out.println("sub set: "+subSet);
        subSet = ts.subSet("GREEN", false, "WHITE", true);
        System.out.println("sub set: "+subSet);
    }
}
 
class MyStrComp implements Comparator<String>{
 
    @Override
    public int compare(String str1, String str2) {
        return str1.compareTo(str2);
    }
     
}

Output:

[BLACK, BLUE, BROWN, GREEN, ORANGE, RED, WHITE, YELLOW]

sub set: [GREEN, ORANGE, RED]

sub set: [GREEN, ORANGE, RED, WHITE]

sub set: [ORANGE, RED, WHITE]

import java.util.Comparator;
import java.util.Set;
import java.util.TreeSet;
 
public class MyUserDuplicates {
 
    public static void main(String a[]){
         
        Set<Emp> ts = new TreeSet<Emp>(new EmpComp());
        ts.add(new Emp(201,"John",40000));
        ts.add(new Emp(302,"Krish",44500));
        ts.add(new Emp(146,"Tom",20000));
        ts.add(new Emp(543,"Abdul",10000));
        ts.add(new Emp(12,"Dinesh",50000));
        //adding duplicate entry
        ts.add(new Emp(146,"Tom",20000));
        //check duplicate entry is there or not
        for(Emp e:ts){
            System.out.println(e);
        }
    }
}
 
class EmpComp implements Comparator<Emp>{
 
    @Override
    public int compare(Emp e1, Emp e2) {
        if(e1.getEmpId() == e2.getEmpId()){
            return 0;
        } if(e1.getEmpId() < e2.getEmpId()){
            return 1;
        } else {
            return -1;
        }
    }
}
 
class Emp {
     
    private int empId;
    private String empName;
    private int empSal;
     
    public Emp(int id, String name, int sal){
        this.empId = id;
        this.empName = name;
        this.empSal = sal;
    }
     
    public int getEmpId() {
        return empId;
    }
     
    public void setEmpId(int empId) {
        this.empId = empId;
    }
     
    public String getEmpName() {
        return empName;
    }
     
    public void setEmpName(String empName) {
        this.empName = empName;
    }
     
    public int getEmpSal() {
        return empSal;
    }
    public void setEmpSal(int empSal) {
        this.empSal = empSal;
    }
     
    public String toString(){
        return empId+" : "+empName+" : "+empSal;
    }
}

Output:

543 : Abdul : 10000

302 : Krish : 44500

201 : John : 40000

146 : Tom : 20000

12 : Dinesh : 50000

import java.util.HashMap;
 
public class MyHashMapCopy {
 
    public static void main(String a[]){
        HashMap<String, String> hm = new HashMap<String, String>();
        //add key-value pair to hashmap
        hm.put("first", "FIRST INSERTED");
        hm.put("second", "SECOND INSERTED");
        hm.put("third","THIRD INSERTED");
        System.out.println(hm);
        HashMap<String, String> subMap = new HashMap<String, String>();
        subMap.put("s1", "S1 VALUE");
        subMap.put("s2", "S2 VALUE");
        hm.putAll(subMap);
        System.out.println(hm);
    }
}

Output:

{second=SECOND INSERTED, third=THIRD INSERTED, first=FIRST INSERTED}

{s2=S2 VALUE, s1=S1 VALUE, second=SECOND INSERTED, third=THIRD INSERTED, first=FIRST INSERTED}

import java.util.HashMap;
import java.util.Set;
 
public class MyDuplicateKeyEx {
 
    public static void main(String a[]){
         
        HashMap<Price, String> hm = new HashMap<Price, String>();
        hm.put(new Price("Banana", 20), "Banana");
        hm.put(new Price("Apple", 40), "Apple");
        hm.put(new Price("Orange", 30), "Orange");
        printMap(hm);
        Price key = new Price("Banana", 20);
        System.out.println("Adding duplicate key...");
        hm.put(key, "Grape");
        System.out.println("After adding dulicate key:");
        printMap(hm);
    }
     
    public static void printMap(HashMap<Price, String> map){
         
        Set<Price> keys = map.keySet();
        for(Price p:keys){
            System.out.println(p+"==>"+map.get(p));
        }
    }
}
 
class Price{
     
    private String item;
    private int price;
     
    public Price(String itm, int pr){
        this.item = itm;
        this.price = pr;
    }
     
    public int hashCode(){
        int hashcode = 0;
        hashcode = price*20;
        hashcode += item.hashCode();
        return hashcode;
    }
     
    public boolean equals(Object obj){
        if (obj instanceof Price) {
            Price pp = (Price) obj;
            return (pp.item.equals(this.item) && pp.price == this.price);
        } else {
            return false;
        }
    }
     
    public String getItem() {
        return item;
    }
    public void setItem(String item) {
        this.item = item;
    }
    public int getPrice() {
        return price;
    }
    public void setPrice(int price) {
        this.price = price;
    }
     
    public String toString(){
        return "item: "+item+"  price: "+price;
    }
}

Output:

item: Apple  price: 40==>Apple

item: Orange  price: 30==>Orange

item: Banana  price: 20==>Banana

Adding duplicate key…

After adding dulicate key:

item: Apple  price: 40==>Apple

item: Orange  price: 30==>Orange

item: Banana  price: 20==>Grape

import java.util.HashMap;
import java.util.Set;
 
public class MyDuplicateKeyEx {
 
    public static void main(String a[]){
         
        HashMap<Price, String> hm = new HashMap<Price, String>();
        hm.put(new Price("Banana", 20), "Banana");
        hm.put(new Price("Apple", 40), "Apple");
        hm.put(new Price("Orange", 30), "Orange");
        printMap(hm);
        Price key = new Price("Banana", 20);
        System.out.println("Adding duplicate key...");
        hm.put(key, "Grape");
        System.out.println("After adding dulicate key:");
        printMap(hm);
    }
     
    public static void printMap(HashMap<Price, String> map){
         
        Set<Price> keys = map.keySet();
        for(Price p:keys){
            System.out.println(p+"==>"+map.get(p));
        }
    }
}
 
class Price{
     
    private String item;
    private int price;
     
    public Price(String itm, int pr){
        this.item = itm;
        this.price = pr;
    }
     
    public int hashCode(){
        int hashcode = 0;
        hashcode = price*20;
        hashcode += item.hashCode();
        return hashcode;
    }
     
    public boolean equals(Object obj){
        if (obj instanceof Price) {
            Price pp = (Price) obj;
            return (pp.item.equals(this.item) && pp.price == this.price);
        } else {
            return false;
        }
    }
     
    public String getItem() {
        return item;
    }
    public void setItem(String item) {
        this.item = item;
    }
    public int getPrice() {
        return price;
    }
    public void setPrice(int price) {
        this.price = price;
    }
     
    public String toString(){
        return "item: "+item+"  price: "+price;
    }
}

Output:

item: Apple  price: 40==>Apple

item: Orange  price: 30==>Orange

item: Banana  price: 20==>Banana

Adding duplicate key…

After adding dulicate key:

item: Apple  price: 40==>Apple

item: Orange  price: 30==>Orange

item: Banana  price: 20==>Grape

import java.util.Comparator;
import java.util.TreeMap;
 
public class MyTreeMapComparator {
     
    public static void main(String a[]){
        //the treemap sorts by key
        TreeMap<String, String> hm = new TreeMap<String, String>(new MyComp());
        //add key-value pair to TreeMap
        hm.put("java", "language");
        hm.put("computer", "machine");
        hm.put("india","country");
        hm.put("mango","fruit");
        System.out.println(hm);
    }
}
 
class MyComp implements Comparator<String>{
 
    @Override
    public int compare(String str1, String str2) {
        return str1.compareTo(str2);
    }
     
}

Output:

{computer=machine, india=country, java=language, mango=fruit}

import java.util.Comparator;
import java.util.Set;
import java.util.TreeMap;
 
public class MyTMCompUserDefine {
 
    public static void main(String a[]){
        //By using name comparator (String comparison)
        TreeMap<Empl,String> tm = new TreeMap<Empl, String>(new MyNameComp());
        tm.put(new Empl("Ram",3000), "RAM");
        tm.put(new Empl("John",6000), "JOHN");
        tm.put(new Empl("Crish",2000), "CRISH");
        tm.put(new Empl("Tom",2400), "TOM");
        Set<Empl> keys = tm.keySet();
        for(Empl key:keys){
            System.out.println(key+" ==> "+tm.get(key));
        }
        System.out.println("===================================");
        //By using salary comparator (int comparison)
        TreeMap<Empl,String> trmap = new TreeMap<Empl, String>(new MySalaryComp());
        trmap.put(new Empl("Ram",3000), "RAM");
        trmap.put(new Empl("John",6000), "JOHN");
        trmap.put(new Empl("Crish",2000), "CRISH");
        trmap.put(new Empl("Tom",2400), "TOM");
        Set<Empl> ks = trmap.keySet();
        for(Empl key:ks){
            System.out.println(key+" ==> "+trmap.get(key));
        }
    }
}
 
class MyNameComp implements Comparator<Empl>{
 
    @Override
    public int compare(Empl e1, Empl e2) {
        return e1.getName().compareTo(e2.getName());
    }
}
 
class MySalaryComp implements Comparator<Empl>{
 
    @Override
    public int compare(Empl e1, Empl e2) {
        if(e1.getSalary() > e2.getSalary()){
            return 1;
        } else {
            return -1;
        }
    }
}
 
class Empl{
     
    private String name;
    private int salary;
     
    public Empl(String n, int s){
        this.name = n;
        this.salary = s;
    }
     
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getSalary() {
        return salary;
    }
    public void setSalary(int salary) {
        this.salary = salary;
    }
    public String toString(){
        return "Name: "+this.name+"-- Salary: "+this.salary;
    }
}

Output:

Name: Crish– Salary: 2000 ==> CRISH

Name: John– Salary: 6000 ==> JOHN

Name: Ram– Salary: 3000 ==> RAM

Name: Tom– Salary: 2400 ==> TOM

===================================

Name: Crish– Salary: 2000 ==> CRISH

Name: Tom– Salary: 2400 ==> TOM

Name: Ram– Salary: 3000 ==> RAM

Name: John– Salary: 6000 ==> JOHN

import java.util.Comparator;
import java.util.Map;
import java.util.TreeMap;
 
public class MyReverseOrderMap {
 
    public static void main(String a[]){
        //the treemap sorts by key
        TreeMap<String, String> hm = new TreeMap<String, String>(new MyCopr());
        //add key-value pair to TreeMap
        hm.put("java", "language");
        hm.put("computer", "machine");
        hm.put("india","country");
        hm.put("mango","fruit");
        hm.put("game","cricket");
        System.out.println("TreeMap Entries:");
        System.out.println(hm);
        Map<String, String> rm = hm.descendingMap();
        System.out.println("Reverse Map Content: ");
        System.out.println(rm);
    }
}
 
class MyCopr implements Comparator<String>{
 
    @Override
    public int compare(String str1, String str2) {
        return str1.compareTo(str2);
    }
     
}

Output:

TreeMap Entries:

{computer=machine, game=cricket, india=country, java=language, mango=fruit}

Reverse Map Content:

{mango=fruit, java=language, india=country, game=cricket, computer=machine}

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
 
public class MyListBinarySearch {
 
    public static void main(String a[]){
         
        List<Emp> empList = new ArrayList<Emp>();
        empList.add(new Emp(12,"Dinesh",50000));
        empList.add(new Emp(146,"Tom",20000));
        empList.add(new Emp(201,"John",40000));
        empList.add(new Emp(302,"Krish",44500));
        empList.add(new Emp(543,"Abdul",10000));
         
        Emp searchKey = new Emp(201,"John",40000);
        int index = Collections.binarySearch(empList, searchKey, new EmpComp());
        System.out.println("Index of the searched key: "+index);
    }
}
 
class EmpComp implements Comparator<Emp>{
 
    public int compare(Emp e1, Emp e2) {
        if(e1.getEmpId() == e2.getEmpId()){
            return 0;
        } else {
            return -1;
        }
    }
}
 
class Emp {
     
    private int empId;
    private String empName;
    private int empSal;
     
    public Emp(int id, String name, int sal){
        this.empId = id;
        this.empName = name;
        this.empSal = sal;
    }
     
    public int getEmpId() {
        return empId;
    }
     
    public void setEmpId(int empId) {
        this.empId = empId;
    }
     
    public String getEmpName() {
        return empName;
    }
     
    public void setEmpName(String empName) {
        this.empName = empName;
    }
     
    public int getEmpSal() {
        return empSal;
    }
    public void setEmpSal(int empSal) {
        this.empSal = empSal;
    }
     
    public String toString(){
        return empId+" : "+empName+" : "+empSal;
    }
}

Output:

Index of the searched key: 2

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
 
public class MyCheckedList {
 
    public static void main(String a[]){
         
        List myList = new ArrayList();
        myList.add("one");
        myList.add("two");
        myList.add("three");
        myList.add("four");
        List chkList = Collections.checkedList(myList, String.class);
        System.out.println("Checked list content: "+chkList);
        //you can add any type of elements to myList object
        myList.add(10);
        //you cannot add any type of elements to chkList object, doing so
        //throws ClassCastException
        chkList.add(10); //throws ClassCastException
    }
}

Output:

Checked list content:

[one, two, three, four]

Exception in thread “main” java.lang.ClassCastException: Attempt to insert class java.lang.Integer element into

                                                            collection with element type class java.lang.String

            at java.util.Collections$CheckedCollection.typeCheck(Collections.java:2202)

            at java.util.Collections$CheckedCollection.add(Collections.java:2243)

            at com.java2novice.collections.MyCheckedList.main(MyCheckedList.java:22)

import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
 
public class MyCheckedSet {
 
    public static void main(String a[]){
         
        Set mySet = new HashSet();
        mySet.add("one");
        mySet.add("two");
        mySet.add("three");
        mySet.add("four");
        Set chkSet = Collections.checkedSet(mySet, String.class);
        System.out.println("Checked set content: "+chkSet);
        //you can add any type of elements to mySet object
        mySet.add(10);
        //you cannot add any type of elements to chkSet object, doing so
        //throws ClassCastException
        chkSet.add(10); //throws ClassCastException
    }
}

Output:
Checked set content: [two, one, three, four]
Exception in thread “main” java.lang.ClassCastException: Attempt to insert class java.lang.Integer element into
collection with element type class java.lang.String
at java.util.Collections$CheckedCollection.typeCheck(Collections.java:2202)
at java.util.Collections$CheckedCollection.add(Collections.java:2243)
at com.java2novice.collections.MyCheckedSet.main(MyCheckedSet.java:22)

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
 
public class MyCheckedMap {
 
    public static void main(String a[]){
         
        Map myMap = new HashMap();
        myMap.put("one", 1);
        myMap.put("two", 2);
        myMap.put("three", 3);
        myMap.put("four", 4);
        Map chkMap = Collections.checkedMap(myMap, String.class, Integer.class);
        System.out.println("Checked map content: "+chkMap);
        //you can add any type of elements to myMap object
        myMap.put(10, "ten");
        //you cannot add any type of elements to chkMap object, doing so
        //throws ClassCastException
        chkMap.put(10, "ten"); //throws ClassCastException
    }
}

Output:
Checked map content: {two=2, one=1, three=3, four=4}
Exception in thread “main” java.lang.ClassCastException: Attempt to insert class java.lang.Integer key into
collection with key type class java.lang.String
at java.util.Collections$CheckedMap.typeCheck(Collections.java:2547)
at java.util.Collections$CheckedMap.put(Collections.java:2579)
at com.java2novice.collections.MyCheckedMap.main(MyCheckedMap.java:22)

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
 
public class MyCheckedMap {
 
    public static void main(String a[]){
         
        Map myMap = new HashMap();
        myMap.put("one", 1);
        myMap.put("two", 2);
        myMap.put("three", 3);
        myMap.put("four", 4);
        Map chkMap = Collections.checkedMap(myMap, String.class, Integer.class);
        System.out.println("Checked map content: "+chkMap);
        //you can add any type of elements to myMap object
        myMap.put(10, "ten");
        //you cannot add any type of elements to chkMap object, doing so
        //throws ClassCastException
        chkMap.put(10, "ten"); //throws ClassCastException
    }
}

Output:
Checked map content: {two=2, one=1, three=3, four=4}
Exception in thread “main” java.lang.ClassCastException: Attempt to insert class java.lang.Integer key into
collection with key type class java.lang.String
at java.util.Collections$CheckedMap.typeCheck(Collections.java:2547)
at java.util.Collections$CheckedMap.put(Collections.java:2579)
at com.java2novice.collections.MyCheckedMap.main(MyCheckedMap.java:22)

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
 
public class MyListDisjoint {
 
    public static void main(String a[]){
         
        List<String> sl = new ArrayList<String>();
        sl.add("apple");
        sl.add("java");
        sl.add("c++");
        sl.add("unix");
        sl.add("orange");
        sl.add("airtel");
        List<String> tl = new ArrayList<String>();
        tl.add("job");
        tl.add("oracle");
        tl.add("jungle");
        tl.add("cricket");
        boolean isCommon = Collections.disjoint(sl,tl);
        System.out.println("Does not found any common elements? "+isCommon);
        tl.add("java");
        isCommon = Collections.disjoint(sl,tl);
        System.out.println("Does not found any common elements? "+isCommon);
    }
}

Output:

Does not found any common elements? true

Does not found any common elements? False

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
 
public class MyListRotate {
     
    public static void main(String a[]){
         
        List<String> list = new ArrayList<String>();
        list.add("java");
        list.add("c");
        list.add("c++");
        list.add("unix");
        list.add("perl");
        list.add("php");
        list.add("javascript");
        list.add("ruby");
        list.add(".net");
        System.out.println(list);
        Collections.rotate(list, 3);
        System.out.println("List after rotation:");
        System.out.println(list);
    }
}

The Java API provides the URL class which can be used to represent the URL address. You can create the URL object if you have the URL address string. The URL class provides getter methods to get the components of the URL such as host name, port, path, query parameters etc.

Example:

String urlString = 'https://www.kodnest.com';
 URL url = new URL(urlString);

The Java API provides the ‘URLConnecton’ class which can be used to create a connection to a URL. If you have a URL object, you can get the URLConnection object by calling openConnection() method on the URL object. Once you have the URLConnection object you can connect to the URL resource by calling the connect() method on the URLConnection object. You can use the URLRequest object to setup parameters and properties that you may need for making the URL connection.

Example:

String urlString = 'https://www.kodnest.com';
URL myUrl = new URL(urlString);
URLConnection myUrlConnection = myUrl.openConnection();
myUrlConnection.connect();
  • Create the URL object
  • Create URLConnection object
  • Open connection to URL
  • Get input stream from connection
  • Read from input stream
  • Close input stream
  • Create the URL object
  • Create URLConnection object
  • Open connection to URL
  • Get output stream from connection
  • Write to output stream
  • Close output stream

Sockets are end points in the communication link between a client program and a server program exchanging data over a network.

On the server side, a socket is bound to a specific port number. The server listens to the socket, waiting for a client to make a connection request.If a connection from a client is successful, the existing socked is used to communicate with that client. In addition a new socket is created and ties to the same port so that the server can listen to new connections from other clients.A new

On the client side: The client makes a connection request to the server, specific to the port number that the server socket is tied to. To successfully connect to the server, the client has to identify itself to the server along with its port number. Hence the client binds itself to a local port before making the connection request.If the connection is successful, a socket is created on the client side that is tied to the port and is used for communicating with the server. The Java programming language provides two classes to represent sockets. Class ‘java.net.Socket’ represents a socket at the client side. Class ‘java.net.ServerSocket’ represents a socket on the server side.

  • Open a socket
  • Open an input stream and output stream to a socket
  • Read from and write to a stream
  • Close the streams
  • Close the socket

TCP is a protocol that provides a reliable, point-to-point communication channel that client-server application use to communicate with each other. To communicate over TCP, a client program and server program must first establish a connection to each other through sockets at each end of the communication channel. To communicate, the client and server reads from and writes to the sockets bound to the connection. Like TCP, UDP is protocol that provides a communication channel that client-server applications use to communicate with each other. But unlike TCP, the message content and arrival time of communication sent via UDP are not guaranteed. In UDP messages are sent via datagrams, which are independent, self-contained packets of data.

Datagram is an independent, self-contained packet of information send over the network between server and client programs in UDP protocol. The delivery of datagrams to their destinations in not guaranteed. The order of arrival of datagrams to their destinations is not guaranteed. Datagrams can be send or broadcast to multiple recipients. Java programming language provides three main classes that can be used to program datagrams – java.net.DatagramPacket, java.net.DatagramSocket, java.net.MultigramSocket

A network interface is the point of interconnection between a computer and a private or public network. A network interface is generally a network interface card (NIC). Network interfaces can either have a physical form or can be implemented in software. The Java networking API provides the java.net.NetworkInterface class which represents both these types of interfaces.

You can get a list of IP addresses that are assigned to a network interface using the NetworkInterface class. You can obtain this information from a NetworkInterface instance by using one of two methods.

  • getInetAddresses() – returns an Enumeration of InetAddress.
  • getInterfaceAddresses() – returns a list of java.net.InterfaceAddress instances. This method is used when you need more information about an interface address beyond its IP address such as it subnet mask.

MyServer.java

import java.io.*;  
import java.net.*;  
public class MyServer {  
public static void main(String[] args){  
try{  
ServerSocket ss=new ServerSocket(6666);  
Socket s=ss.accept();//establishes connection   
DataInputStream dis=new DataInputStream(s.getInputStream());  
String  str=(String)dis.readUTF();  
System.out.println("message= "+str);  
ss.close();  
}catch(Exception e){System.out.println(e);}  
}  
}  

MyClient.java

import java.io.*;  
import java.net.*;  
public class MyClient
 {  
public static void main(String[] args) 
{  
try{      
Socket s=new Socket("localhost",6666);  
DataOutputStream dout=new DataOutputStream(s.getOutputStream());  
dout.writeUTF("Hello Server");  
dout.flush();  
dout.close();  
s.close();  
}catch(Exception e){System.out.println(e);}  
}  
}  

MyServer.java

import java.net.*;  
import java.io.*;  
class MyServer
{  
public static void main(String args[])throws Exception
{  
ServerSocket ss=new ServerSocket(3333);  
Socket s=ss.accept();  
DataInputStream din=new DataInputStream(s.getInputStream());  
DataOutputStream dout=new DataOutputStream(s.getOutputStream());  
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));  
  
String str="",str2="";  
while(!str.equals("stop")){  
str=din.readUTF();  
System.out.println("client says: "+str);  
str2=br.readLine();  
dout.writeUTF(str2);  
dout.flush();  
}  
din.close();  
s.close();  
ss.close();  
}
}  

MyClient.java

import java.net.*;  
import java.io.*;  
class MyClient
{  
public static void main(String args[])throws Exception
{  
Socket s=new Socket("localhost",3333);  
DataInputStream din=new DataInputStream(s.getInputStream());  
DataOutputStream dout=new DataOutputStream(s.getOutputStream());  
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));  
  
String str="",str2="";  
while(!str.equals("stop")){  
str=br.readLine();  
dout.writeUTF(str);  
dout.flush();  
str2=din.readUTF();  
System.out.println("Server says: "+str2);  
}    
dout.close();  
s.close();  
}
}  
×