Quick Expense Manger. Your free expense manager. Lots of features. The application is also ad free.

4 Advanced Java Interview Questions

Posted on May 26, 2018
advanced-java-interview-questions

In this post I will explain 4 advanced java interview questions and answers which are often asked in interviews.


1) What is immutable? Create a custom immutable class


An immutable object in Java is an object whose contents cannot be changed after it is created. Java has some predefined immutable class like Integer, String etc.

We will now create a custom immutable class Student with properties name and rollNo.

class Student{
private String name;
private int rollNo;
}

Generally to set the properties we have setter methods as below.

public void setName(String name){
this.name = name;
}

public void setRollNo(int rollNo){
this.rollNo = rollNo;
}

But since the properties of the object cannot be altered, after the object is created, we will not have any setter methods for the properties. So, to initialize the properties we will use the constructor and to access the properties we will use the getter methods.

class Student{

private String name;
private int rollNo;

public Student(String name,int rollNo){
this.name = name;
this.rollNo = rollNo;
}

public String getName(){
return name;
}

public int getRollNo(){
return rollNo;
}
}


So are we done ? Has the Student class become immutable. At first glance it looks like that we are done. But there are many other details that we need to take care. For example let's look at the below code.


class HackedStudent extends Student{
public String getName(){
this.name = null;
return this.name;
}

public static void main(String [] args){
Student student = new HackedStudent("Rahul",3);
}
}


We can see that HackedStudent is also a Student as it extends Student. But we can see that we can alter the property "name" after the object is created. So, to prevent this we need to make the class Student final. Then any other class won't be able to extend the class Student.


final class Student{

private String name;
private int rollNo;

public Student(String name,int rollNo){
this.name = name;
this.rollNo = rollNo;
}

public String getName(){
return name;
}

public int getRollNo(){
return rollNo;
}
}


But we are still not done. The class Student will work fine as an immutable class now. But let's add one more property to the class say - dateOfRegistration and it's a Date object.

We cannot just set the date object in the constructor or return this object in the getter method. Because if someone later changes this dateOfRegistration object, the immutability of the Student object will be violated.

So, we have to set/return the copy of the dateOfRegistration object in the constructor or in the getter method, instead of setting/returning the original object as shown below.


final class Student{

private String name;
private int rollNo;
private Date dateOfRegistration;

public Student(String name,int rollNo,Date dateOfRegistration){
this.name = name;
this.rollNo = rollNo;
this.dateOfRegistration = new Date(dateOfRegistration.getTime());
}

public String getName(){
return name;
}

public int getRollNo(){
return rollNo;
}

public Date getDateOfRegistration(){
Date copy = new Date(dateOfRegistration.getTime());
return copy;
}

}


Now, the Student class is immutable.


2) What is Singleton in Java ? Write your own Singleton class


A Singleton class in Java is class for which only a single object can be created. Let's see the below code

class MySingleton{
private static volatile MySingleton object;

public static MySingleton getInstance(){

//First check
if(object == null){
synchronized(MySingleton.class){
//Second check
if(object == null){
object = new MySingleton();
}
}
}

return object;
}
}


First we should have some knowledge of multi threading. We have to be careful that when multiple threads are trying to get/create the object of the Singleton class, only a single object should be created.

First we have to make sure that any thread should not put the Singleton object in the local cache of the thread.

Why ??

Because say Thread-1 is executing the line after the comment "First check" and it finds the object is NULL, it has then put this info in its local cache. At that time Thread-1 gets suspended and JVM starts executing Thread-2.

Let's say Thread-2 is also executing the line after the comment "First check" and it finds the object is NULL as well. It also puts this info in it's local cache. Now Thread-2 gets suspended and JVM loads the Thread-1 again.

Thread-1 loads the info from cache and finds that the object value is null and creates the instance of the class. The JVM now suspends Thread-1 and loads Thread-2.

Thread-2 also checks it's cache and finds that the object value is NULL and it also creates another instance. So, now Singleton is violated.

To take care of this, we have made the object volatile. This will prevent any thread to locally cache the object. And all the threads will get the object only from main memory.


3) What is Hash map ? Write your own custom hash map. Will it work if we don't override hashCode() in the Key class ?


Check my post on Custom Hash Map implementation. Now coming to the second part "Will it work if we don't override hashCode() method in the Key class" ?

Answer - No. First we have to understand how the hashCode is created. Let's create an object of the Song class as explained in the Custom hash map implementation class.

Song songObject = new Song("Dummy song title");

If we wouldn't have override the hashCode() method, then it will use the default implementation as defined in the Object class and will use the bit pattern in the object reference (of songObject) to calculate the hashCode value.

Let's assume we have put this Song object in the hash map. Here is the problem. Suppose we create one more Song object as below.

Song sonObject2 = new Song("Dummy song title");

Now if we lookup the songObject2 in hash map, it will not be able to find this object. But logically it should be able to find. Because from user's perspective songObject and songObject2 are equal.

The reason it fails to find this object in hash map is it calculates the hash code using the bit pattern of the object reference (songObject2) and the calculated hash code is different from songObject as songObject and songObject2 has different bit patterns in their representation.

But sometimes the hashCode may become same as well depending upon the bit patterns but its not always the case.


4) Implement the order by facility of SQL in Java


Let's see what is "order by" in SQL. Let's take an example of a table "Person" with two columns "Name" and "Age" and let's assume we have 3 following records inserted into the table.

a) Aman, 45

b) Akash, 45

c) Bikash, 30

Now let's look at the following query

select * from Person order by age

Here is the result of the above query

a) Bikash, 30

b) Aman, 45

c) Akash, 45

Now let's look at the below query

select * from Person order by age,name

Here is the result of the above query

a) Bikash, 30

b) Akash, 45

c) Aman, 45

In this case first it will arrange the records by age. But if two ages are equal than it will arrange them in ascending order of name.

So, in the order by clause there can be many such fields and depending upon the order of the fields the results may vary. So, in the run time we have to take these fields as input and display the results accordingly.

Many candidates design the solution as below.

class Person implements Comparable<Person>{

public in compareTo(Person p){
for(String field : fields){
if(field.equals("name"){
int val = name.compareTo(p.name);
if(val!=0)
return val;
}
if(field.equals("age"){
int val = name.compareTo(p.name);
if(val!=0)
return val;
}
}
}
}


The above code is works fine. But there are some design problems.

a) There are hard coding of the field names.

b) If we add more columns into the table, we have to change this code as well to incorporate the new changes. So, in this case we have to modify existing codes for any new changes and this is against good design principle.

Instead we can design this problem in more object oriented way as shown below.

class Person{
private String name;
private int age;
public Person(String name,int age){
this.name = name;
this.age = age;
}

public String getName(){
return this.name;
}

public int getAge(){
return this.age;
}
}
public class NameComparator implements Comparator<Person>{
public int compare(Person p1, Person p2){
return p1.getName().compareTo(p2.getName());
}
}
public class AgeComparator implements Comparator<Person>{
public int compare(Person p1, Person p2){
return p1.getAge() - p2.getAge();
}
}
public class AllPersonComparators implements Comparator<Person>{

Map<String,Comparator> allPersonComparators;
String [] fields;

public AllPersonComparators() {
allPersonComparators = new HashMap<>();
}

public void setFields(String [] fields){
this.fields = fields;
}

public void addNewComparator(String field,Comparator<Person> comparator){
allPersonComparators.put(field,comparator);
}

public void deleteComparator(String field){
allPersonComparators.remove(field);
}

@Override
public int compare(Person p1, Person p2) {
for(String field : fields){
Comparator<Person> comparator = allPersonComparators.get(field);
if(comparator != null && comparator.compare(p1,p2)!=0){
return comparator.compare(p1,p2);
}
}
return 0;
}
}

public class AllPersonComparatorsTest {

AllPersonComparators unit;

@Before
public void setUp() throws Exception {
unit = new AllPersonComparators();
}

@Test
public void test_all_person_comparators(){
Comparator<Person> ageComparator = new AgeComparator();
Comparator<Person> nameComparator = new NameComparator();

unit.addNewComparator("age",ageComparator);
unit.addNewComparator("name",nameComparator);
unit.setFields(new String[]{"age","name"});

List<Person> personList = new ArrayList<>();
personList.add(new Person("Amit",25));
personList.add(new Person("Arun",25));
personList.add(new Person("Kamal",30));

Collections.sort(personList,unit);
Assert.assertTrue(personList.get(0).getName().equals("Amit"));
}
}


So, in this case if we add a column to the table, we just need to write a new Comparator and add it in the AllComparators by calling the addNewComparator() method. Or if we delete a column, we just need to remove the comparator from the AllComparators.

So, in this case we don't need to touch any existing codes and there is no hard coding of the fields.

Sharing is Caring!

Quick Expense Manger. Your free expense manager. Lots of features. The application is also ad free.

GET FREE UPDATES


RECOMMENDED POSTS FOR YOU


profile image

Kaushik Baruah


ABOUT

My name is Kaushik Baruah and I am the chief blogger on this Blog and here I like to share my experience as software engineer and research engineer with my online readers. I will try to focus on career planning, latest emerging technologies and tutorials on various computer science subjects. You can follow me on Twitter, Facebook and Google+

GET FREE UPDATES

POPULAR POSTS

Copyright © 2016
About Us

My name is Kaushik Baruah and I am the chief blogger on this Blog and here I like to share my experience as software engineer and research engineer with my online readers. I will try to focus on career planning, latest emerging technologies and tutorials on various computer science subjects.

Get Free Updates