Advanced Java interview questions

Category : Java | Sub Category : Java Interview questions | By Prasad Bonam Last updated: 2020-10-20 11:14:53 Viewed : 535


          

    Advanced Java interview questions  

   

1.        What are Variable Arguments or varargs?

Variable Arguments allow calling a method with different number of parameters. Consider the example method sum below. This sum method can be called with 1 int parameter or 2 int parameters or more int parameters.

 

//int(type) followed ... (three dot`s) is syntax of a variable argument.

public int sum(int... numbers) {

//inside the method a variable argument is similar to an array.

//number can be treated as if it is declared as int[] numbers;

int sum = 0;

for (int number: numbers) { sum += number;

}

return sum;

}


public static void main(String[] args) {

VariableArgumentExamples example = new VariableArgumentExamples();

//3 Arguments System.out.println(example.sum(1, 4, 5));//10

//4 Arguments

System.out.println(example.sum(1, 4, 5, 20));//30

//0 Arguments System.out.println(example.sum());//0

}

 

 

2.          What are Asserts used for?

Assertions are introduced in Java 1.4. They enable you to validate assumptions. If an assert fails (i.e. returns false), AssertionError is thrown (if assertions are enabled). Basic assert is shown in the example below

 

private int computerSimpleInterest(int principal,float interest,int years){

assert(principal>0); return 100;

}

 

 

3.          When should Asserts be used?

Assertions should not be used to validate input data to a public method or command line argument. IllegalArgumentException would be a better option. In public method, only use assertions to check for cases which are never supposed to happen.

 

4.          What is Garbage Collection?

Garbage Collection is a name given to automatic memory management in Java. Aim of Garbage Collection is to Keep as much of heap available (free) for the program as possible. JVM removes objects on the heap which no longer have references from the heap.

 

5.          Can you explain Garbage Collection with an example?

Let`s say the below method is called from a function.

 

void method(){

Calendar calendar = new GregorianCalendar(2000,10,30); System.out.println(calendar);

}

 

An object of the class GregorianCalendar is created on the heap by the first line of the function with one reference variable calendar.

 

After the function ends execution, the reference variable calendar is no longer valid. Hence, there are no references to the object created in the method.

 

JVM recognizes this and removes the object from the heap. This is called Garbage Collection.

 

6.          When is Garbage Collection run?

Garbage Collection runs at the whims and fancies of the JVM (it isn`t as bad as that). Possible situations when Garbage Collection might run are

·        when available memory on the heap is low

·        when cpu is free


 

 

7.          What are best practices on Garbage Collection?

Programmatically, we can request (remember it`s just a request - Not an order) JVM to run Garbage Collection by calling System.gc() method.

 

JVM might throw an OutOfMemoryException when memory is full and no objects on the heap are eligible for garbage collection.

 

finalize() method on the objected is run before the object is removed from the heap from the garbage collector. We recommend not to write any code in finalize();

 

 

8.          What are Initialization Blocks?

Initialization Blocks - Code which runs when an object is created or a class is loaded

There are two types of Initialization Blocks

Static Initializer: Code that runs when a class is loaded.

Instance Initializer: Code that runs when a new object is created.

 

 

9.          What is a Static Initializer?

Look at the example below:

 

public class InitializerExamples {

static int count;

int i;

 

static{

//This is a static initializers. Run only when Class is first loaded.

//Only static variables can be accessed System.out.println("Static Initializer");

//i = 6;//COMPILER ERROR

System.out.println("Count when Static Initializer is run is " + count);

}

 

public static void main(String[] args) {

InitializerExamples example = new InitializerExamples(); InitializerExamples example2 = new InitializerExamples(); InitializerExamples example3 = new InitializerExamples();

}

}

 

Code within static{ and } is called a static initializer. This is run only when class is first loaded. Only static variables can be accessed in a static initializer.

Example Output

Static Initializer

Count when Static Initializer is run is 0

 

Even though three instances are created static initializer is run only once.

 

 

10.       What is an Instance Initializer Block?

Let`s look at an example

public class InitializerExamples {

static int count;

int i;

{

//This is an instance initializers. Run every time an object is created.

//static and instance variables can be accessed System.out.println("Instance Initializer");

i = 6;

count = count + 1;

System.out.println("Count when Instance Initializer is run is " + count);

}

 

public static void main(String[] args) {

InitializerExamples example = new InitializerExamples(); InitializerExamples example1 = new InitializerExamples();


InitializerExamples example2 = new InitializerExamples();

}

 

}

 

Code within instance initializer is run every time an instance of the class is created. 

Example Output

Instance Initializer

Count when Instance Initializer is run is 1 Instance Initializer

Count when Instance Initializer is run is 2 Instance Initializer

Count when Instance Initializer is run is 3

11.       What are Regular Expressions?


Regular Expressions make parsing, scanning and splitting a string very easy. We will first look at how you can evaluate a regular expressions in Java using Patter, Matcher and Scanner classes. We will then look into how to write a regular expression.

12.       What is Tokenizing?

Tokenizing means splitting a string into several sub strings based on delimiters. For example, delimiter ; splits the string ac;bd;def;e into four sub strings ac, bd, def and e.

Delimiter can in itself be any of the regular expression(s) we looked at earlier. String.split(regex) function takes regex as an argument.

13.       Can you give an example of Tokenizing?


private static void tokenize(String string,String regex) { String[] tokens = string.split(regex); System.out.println(Arrays.toString(tokens));

}

 

Example:

tokenize("ac;bd;def;e",";");//[ac, bd, def, e]

 

14.       How can you Tokenize using Scanner Class?


private static void tokenizeUsingScanner(String string,String regex) { Scanner scanner = new Scanner(string); scanner.useDelimiter(regex);

List<String> matches = new ArrayList<String>();

while(scanner.hasNext()){ matches.add(scanner.next());

}

System.out.println(matches);

}

 

Example:

tokenizeUsingScanner("ac;bd;def;e",";");//[ac, bd, def, e]


15.       How do you add hours to a date object?


 Lets now look at adding a few hours to a date object. All date manipulation to date needs to be done by adding milliseconds to the date. For example, if we want to add 6 hour, we convert 6 hours into millseconds. 6 hours = 6 * 60 * 60 * 1000 milliseconds. Below examples shows specific code.

 

Date date = new Date();

 

//Increase time by 6 hrs date.setTime(date.getTime() + 6 * 60 * 60 * 1000); System.out.println(date);

 

//Decrease time by 6 hrs date = new Date();

date.setTime(date.getTime() -­ 6 * 60 * 60 * 1000); System.out.println(date);

 

16.       How do you format Date Objects?


Formatting Dates is done by using DateFormat class. Let`s look at a few examples.

 

//Formatting Dates System.out.println(DateFormat.getInstance().format(

date));//10/16/12 5:18 AM

 

Formatting Dates with a locale

 

System.out.println(DateFormat.getDateInstance( DateFormat.FULL, new Locale("it", "IT"))

.format(date));//marted“ 16 ottobre 2012

 

System.out.println(DateFormat.getDateInstance( DateFormat.FULL, Locale.ITALIAN)

.format(date));//marted“ 16 ottobre 2012

 

//This uses default locale US System.out.println(DateFormat.getDateInstance(

DateFormat.FULL).format(date));//Tuesday, October 16, 2012

 

System.out.println(DateFormat.getDateInstance()

.format(date));//Oct 16, 2012 System.out.println(DateFormat.getDateInstance(

DateFormat.SHORT).format(date));//10/16/12 System.out.println(DateFormat.getDateInstance(

DateFormat.MEDIUM).format(date));//Oct 16, 2012

 

System.out.println(DateFormat.getDateInstance( DateFormat.LONG).format(date));//October 16, 2012

 

17.       What is the use of Calendar class in Java?


  Calendar class provides easy ways to add or reduce days, months or years


from a date. It also provide lot of details about a date (which day of the year? Which week of the year? etc.)

18.       How do you get an instance of Calendar class in Java?


Calendar class cannot be created by using new Calendar. The best way to get an instance of Calendar class is by using getInstance() static method in Calendar.

//Calendar calendar = new Calendar(); //COMPILER ERROR Calendar calendar = Calendar.getInstance();

 

19.       Can you explain some of the important methods in Calendar class?

Setting day, month or year on a calendar object is simple. Call the set method with appropriate Constant for Day, Month or Year. Next parameter is the value.

calendar.set(Calendar.DATE, 24); calendar.set(Calendar.MONTH, 8);//8 -­ September calendar.set(Calendar.YEAR, 2010);

 

20.       Calendar get method


Let`s get information about a particular date 24th September 2010. We use the calendar get method. The parameter passed indicates what value we would want to get from the calendar – day or month or year or .. Few examples of the values you can obtain from a calendar are listed below.

System.out.println(calendar.get(Calendar.YEAR));//2010 System.out.println(calendar.get(Calendar.MONTH));//8 System.out.println(calendar.get(Calendar.DATE));//24 System.out.println(calendar.get(Calendar.WEEK_OF_MONTH));//4 System.out.println(calendar.get(Calendar.WEEK_OF_YEAR));//39 System.out.println(calendar.get(Calendar.DAY_OF_YEAR));//267 System.out.println(calendar.getFirstDayOfWeek());//1> Calendar.SUNDAY

 

21.       What is the use of NumberFormat class?

Number format is used to format a number to different locales and different formats.

 

22.       Format number Using Default locale

System.out.println(NumberFormat.getInstance().format(321.24f));//321.24

 

23.       Format number using locale

Formatting a number using Netherlands locale System.out.println(NumberFormat.getInstance(new Locale("nl")).format(4032.3f));//4.032,3

 

Formatting a number using Germany locale System.out.println(NumberFormat.getInstance(Locale.GERMANY).format(4032.3f));//4.032, 3

 

24.       Formatting a Currency using Default locale

System.out.println(NumberFormat.getCurrencyInstance().format(40324.31f));//$40,324.31

 

25.       Format currency using locale

Formatting a Currency using Netherlands locale


System.out.println(NumberFormat.getCurrencyInstance(new Locale("nl")).format(40324.31f));//? 40.324,31

 

 

Collections Interfaces

 

26.       Why do we need Collections in Java?

Arrays are not dynamic. Once an array of a particular size is declared, the size cannot be modified. To add a new element to the array, a new array has to be created with bigger size and all the elements from the old array copied to new array.

Collections are used in situations where data is dynamic. Collections allow adding an element, deleting an element and host of other operations. There are a number of Collections in Java allowing to choose the right Collection for the right context.

 

27.       What are the important methods that are declared in the Collection Interface?

 Most important methods declared in the collection interface are the methods to add and remove an element. add method allows adding an element to a collection and delete method allows deleting an  element from a collection.

size() methods returns number of elements in the collection. Other important methods defined as part of collection interface are shown below.

interface Collection<E> extends Iterable<E>

{

boolean add(E paramE);

boolean remove(Object paramObject);

 

int size(); boolean isEmpty(); void clear();

 

boolean contains(Object paramObject);

boolean containsAll(Collection<?> paramCollection);

 

boolean addAll(Collection<? extends E> paramCollection); boolean removeAll(Collection<?> paramCollection); boolean retainAll(Collection<?> paramCollection);

 

 

Iterator<E> iterator();

 

//A NUMBER OF OTHER METHODS AS WELL..

}


28.       Can you explain briefly about the List Interface?


List interface extends Collection interface. So, it contains all methods defined in the Collection interface. In addition, List interface allows operation specifying the position of the element in the Collection.

Most important thing to remember about a List interface any implementation of the List interface would maintain the insertion order. When an element A is inserted into a List (without specifying position) and then another element B is inserted, A is stored before B in the List.

When a new element is inserted without specifying a position, it is inserted at the end of the list of elements.

 

However, We can also use the void add(int position, E paramE); method to insert an element at a specific position.

Listed below are some of the important methods in the List interface (other than those inherited from Collection interface):

 

interface List<E> extends Collection<E>

{

boolean addAll(int paramInt, Collection<? extends E> paramCollection);

 

E get(int paramInt);

E set(int paramInt, E paramE);

 

void add(int paramInt, E paramE); E remove(int paramInt);

 

int indexOf(Object paramObject);

int lastIndexOf(Object paramObject);

 

ListIterator<E> listIterator(); ListIterator<E> listIterator(int paramInt); List<E> subList(int paramInt1, int paramInt2);

}

 

29.       Can you briefly explain about the Map Interface?


First and foremost, Map interface does not extend Collection interface. So, it does not inherit any of the methods from the Collection interface.

A  Map  interface supports Collections that use a key value pair. A  keyvalue pair is a set of linked data items: a key, which is a unique identifier for some item of data, and the value, which is either the data or a pointer to the data. Keyvalue pairs are used in lookup tables, hash tables and configuration files. A key value pair in a Map interface is called an Entry.

Put method allows to add a key, value pair to the Map.

 

V put(K paramK, V paramV);

 

Get method allows to get a value from the Map based on the key.

 

V get(Object paramObject);


 

Other important methods in Map Inteface are shown below:

 

interface Map<K, V>

{

int size();

boolean isEmpty();

 

boolean containsKey(Object paramObject);

boolean containsValue(Object paramObject);

 

V get(Object paramObject); V put(K paramK, V paramV);

V remove(Object paramObject);

 

void putAll(Map<? extends K, ? extends V> paramMap);

void clear();

 

Set<K> keySet(); Collection<V> values(); Set<Entry<K, V>> entrySet();

 

boolean equals(Object paramObject);

int hashCode();

 

public static abstract interface Entry<K, V>

{

K getKey();

V getValue();

V setValue(V paramV);

boolean equals(Object paramObject);

int hashCode();

}

}

 

30.       What is the difference between Set and SortedSet?


SortedSet Interface extends the Set Interface. Both Set and SortedSet do not allow duplicate elements.

 

Main difference between Set and SortedSet is an implementation of SortedSet interface maintains its elements in a sorted order. Set interface does not guarantee any Order. For example, If elements 4,5,3 are inserted into an implementation of Set interface, it might store the elements in any order. However, if we use SortedSet, the elements are sorted. The SortedSet implementation would give an output 3,4,5.

Important Operations in the SortedSet interface which are not present in the Set Interface are listed below:

public interface SortedSet<E> extends Set<E> {

 

SortedSet<E> subSet(E fromElement, E toElement); SortedSet<E> headSet(E toElement);

SortedSet<E> tailSet(E fromElement);


 

E first();

E last();

 

Comparator<? super E> comparator();

}

 

31.       What is difference between Map and SortedMap?

SortedMap interface extends the Map interface. In addition, an implementation of SortedMap interface maintains keys in a sorted order.

Methods are available in the interface to get a ranges of values based on their keys.

 

public interface SortedMap<K, V> extends Map<K, V> { Comparator<? super K> comparator();

 

SortedMap<K, V> subMap(K fromKey, K toKey); SortedMap<K, V> headMap(K toKey); SortedMap<K, V> tailMap(K fromKey);

K firstKey();

 

K lastKey();

}

 

32.       Explain briefly about Queue Interface?

Queue Interface extends Collection interface. Queue Interface is typically used for implementation holding elements in order for some processing.

 

Queue interface offers methods peek() and poll() which get the element at head of the queue. The difference is that poll() method removes the head from queue also. peek() would keep head of the queue unchanged.

interface Queue<E> extends Collection<E>

{

boolean offer(E paramE); E remove();

E poll();

E element();

E peek();

}

 

33.       Explain briefly about Iterator?

Iterator interface enables us to iterate (loop around) a collection. All collections define a method iterator() that gets an iterator of the collection.

hasNext() checks if there is another element in the collection being iterated. next() gets the next element.


public interface Iterator<E> {

boolean hasNext();

 

E next();

}

 

 

ArrayList

 

34.        Explain about ArrayList with an example?

ArrayList implements the list interface. So, ArrayList stores the elements in insertion order (by default). Element`s can be inserted into and removed from ArrayList based on their position.

Let`s look at how to instantiate an ArrayList of integers.

 

List<Integer> integers = new ArrayList<Integer>();

 

Code like below is permitted because of auto boxing. 5 is auto boxed into Integer object and stored in ArrayList.

integers.add(5);//new Integer(5)

 

Add method (by default) adds the element at the end of the list.

 

35.       Can an ArrayList have Duplicate elements?

ArrayList can have duplicates (since List can have duplicates).

 

List<String> arraylist = new ArrayList<String>();

 

//adds at the end of list arraylist.add("Sachin");//[Sachin]

 

//adds at the end of list arraylist.add("Dravid");//[Sachin, Dravid]

 

//adds at the index 0

arraylist.add(0, "Ganguly");//[Ganguly, Sachin, Dravid]

 

//List allows duplicates -­ Sachin is present in the list twice arraylist.add("Sachin");//[ Ganguly, Sachin, Dravid, Sachin]

 

System.out.println(arraylist.size());//4 System.out.println(arraylist.contains("Dravid"));//true

 

36.       How do you iterate around an ArrayList using Iterator?

Example below shows how to iterate around an ArrayList.

 

Iterator<String> arraylistIterator = arraylist

.iterator();


while (arraylistIterator.hasNext()) { String str = arraylistIterator.next();

System.out.println(str);//Prints the 4 names in the list on separate lines.

}

 

37.       How do you sort an ArrayList?

Example below shows how to sort an ArrayList. It uses the Collections.sort method.

 

List<String> numbers = new ArrayList<String>(); numbers.add("one");

numbers.add("two"); numbers.add("three"); numbers.add("four");

System.out.println(numbers);//[one, two, three, four]

 

//Strings -­ By Default -­ are sorted alphabetically Collections.sort(numbers);

 

System.out.println(numbers);//[four, one, three, two]

 

38.       How do you sort elements in an ArrayList using Comparable interface?

Consider the following class Cricketer.

 

class Cricketer implements Comparable<Cricketer> {

int runs; String name;

 

public Cricketer(String name, int runs) {

super(); this.name = name; this.runs = runs;

}

 

@Override

public String toString() {

return name + " " + runs;

}

 

@Override

public int compareTo(Cricketer that) {

if (this.runs > that.runs) {

return 1;

}

if (this.runs < that.runs) {

return 1;

}

return 0;

}

}

 

Let`s now try to sort a list containing objects of Cricketer class.

 

List<Cricketer> cricketers = new ArrayList<Cricketer>(); cricketers.add(new Cricketer("Bradman", 9996));


cricketers.add(new Cricketer("Sachin", 14000));

cricketers.add(new Cricketer("Dravid", 12000));

cricketers.add(new Cricketer("Ponting", 11000)); System.out.println(cricketers);

//[Bradman 9996, Sachin 14000, Dravid 12000, Ponting 11000]

 

Now let`s try to sort the cricketers.

 

Collections.sort(cricketers); System.out.println(cricketers);

//[Bradman 9996, Ponting 11000, Dravid 12000, Sachin 14000]

 

39.       How do you sort elements in an ArrayList using Comparator interface?

 

Other option to sort collections is by creating a separate class which implements Comparator interface. Example below:

class DescendingSorter implements Comparator<Cricketer> {

 

//compareTo returns 1 if cricketer1 < cricketer2

//                             1 if cricketer1 > cricketer2

//                             0 if cricketer1 = cricketer2

 

//Since we want to sort in descending order,

//we should return -­1 when runs are more @Override

public int compare(Cricketer cricketer1, Cricketer cricketer2) {

if (cricketer1.runs > cricketer2.runs) {

return 1;

}

if (cricketer1.runs < cricketer2.runs) {

return 1;

}

return 0;

}

 

}

 

Let`s now try to sort the previous defined collection:

 

Collections

.sort(cricketers, new DescendingSorter());

 

System.out.println(cricketers);

//[Sachin 14000, Dravid 12000, Ponting 11000, Bradman 9996]

 

40.       How do you convert List to Array?

There are two ways. First is to use toArray(String) function. Example below. This creates an array of String`s

List<String> numbers1 = new ArrayList<String>();


numbers1.add("one"); numbers1.add("two"); numbers1.add("three"); numbers1.add("four");

String[] numbers1Array = new String[numbers1.size()]; numbers1Array = numbers1.toArray(numbers1Array); System.out.println(Arrays.toString(numbers1Array));

//prints [one, two, three, four]

 

Other is to use toArray() function. Example below. This creates an array of Objects.

 

Object[] numbers1ObjArray = numbers1.toArray(); System.out.println(Arrays

.toString(numbers1ObjArray));

//[one, two, three, four]

 

41.       How do you convert an Array to List?

String values[] = { "value1", "value2", "value3" }; List<String> valuesList = Arrays.asList(values); System.out.println(valuesList);//[value1, value2, value3]

 

Collections

 

42.       What is Vector class? How is it different from an ArrayList?

Vector has the same operations as an ArrayList. However, all methods in Vector are synchronized. So, we can use Vector if we share a list between two threads and we would want to them synchronized.

43.       What is LinkedList? What interfaces does it implement? How is it different from an ArrayList?

Linked List extends List and Queue.Other than operations exposed by the Queue interface, LinkedList has the same operations as an ArrayList. However, the underlying implementation of Linked List is different from that of an ArrayList.

ArrayList uses an Array kind of structure to store elements. So, inserting and deleting from an ArrayList are expensive operations. However, search of an ArrayList is faster than LinkedList.

LinkedList uses a linked representation. Each object holds a link to the next element. Hence, insertion and deletion are faster than ArrayList. But searching is slower.

44.       Can you give examples of classes that implement the Set Interface?

HashSet, LinkedHashSet and TreeSet implement the Set interface.   


45.       What is a HashSet?

HashSet implements set interface. So, HashSet does not allow duplicates. However, HashSet does not support ordering. The order in which elements are inserted is not maintained.

46.       HashSet Example

Set<String> hashset = new HashSet<String>();

 

hashset.add("Sachin"); System.out.println(hashset);//[Sachin]

 

hashset.add("Dravid"); System.out.println(hashset);//[Sachin, Dravid]

 

Let`s try to add Sachin to the Set now. Sachin is Duplicate. So will not be added. returns false.

 

hashset.add("Sachin");//returns false since element is not added System.out.println(hashset);//[Sachin, Dravid]

 

47.       What is a LinkedHashSet? How is different from a HashSet?

LinkedHashSet implements set interface and exposes similar operations to a HashSet. Difference is that LinkedHashSet maintains insertion order. When we iterate a LinkedHashSet, we would get the elements back in the order in which they were inserted.

48.       What is a TreeSet? How is different from a HashSet?

TreeSet implements Set, SortedSet and NavigableSet interfaces.TreeSet is similar to HashSet except that it stores element`s in Sorted Order.

Set<String> treeSet = new TreeSet<String>();

 

treeSet.add("Sachin"); System.out.println(treeSet);//[Sachin]

 

Notice that the list is sorted after inserting Dravid.

 

//Alphabetical order treeSet.add("Dravid");

System.out.println(treeSet);//[Dravid, Sachin]

 

Notice that the list is sorted after inserting Ganguly.

 

treeSet.add("Ganguly"); System.out.println(treeSet);//[Dravid, Ganguly, Sachin]

 

//Sachin is Duplicate. So will not be added. returns false. treeSet.add("Sachin");//returns false since element is not added System.out.println(treeSet);//[Dravid, Ganguly, Sachin]

 

49.       Can you give examples of implementations of NavigableSet?

TreeSet implements this interface. Let`s look at an example with TreeSet. Note that elements in TreeSet are sorted.


TreeSet<Integer> numbersTreeSet = new TreeSet<Integer>(); numbersTreeSet.add(55);

numbersTreeSet.add(25); numbersTreeSet.add(35); numbersTreeSet.add(5); numbersTreeSet.add(45);

 

NavigableSet interface has following methods.

 

Lower method finds the highest element lower than specified element. Floor method finds the highest element lower than or equal to specified element. Corresponding methods for finding lowest number higher than specified element are higher and ceiling. A few examples using the Set created earlier below.

//Find the highest number which is lower than 25 System.out.println(numbersTreeSet.lower(25));//5

 

//Find the highest number which is lower than or equal to 25 System.out.println(numbersTreeSet.floor(25));//25

 

//Find the lowest number higher than 25 System.out.println(numbersTreeSet.higher(25));//35

 

//Find the lowest number higher than or equal to 25 System.out.println(numbersTreeSet.ceiling(25));//25

 

50.       What are the different implementations of a Map Interface?

HashMap and TreeMap.  

What is a HashMap?

HashMap implements Map interface – there by supporting key value pairs. Let`s look at an example.

 

HashMap Example

Map<String, Cricketer> hashmap = new HashMap<String, Cricketer>(); hashmap.put("sachin",

new Cricketer("Sachin", 14000)); hashmap.put("dravid",

new Cricketer("Dravid", 12000)); hashmap.put("ponting", new Cricketer("Ponting",

11500));

hashmap.put("bradman", new Cricketer("Bradman", 9996));

 

51.       What are the different methods in a Hash Map?

get method gets the value of the matching key.

 

System.out.println(hashmap.get("ponting"));//Ponting 11500

 

//if key is not found, returns null. System.out.println(hashmap.get("lara"));//null


 

If existing key is reused, it would replace existing value with the new value passed in.

 

//In the example below, an entry with key "ponting" is already present.

//Runs are updated to 11800. hashmap.put("ponting", new Cricketer("Ponting",

11800));

 

//gets the recently updated value System.out.println(hashmap.get("ponting"));//Ponting 11800

 

52.       What is a TreeMap? How is different from a HashMap?

TreeMap is similar to HashMap except that it stores keys in sorted order. It implements NavigableMap interface and SortedMap interfaces along with the Map interface.

Map<String, Cricketer> treemap = new TreeMap<String, Cricketer>(); treemap.put("sachin",

new Cricketer("Sachin", 14000)); System.out.println(treemap);

//{sachin=Sachin 14000}

 

We will now insert a Cricketer with key dravid. In sorted order,dravid comes before sachin. So, the value with key dravid is inserted at the start of the Map.

treemap.put("dravid",

new Cricketer("Dravid", 12000)); System.out.println(treemap);

//{dravid=Dravid 12000, sachin=Sachin 14000}

 

We will now insert a Cricketer with key ponting. In sorted order, ponting fits in between dravid and sachin.

treemap.put("ponting", new Cricketer("Ponting", 11500));

System.out.println(treemap);

//{dravid=Dravid 12000, ponting=Ponting 11500, sachin=Sachin 14000}

 

treemap.put("bradman", new Cricketer("Bradman", 9996));

System.out.println(treemap);

//{bradman=Bradman 9996, dravid=Dravid 12000, ponting=Ponting 11500, sachin=Sachin

14000}

 

53.         Can you give an example of implementation of NavigableMap Interface?  TreeMap is a good example of a NavigableMap interface implementation. Note that keys in TreeMap are sorted.

 

TreeMap<Integer, Cricketer> numbersTreeMap = new TreeMap<Integer, Cricketer>(); numbersTreeMap.put(55, new Cricketer("Sachin",

14000));

numbersTreeMap.put(25, new Cricketer("Dravid", 12000));


numbersTreeMap.put(35, new Cricketer("Ponting", 12000));

numbersTreeMap.put(5,

new Cricketer("Bradman", 9996)); numbersTreeMap

.put(45, new Cricketer("Lara", 10000));

 

lowerKey method finds the highest key lower than specified key. floorKey method finds the highest key lower than or equal to specified key. Corresponding methods for finding lowest key higher than specified key are higher and ceiling. A few examples using the Map created earlier below.

//Find the highest key which is lower than 25 System.out.println(numbersTreeMap.lowerKey(25));//5

 

//Find the highest key which is lower than or equal to 25 System.out.println(numbersTreeMap.floorKey(25));//25

 

//Find the lowest key higher than 25 System.out.println(numbersTreeMap.higherKey(25));//35

 

//Find the lowest key higher than or equal to 25 System.out.println(numbersTreeMap.ceilingKey(25));//25

 

54.       What is a PriorityQueue?

PriorityQueue implements the Queue interface.

 

//Using default constructor -­ uses natural ordering of numbers

//Smaller numbers have higher priority

PriorityQueue<Integer> priorityQueue = new PriorityQueue<Integer>();

 

Adding an element into priority queue offer method priorityQueue.offer(24);    priorityQueue.offer(15);

priorityQueue.offer(9);

priorityQueue.offer(45); System.out.println(priorityQueue);//[9, 24, 15, 45]

55.       Peek method examples

//peek method get the element with highest priority. System.out.println(priorityQueue.peek());//9

//peek method does not change the queue System.out.println(priorityQueue);//[9, 24, 15, 45]

 

//poll method gets the element with highest priority. System.out.println(priorityQueue.poll());//9

//peek method removes the highest priority element from the queue. System.out.println(priorityQueue);//[24, 15, 45]

 

//This comparator gives high priority to the biggest number. Comparator reverseComparator = new Comparator<Integer>() {

public int compare(Integer paramT1, Integer paramT2) {


return paramT2 -­ paramT1;

}

 

};

 

56.       What are the static methods present in the Collections class?

·        static int binarySearch(List, key)

o   Can be used only on sorted list

·        static int binarySearch(List, key, Comparator)

·        static void reverse(List)

o   Reverse the order of elements in a List.

·        static Comparator reverseOrder();

o   Return a Comparator that sorts the reverse of the collection current sort sequence.

·        static void sort(List)

·        static void sort(List, Comparator)

 

Generics

57.       What are Generics?

Generics are used to create Generic Classes and Generic methods which can work with different Types(Classes).

58.       Why do we need Generics? Can you give an example of how Generics make a program more flexible?

Consider the class below:

 

class MyList {

private List<String> values;

 

void add(String value) { values.add(value);

}

 

void remove(String value) { values.remove(value);

}

}

 

MyList can be used to store a list of Strings only.

 

MyList myList = new MyList(); myList.add("Value 1");

myList.add("Value 2");

 

To store integers, we need to create a new class. This is problem that Generics solve. Instead of hard coding String class as the only type the class can work with, we make the class type a parameter to the    class.


59.       Example with Generics

Let`s replace String with T and create a new class. Now the MyListGeneric class can be used to create a list of Integers or a list of Strings

class MyListGeneric<T> {

private List<T> values;

 

void add(T value) { values.add(value);

}

 

void remove(T value) { values.remove(value);

}

 

T get(int index) {

return values.get(index);

}

}

 

MyListGeneric<String> myListString = new MyListGeneric<String>(); myListString.add("Value 1");

myListString.add("Value 2");

 

MyListGeneric<Integer> myListInteger = new MyListGeneric<Integer>(); myListInteger.add(1);

myListInteger.add(2);

 

 

60.       How do you declare a Generic Class?

Note the declaration of class:

 

class MyListGeneric<T>

 

Instead of T, We can use any valid identifier

 

61.       What are the restrictions in using generic type that is declared in a class declaration?

If a generic is declared as part of class declaration, it can be used any where a type can be used in a class

method (return type or argument), member variable etc. For Example: See how T is used as a parameter and return type in the class MyListGeneric.

62.       How can we restrict Generics to a subclass of particular class?

In MyListGeneric, Type T is defined as part of class declaration. Any Java Type can be used a type for this class. If we would want to restrict the types allowed for a Generic Type, we can use a Generic Restrictions. Consider the example class below: In declaration of the class, we specified a constraint "T extends Number". We can use the class MyListRestricted with any class extending (any sub class of) Number Float, Integer, Double etc.

class MyListRestricted<T extends Number> {


private List<T> values;

 

void add(T value) { values.add(value);

}

 

void remove(T value) { values.remove(value);

}

 

T get(int index) {

return values.get(index);

}

}

 

MyListRestricted<Integer> restrictedListInteger = new MyListRestricted<Integer>();

 

restrictedListInteger.add(1); restrictedListInteger.add(2);

 

String not valid substitute for constraint "T extends Number".

 

//MyListRestricted<String> restrictedStringList =

//                         new MyListRestricted<String>();//COMPILER ERROR

 

63.       How can we restrict Generics to a super class of particular class?

In MyListGeneric, Type T is defined as part of class declaration. Any Java Type can be used a type for this class. If we would want to restrict the types allowed for a Generic Type, we can use a Generic Restrictions. In declaration of the class, we specified a constraint "T super Number". We can use the class MyListRestricted with any class that is a super class of Number class.

64.       Can you give an example of a Generic Method?

A generic type can be declared as part of method declaration as well. Then the generic type can be used anywhere in the method (return type, parameter type, local or block variable type).

Consider the method below:

 

static <X extends Number> X doSomething(X number){ X result = number;

//do something with result

return result;

}

 

 

The method can now be called with any Class type extend Number.

 

Integer i = 5;

Integer k = doSomething(i);


Exception Handling

65.       Explain about Exception Handling with an example.

 

Exception Handling helps us to recover from an unexpected situations – File not found or network connection is down. The important part in exception handling is the try – catch block. Look at the example below.

 

public static void main(String[] args) {

method1();

System.out.println("Line after Exception -­ Main");

}

 

private static void method1() {

method2();

System.out.println("Line after Exception -­ Method 1");

}

 

private static void method2() {

try {

String str = null; str.toString();

System.out.println("Line after Exception -­ Method 2");

} catch (Exception e) {

// NOT PRINTING EXCEPTION TRACE BAD PRACTICE

System.out.println("Exception Handled -­ Method 2");

}

}

 

Program Output

Exception Handled - Method 2 Line after Exception - Method 1 Line after Exception - Main

 

When exception is handled in a method, the calling methods will not need worry about that exception. Since Exception Handling is added in the method method2, the exception did not propogate to method1

i.e. method1 does not know about the exception in method2.

 

Few important things to remember from this example.

·     If exception is handled, it does not propogate further.

·     In a try block, the lines after the line throwing the exception are not executed.

66.       What is the use of finally block in Exception Handling?

When an exception happens, the code after the line throwing exception is not executed. If code for things like closing a connection is present in these lines of code, it is not executed. This leads to connection and other resource leaks.

 

Code written in finally block is executed even when there is an exception.

 

Consider the example below. This is code without a finally block . We have Connection class with open and close methods. An exception happens in the main method. The connection is not closed because there is no finally block.


class Connection {

void open() {

System.out.println("Connection Opened");

}

 

void close() { System.out.println("Connection Closed");

}

}

 

public class ExceptionHandlingExample1 {

 

public static void main(String[] args) {

try {

Connection connection = new Connection(); connection.open();

 

// LOGIC

String str = null; str.toString();

 

connection.close();

} catch (Exception e) {

// NOT PRINTING EXCEPTION TRACE BAD PRACTICE

System.out.println("Exception Handled -­ Main");

}

}

}

 

Output

Connection Opened Exception Handled - Main

 

Connection that is opened is not closed. This results in a dangling (un-closed) connection.

Finally block is used when code needs to be executed irrespective of whether an exception is thrown. Let us now move connection.close(); into a finally block. Also connection declaration is moved out of the try block to make it visible in the finally block.

 

public static void main(String[] args) { Connection connection = new Connection(); connection.open();

try {

// LOGIC

String str = null; str.toString();

 

} catch (Exception e) {

// NOT PRINTING EXCEPTION TRACE -­ BAD PRACTICE

System.out.println("Exception Handled -­ Main");

} finally {

connection.close();

}

}

 

Output


Connection Opened Exception Handled - Main Connection Closed

 

Connection is closed even when exception is thrown. This is because connection.close() is called in the finally block.

 

Finally block is always executed (even when an exception is thrown). So, if we want some code to be always executed we can move it to finally block.

67.       In what kind of scenarios, a finally block is not executed?

 

Code in finally is NOT executed only in two situations.

1.      If exception is thrown in finally.

2.      If JVM Crashes in between (for example, System.exit()).

 

Is a finally block executed even when there is a return statement in the try block?

private static void method2() {

 

Connection connection = new Connection(); connection.open();

try {

// LOGIC

String str = null; str.toString(); return;

} catch (Exception e) {

// NOT PRINTING EXCEPTION TRACE -­ BAD PRACTICE

System.out.println("Exception Handled -­ Method 2");

return;

} finally {

connection.close();

}

}

 

68.       Is a try block without corresponding catch block allowed?

Yes. try without a catch is allowed. Example below. private static void method2() {

Connection connection = new Connection(); connection.open();

try {

// LOGIC

String str = null; str.toString();

} finally {

connection.close();

}

}

 

However a try block without both catch and finally is NOT allowed.


Below method would give a Compilation Error!! (End of try block)

private static void method2() {

Connection connection = new Connection(); connection.open();

try {

// LOGIC

String str = null; str.toString();

}//COMPILER ERROR!!

}

 

69.       Explain the hierarchy of Exception related classes in Java?

Throwable is the highest level of Error Handling classes.

 

Below class definitions show the pre-defined exception hierarchy in Java.

 

//Predefined Java Classes

class Error extends Throwable{}

class Exception extends Throwable{}

class RuntimeException extends Exception{}

 

Below class definitions show creation of a programmer defined exception in Java.

//Programmer defined classes

class CheckedException1 extends Exception{}

class CheckedException2 extends CheckedException1{}

 

class UnCheckedException extends RuntimeException{}

class UnCheckedException2 extends UnCheckedException{}

 

70.       What is difference between an Error and an Exception?

Error is used in situations when there is nothing a programmer can do about an error. Ex: StackOverflowError, OutOfMemoryError. Exception is used when a programmer can handle the exception.

71.       What  is  the  difference  between  a        Checked  Exception  and  an  Un-­Checked Exception?

RuntimeException and classes that extend RuntimeException are called unchecked exceptions. For Example: RuntimeException,UnCheckedException,UnCheckedException2 are unchecked or RunTime Exceptions. There are subclasses of RuntimeException (which means they are subclasses of Exception also.)

 

Other Exception Classes (which don`t fit the earlier definition). These are also called Checked Exceptions. Exception, CheckedException1,CheckedException2 are checked exceptions. They are subclasses of Exception which are not subclasses of RuntimeException.

72.       How do you throw a Checked Exception from a Method?

Consider the example below. The method addAmounts throws a new Exception. However, it gives us a compilation error because Exception is a Checked Exception.

 

All classes that are not RuntimeException or subclasses of RuntimeException but extend Exception are called CheckedExceptions. The rule for CheckedExceptions is that they should be handled or thrown. Handled means it should be completed handled - i.e. not throw out of the method. Thrown means the method should declare that it throws the exception


73.       Example without throws: Does NOT compile

class AmountAdder {

static Amount addAmounts(Amount amount1, Amount amount2) {

if (!amount1.currency.equals(amount2.currency)) {

throw  new Exception("Currencies don`t   match");//            COMPILER                             ERROR!

// Unhandled exception type Exception

}

return new Amount(amount1.currency, amount1.amount + amount2.amount);

}

}

 

74.       Example with throws definition

Let`s look at how to declare throwing an exception from a method.

 

Look at the line "static Amount addAmounts(Amount amount1, Amount amount2) throws Exception". This is how we declare that a method throws Exception.

 

class AmountAdder {

static Amount addAmounts(Amount amount1, Amount amount2) throws Exception {

if (!amount1.currency.equals(amount2.currency)) {

throw new Exception("Currencies don`t match");

}

return new Amount(amount1.currency, amount1.amount + amount2.amount);

}

}

 

75.       How do you create a Custom Exception Classes?

We can create a custom exception by extending Exception class or RuntimeException class. If we extend Exception class, it will be a checked exception class. If we extend RuntimeException class, then we create an unchecked exception class.

 

Example

class CurrenciesDoNotMatchException extends Exception{

}

 

Let`s now create some sample code to use CurrenciesDoNotMatchException. Since it is a checked exception we need do two things a. throw new CurrenciesDoNotMatchException(); b. throws CurrenciesDoNotMatchException (in method declaration).

 

class AmountAdder {

static Amount addAmounts(Amount amount1, Amount amount2)

throws CurrenciesDoNotMatchException {

if (!amount1.currency.equals(amount2.currency)) {

throw new CurrenciesDoNotMatchException();

}

return new Amount(amount1.currency, amount1.amount + amount2.amount);

}

}

 

76.       How should the Exception catch blocks be ordered ?

Specific Exception catch blocks should be before the catch block for a Generic Exception. For example, CurrenciesDoNotMatchException should be before Exception. Below code gives a compilation error.


 

public static void main(String[] args) {

try {

AmountAdder.addAmounts(new Amount("RUPEE", 5), new Amount("DOLLAR", 5));

} catch (Exception e) { // COMPILER ERROR!! System.out.println("Handled Exception");

} catch (CurrenciesDoNotMatchException e) { System.out.println("Handled CurrenciesDoNotMatchException");

}

}

 

77.       Can you explain some Exception Handling Best Practices?

Never Completely Hide Exceptions. At the least log them. printStactTrace method prints the entire stack trace when an exception occurs. If you handle an exception, it is always a good practice to log the trace.

public static void main(String[] args) {

try {

AmountAdder.addAmounts(new Amount("RUPEE", 5), new Amount("RUPEE", 5));

String string = null; string.toString();

} catch (CurrenciesDoNotMatchException e) { System.out.println("Handled CurrenciesDoNotMatchException"); e.printStackTrace();

}

}

 

Files

78.       What are the basic methods in File class?

Create a File Object

 

File file = new File("FileName.txt");

 

Check if the file exists.

 

System.out.println(file.exists());

 

If file does not exist creates it and returns true. If file exists, returns false.

 

System.out.println(file.createNewFile());

 

Getting full path of file.

 

System.out.println(file.getAbsolutePath()); System.out.println(file.isFile());//true System.out.println(file.isDirectory());//false

 

Renaming a file

 

File fileWithNewName = new File("NewFileName.txt"); file.renameTo(fileWithNewName);


//There is no method file.renameTo("NewFileName.txt");

 

79.       How do you handle directories in Java?

A File class in Java represents a file and directory.

 

File directory = new File("src/com/rithus");

 

Print full directory path

 

System.out.println(directory.getAbsolutePath()); System.out.println(directory.isDirectory());//true

 

This does not create the actual file.

 

File fileInDir = new File(directory,"NewFileInDirectory.txt");

 

Actual file is created when we invoke createNewFile method.

 

System.out.println(fileInDir.createNewFile()); //true -­ First Time

 

Print the files and directories present in the folder.

 

System.out.println(Arrays.toString(directory.list()));

 

Creating a directory

File newDirectory = new File("newfolder"); System.out.println(newDirectory.mkdir());//true -­ First Time

 

Creating a file in a new directory

File notExistingDirectory = new File("notexisting"); File newFile = new File(notExistingDirectory,"newFile");

 

//Will throw Exception if uncommented: No such file or directory

//newFile.createNewFile(); System.out.println(newDirectory.mkdir());//true -­ First Time

80.       How do you write to a file using FileWriter class?

We can write to a file using FileWriter class.

 

81.       Write a string to a file using FileWriter

//FileWriter helps to write stuff into the file FileWriter fileWriter = new FileWriter(file); fileWriter.write("How are you doing?");

//Always flush before close. Writing to file uses Buffering. fileWriter.flush();

fileWriter.close();

 

82.       FileWriter Constructors

FileWriter Constructors can accept file(File) or the path to file (String) as argument. When a writer object is created, it creates the file if it does not exist.


FileWriter fileWriter2 = new FileWriter("FileName.txt"); fileWriter2.write("How are you doing Buddy?");

//Always flush before close. Writing to file uses Buffering. fileWriter2.flush();

fileWriter2.close();

 

83.       How do you read from a file using FileReader class?

File Reader can be used to read entire content from a file at one go.

 

84.       Read from file using FileReader

FileReader fileReader = new FileReader(file);

char[] temp = new char[25];

 

//fileReader reads entire file and stores it into temp System.out.println(fileReader.read(temp));//18 -­ No of characters Read from file

 

System.out.println(Arrays.toString(temp));//output below

//[H, o, w,   , a, r, e,     , y, o, u,     , d, o, i, n, g, ?, , , , , ,] fileReader.close();//Always close anything you opened:)

85.       FileReader Constructors

FileReader constructors can accept file(File) or the path to file (String) as argument.

 

FileReader fileReader2 = new FileReader("FileName.txt"); System.out.println(fileReader2.read(temp));//24 System.out.println(Arrays.toString(temp));//output below

 

 

What is the use of BufferedWriter and BufferedReader classes in Java? BufferedWriter and BufferedReader provide better buffering in addition to basic file writing and reading operations. For example, instead of reading the entire file, we can read a file line by line. Let`s write an example to write and read from a file using FileReader and FileWriter.

BufferedWriter class helps writing to a class with better buffering than FileWriter. BufferedWriter Constructors only accept another Writer as argument.

FileWriter fileWriter3 = new FileWriter("BufferedFileName.txt"); BufferedWriter bufferedWriter = new BufferedWriter(fileWriter3); bufferedWriter.write("How are you doing Buddy?"); bufferedWriter.newLine();

bufferedWriter.write("I`m Doing Fine");

//Always flush before close. Writing to file uses Buffering. bufferedWriter.flush();

bufferedWriter.close(); fileWriter3.close();

 

 

BufferedReader helps to read the file line by line. BufferedReader Constructors only accept another Reader as argument.


FileReader fileReader3 = new FileReader("BufferedFileName.txt"); BufferedReader bufferedReader = new BufferedReader(fileReader3);

 

String line;

//readLine returns null when reading the file is completed.

while((line=bufferedReader.readLine()) != null){ System.out.println(line);

}

 

86.       What is the use of PrintWriter class?

PrintWriter provides advanced methods to write formatted text to the file. It supports printf function. PrintWriter constructors supports varied kinds of arguments – File, String (File Path) and Writer.

 

PrintWriter printWriter = new PrintWriter("PrintWriterFileName.txt");

 

 

Other than write function you can use format, printf, print, println functions to write to PrintWriter file.

 

//writes "             My Name" to the file printWriter.format("%15s", "My Name");

 

printWriter.println(); //New Line printWriter.println("Some Text");

 

//writes "Formatted Number: 4.50000" to the file printWriter.printf("Formatted Number: %5.5f", 4.5); printWriter.flush();//Always flush a writer printWriter.close();

 

 

Serialization

87.       What is Serialization?

Serialization helps us to save and retrieve the state of an object.

·     Serialization => Convert object state to some internal object representation.

·     De-Serialization => The reverse. Convert internal representation to object.

 

Two important methods

·     ObjectOutputStream.writeObject() // serialize and write to file

·     ObjectInputStream.readObject() // read from file and deserialize

How do you serialize an object using Serializable interface?

To serialize an object it should implement Serializable interface. In the example below, Rectangle class implements Serializable interface. Note that Serializable interface does not declare any methods to be implemented.

 

Below example shows how an instance of an object can be serialized. We are creating a new Rectangle object and serializing it to a file Rectangle.ser.

 

class Rectangle implements Serializable {

public Rectangle(int length, int breadth) {


this.length = length; this.breadth = breadth; area = length * breadth;

}

 

int length; int breadth; int area;

}

 

FileOutputStream fileStream = new FileOutputStream("Rectangle.ser"); ObjectOutputStream objectStream = new ObjectOutputStream(fileStream); objectStream.writeObject(new Rectangle(5, 6));

objectStream.close();

 

88.       How do you de-­serialize in Java?

Below example show how a object can be deserialized from a serialized file. A rectangle object is deserialized from the file Rectangle.ser

 

FileInputStream fileInputStream = new FileInputStream("Rectangle.ser"); ObjectInputStream objectInputStream = new ObjectInputStream(

fileInputStream);

Rectangle rectangle = (Rectangle) objectInputStream.readObject(); objectInputStream.close(); System.out.println(rectangle.length);// 5

System.out.println(rectangle.breadth);// 6

System.out.println(rectangle.area);// 30

 

What do you do if only parts of the object have to be serialized?

We mark all the properties of the object which should not be serialized as transient. Transient attributes in an object are not serialized. Area in the previous example is a calculated value. It is unnecessary to serialize and deserialize. We can calculate it when needed. In this situation, we can make the variable transient. Transient variables are not serialized. (transient int area;)

 

//Modified Rectangle class

 

class Rectangle implements Serializable {

public Rectangle(int length, int breadth) {

this.length = length; this.breadth = breadth; area = length * breadth;

}

 

int length;

int breadth;

transient int area;

}

 

 

If you run the program again, you would get following output

 

System.out.println(rectangle.length);// 5

System.out.println(rectangle.breadth);// 6

System.out.println(rectangle.area);// 0


 

Note that the value of rectangle.area is set to 0. Variable area is marked transient. So, it is not stored into the serialized file. And when de-serialization happens area value is set to default value i.e. 0.

89.       How do you serialize a hierarchy of objects?

Objects of one class might contain objects of other classes. When serializing and de-serializing, we might need to serialize and de-serialize entire object chain. All classes that need to be serialized have to implement the Serializable interface. Otherwise, an exception is thrown. Look at the class below. An object of class House contains an object of class Wall.

 

class House implements Serializable {

public House(int number) {

super();

this.number = number;

}

 

Wall wall;

int number;

}

 

class Wall{

int length; int breadth; int color;

}

 

House implements Serializable. However, Wall doesn`t implement Serializable. When we try to serialize an instance of House class, we get the following exception.

 

Output:

Exception          in            thread          "main"                         java.io.NotSerializableException: com.rithus.serialization.Wall

at java.io.ObjectOutputStream.writeObject0(Unknown Source)

at java.io.ObjectOutputStream.defaultWriteFields(Unknown Source)

 

This is because Wall is not serializable. Two solutions are possible.

1.      Make Wall transient. Wall object will not be serialized. This causes the wall object state to be lost.

2.      Make Wall implement Serializable. Wall object will also be serialized and the state of wall object along with the house will be stored.

 

class House implements Serializable {

public House(int number) {

super();

this.number = number;

}

 

transient Wall wall;

int number;

}

 

class Wall implements Serializable {

int length; int breadth; int color;

}


 

With both these programs, earlier main method would run without throwing an exception.

 

If you try de-serializing, In Example2, state of wall object is retained whereas in Example1, state of wall object is lost.

90.       Are the constructors in an object invoked when it is de-­serialized?

No. When a class is De-serialized, initialization (constructor`s, initializer`s) does not take place. The state of the object is retained as it is.

91.       Are the values of static variables stored when an object is serialized?

Static Variables are not part of the object. They are not serialized.

 

 

MultiThreading

92.       What is the need for Threads in Java?

Threads allow Java code to run in parallel. Let`s look at an example to understand what we can do with Threads.

93.       Need for Threads

We are creating a Cricket Statistics Application. Let`s say the steps involved in the application are

 

·     STEP I: Download and Store Bowling Statistics => 60 Minutes

·     STEP II: Download and Store Batting Statistics => 60 Minutes

·     STEP III: Download and Store Fielding Statistics => 15 Minutes

·     STEP IV: Merge and Analyze => 25 Minutes

 

Steps I, II and III are independent and can be run in parallel to each other. Run individually this program takes 160 minutes. We would want to run this program in lesser time. Threads can be a solution to this problem. Threads allow us to run STEP I, II and III in parallel and run Step IV when all Steps I, II and III are completed.

Below example shows the way we would write code usually – without using Threads.

 

ThreadExamples example = new ThreadExamples(); example.downloadAndStoreBattingStatistics(); example.downloadAndStoreBowlingStatistics(); example.downloadAndStoreFieldingStatistics();

 

example.mergeAndAnalyze();

 

downloadAndStoreBowlingStatistics starts only after downloadAndStoreBattingStatistics completes execution. downloadAndStoreFieldingStatistics starts only after downloadAndStoreBowlingStatistics completes execution. What if I want to run them in parallel without waiting for the others to complete?

This is where Threads come into picture. Using Multi-­Threading we can run each of the above steps in parallel and synchronize when needed. We will understand more about synchronization later.


94.       How do you create a thread?

Creating a Thread class in Java can be done in two ways. Extending Thread class and implementing Runnable interface. Let`s create the BattingStatisticsThread extending Thread class and BowlingStatisticsThread implementing Runnable interface.

95.       How do you create a thread by extending Thread class?

Thread class can be created by extending Thread class and implementing the public void run() method.

 

Look at the example below: A dummy implementation for BattingStatistics is provided which counts from 1 to 1000.

class BattingStatisticsThread extends Thread {

//run method without parameters

public void run() {

for (int i = 0; i < 1000; i++) System.out

.println("Running Batting Statistics Thread "

+ i);

}

}

 

96.       How do you create a thread by implementing Runnable interface?

Thread class can also be created by implementing Runnable interface and implementing the method declared in Runnable interface “public void run()”. Example below shows the Batting Statistics Thread implemented by implementing Runnable interface.

class BowlingStatisticsThread implements Runnable {

//run method without parameters

public void run() {

for (int i = 0; i < 1000; i++) System.out

.println("Running Bowling Statistics Thread "

+ i);

}

}

 

97.       How do you run a Thread in Java?

Running a Thread in Java is slightly different based on the approach used to create the thread.

 

98.       Thread created Extending Thread class

When using inheritance, An object of the thread needs be created and start() method on the thread needs to be called. Remember that the method that needs to be called is not run() but it is start().

BattingStatisticsThread battingThread1 = new BattingStatisticsThread(); battingThread1.start();

 

99.       Thread created implementing RunnableInterface.

Three steps involved.


·     Create an object of the BowlingStatisticsThread(class implementing Runnable).

·     Create a Thread object with the earlier object as constructor argument.

·     Call the start method on the thread.

 

BowlingStatisticsThread battingInterfaceImpl = new BowlingStatisticsThread(); Thread battingThread2 = new Thread(

battingInterfaceImpl); battingThread2.start();

 

100.    What are the different states of a Thread?

Different states that a thread can be in are defined the class State.

 

·     NEW;

·     RUNNABLE;

·     RUNNING;

·     BLOCKED/WAITING;

·     TERMINATED/DEAD;

 

Let`s consider the example that we discussed earlier.

 

Example Program

LINE 1: BattingStatisticsThread battingThread1 = new BattingStatisticsThread(); LINE 2: battingThread1.start();

 

LINE 3: BowlingStatisticsThread battingInterfaceImpl = new BowlingStatisticsThread(); LINE 4: Thread battingThread2 = new Thread(battingInterfaceImpl);

LINE 5:battingThread2.start();

 

Description

A thread is in NEW state when an object of the thread is created but the start method is not yet called. At the end of line 1, battingThread1 is in NEW state.

A thread is in RUNNABLE state when it is eligible to run, but not running yet. (A number of Threads can be in RUNNABLE state. Scheduler selects which Thread to move to RUNNING state). In the above example, sometimes the Batting Statistics thread is running and at other time, the Bowling Statistics Thread is running. When Batting Statistics thread is Running, the Bowling Statistics thread is ready to run.  It`s  just  that  the  scheduler  picked  Batting  Statistics  thread  to  run  at  that  instance  and  viceversa. When Batting Statistics thread is Running, the Bowling Statistics Thread is in Runnable state (Note that the Bowling Statistics Thread is not waiting for anything except for the Scheduler to pick it up and run it).

A thread is RUNNING state when it`s the one that is currently , what else to say, Running.

 

A thread is in BLOCKED/WAITING/SLEEPING state when it is not eligible to be run by the Scheduler. Thread is alive but is waiting for something. An example can be a Synchronized block. If Thread1 enters synchronized block, it blocks all the other threads from entering synchronized code on the same instance or class. All other threads are said to be in Blocked state.


A thread is in DEAD/TERMINATED state when it has completed its execution. Once a thread enters dead state, it cannot be made active again.

What is priority of a thread? How do you change the priority of a thread? Scheduler can be requested to allot more CPU to a thread by increasing the threads priority. Each thread      in Java is assigned a default Priority 5. This priority can be increased or decreased (Range 1 to 10).

If two threads are waiting, the scheduler picks the thread with highest priority to be run. If all threads have equal priority, the scheduler then picks one of them randomly. Design programs so that they don`t depend on priority.

101.    Thread Priority Example

Consider the thread example declared below:

 

class ThreadExample extends Thread {

public void run() {

for (int i = 0; i < 1000; i++) System.out

.println( this.getName() + " Running "

+ i);

}

}

 

Priority of thread can be changed by invoking setPriority method on the thread.

 

ThreadExample thread1 = new ThreadExample(); thread1.setPriority(8);

 

Java also provides predefined constants Thread.MAX_PRIORITY(10), Thread.MIN_PRIORITY(1), Thread.NORM_PRIORITY(5) which can be used to assign priority to a thread.

 

Synchronization

102.    What is synchronization of threads?

Since Threads run in parallel, a new problem arises. What if thread1 modifies data which is being accessed by thread2? How do we ensure that different threads don`t leave the system in an inconsistent state? This problem is usually called synchronization problem.

Let`s first look at an example where this problem can occur. Consider the code in the setAndGetSum method.

int setandGetSum(int a1, int a2, int a3) { cell1 = a1;

sleepForSomeTime(); cell2 = a2; sleepForSomeTime(); cell3 = a3; sleepForSomeTime();


return cell1 + cell2 + cell3;

}

 

If following method is running in two different threads, funny things can happen. After setting the value to each cell, there is a call for the Thread to sleep for some time. After Thread 1 sets the value of cell1, it goes to Sleep. So, Thread2 starts executing. If Thread 2 is executing “return cell1 + cell2 + cell3;”, it uses cell1 value set by Thread 1 and cell2 and cell3 values set by Thread 2. This results in the unexpected results that we see when the method is run in parallel. What is explained is one possible scenario. There are several such scenarios possible.

The way you can prevent multiple threads from executing the same method is by using the synchronized keyword on the method. If a method is marked synchronized, a different thread gets access to the method only when there is no other thread currently executing the method.

Let`s mark the method as synchronized:

 

synchronized int setandGetSum(int a1, int a2, int a3) { cell1 = a1;

sleepForSomeTime(); cell2 = a2; sleepForSomeTime(); cell3 = a3; sleepForSomeTime();

return cell1 + cell2 + cell3;

}

 

103.    Can you give an example of a synchronized block?

All code which goes into the block is synchronized on the current object.

 

void synchronizedExample2() {

synchronized (this){

//All code goes here..

}

}

 

104.    Can a static method be synchronized?

Yes. Consider the example below.

 

synchronized static int getCount(){

return count;

}

 

Static methods and block are synchronized on the class. Instance methods and blocks are synchronized on the instance of the class i.e. an object of the class. Static synchronized methods and instance synchronized methods don`t affect each other. This is because they are synchronized on two different things.

static int getCount2(){

synchronized (SynchronizedSyntaxExample.class) {

return count;


}

}

 

105.    What is the use of join method in threads?

Join method is an instance method on the Thread class. Let`s see a small example to understand what join method does.

Let`s consider the thread`s declared below: thread2, thread3, thread4

 

ThreadExample thread2 = new ThreadExample(); ThreadExample thread3 = new ThreadExample(); ThreadExample thread4 = new ThreadExample();

 

Let`s say we would want to run thread2 and thread3 in parallel but thread4 can only run when thread3 is finished. This can be achieved using join method.

Join method example

Look at the example code below:

 

thread3.start(); thread2.start();

thread3.join();//wait for thread 3 to complete System.out.println("Thread3 is completed."); thread4.start();

 

thread3.join() method call force the execution of main method to stop until thread3 completes execution. After that, thread4.start() method is invoked, putting thread4 into a Runnable State.

Overloaded Join method

Join method also has an overloaded method accepting time in milliseconds as a parameter.

 

thread4.join(2000);

In above example, main method thread would wait for 2000 ms or the end of execution of thread4, whichever is minimum.

106.    Describe a few other important methods in Threads?

Thread yield method

Yield is a static method in the Thread class. It is like a thread saying " I have enough time in the limelight. Can some other thread run next?".

A call to yield method changes the state of thread from RUNNING to RUNNABLE. However, the scheduler might pick up the same thread to run again, especially if it is the thread with highest priority.

Summary is yield method is a request from a thread to go to Runnable state. However, the scheduler can immediately put the thread back to RUNNING state.


Thread sleep method

sleep is a static method in Thread class. sleep method can throw a InterruptedException. sleep method causes the thread in execution to go to sleep for specified number of milliseconds.

107.    What is a deadlock?

Let`s consider a situation where thread1 is waiting for thread2 ( thread1 needs an object whose synchronized code is being executed by thread1) and thread2 is waiting for thread1. This situation is called a Deadlock. In a Deadlock situation, both these threads would wait for one another for ever.

108.    What are the important methods in java for inter-­thread communication?

Important methods are wait, notify and notifyAll.

 

109.    What is the use of wait method?

Below snippet shows how wait is used. wait method is defined in the Object class. This causes the thread to wait until it is notified.

synchronized(thread){ thread.start(); thread.wait();

}

 

110.    What is the use of notify method?

Below snippet shows how notify is used. notify method is defined in the Object class. This causes the object to notify other waiting threads.

 

synchronized (this) { calculateSumUptoMillion(); notify();

}

 

111.    What is the use of notifyAll method?

If more than one thread is waiting for an object, we can notify all the threads by using notifyAll method. thread.notifyAll();

112.    Can you write a synchronized program with wait and notify methods?

package com.rithus.threads;

 

class Calculator extends Thread {

long sumUptoMillion;

long sumUptoTenMillion;

 

public void run() {

synchronized (this) { calculateSumUptoMillion(); notify();

}

calculateSumUptoTenMillion();

}


 

private void calculateSumUptoMillion() {

for (int i = 0; i < 1000000; i++) { sumUptoMillion += i;

}

System.out.println("Million done");

}

 

private void calculateSumUptoTenMillion() {

for (int i = 0; i < 10000000; i++) { sumUptoTenMillion += i;

}

System.out.println("Ten Million done");

}

}

 

public class ThreadWaitAndNotify {

public static void main(String[] args) throws InterruptedException { Calculator thread = new Calculator();

synchronized(thread){ thread.start(); thread.wait();

}

System.out.println(thread.sumUptoMillion);

}

}

 

 

Output Million done 499999500000

Ten Million done

 

Search
Related Articles

Leave a Comment: