Friday, 8 January 2016

Top Interview Questions asked for Java Developer

 Q1. What are 4 different OOPS principal in java ??


    Abstraction -
           Abstraction is a design level or logical concept and doesn’t include programming approach.
            It is a process of hiding the detail-information from the end users, and exposing only the essential  features of a particular object. Data Hiding is a ability of objects to shields the variables from external access.

    Encapsulation - Encapsulation means data hiding.
           Encapsulation is a mechanism by which you restrict the access to some of the object's components, as well as binding the data and methods operating on the data by writing class.

    Inheritance - Inheritance is a process where child class acquires the properties of super class.

    Polymorphism -
        Compile time polymorphism - can be achieved by using Method overloading.
        Runtime polymorphism - Runtime polymorphism can be achieved by using Method overriding.
                                                  Runtime polymorphism is not applicable on final, due to not override.

Q2. Can overriding of hashcode() method cause any performance issues ??

Improper implementation of hashCode() can cause performance issues, because in that most of the key-value pairs will be stored on same bucket location and unnecessary time will be consumed while fetching value corresponding to key.

Q3. What are immutable classes in java? How we can create immutable classes in java?

Any change made to object of immutable class produces new object.
Example- String is Immutable class in java, Integer, Double, Long, Short, Byte etc are also.

We must follow following steps for creating immutable classes -

1) Final class - Make class final so that it cannot be inherited
2) private member variable-Making member variables private ensure fields can't be accessed outside class.
3) final member variable-Make member variables final so that once assigned their values cannot be changed
4) Constructor - Initialize all fields in constructor. assign all mutable member variable using new keyword.
5) Don't provide setter methods in class/ provide only getter methods.


 Q4. What is cloning in java ??

Cloning is done for copying the object, cloning can be done using shallow or deep copy.

Few key points about clone method -

    1) Definition of clone method -

           protected native Object clone() throws CloneNotSupportedException;

    Clone is a protected method - clone method can’t be called outside class without inheritance.
    Clone is native method, if not overridden its implementation is provided by JVM.
    It returns Object - Means explicitly cast is needed to convert it to original object.

    2) By default clone method do shallow copy.
    3) Class must implement marker interface java.lang.Cloneable. If class doesn’t implement Cloneable than   calling clone method on its object will throw CloneNotSupportedException.
    4) shallow copy- If we implement Cloneable interface, we must override clone method and call super.clone() from it, invoking super.clone() will do shallow copy.
    5) Deep copy - We need to provide custom implementation of clone method for deep copying.  When the copied object contains some other object its references are copied recursively in deep copy.


Q6. How can we ensure that all threads started from main must end in order in which they started i.e. ends with main ? 


We can use join() method to 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);

 class MyRunnable implements Runnable
{
    public void run(){
        System.out.println("in run() method");
           for(int i=0;i<5;i++){
                  System.out.println("i="+i+" ,ThreadName="+Thread.currentThread().getName());
           }         
    }
}

public class MyClass {
    public static void main(String...args) throws InterruptedException{
           System.out.println("In main() method");
           MyRunnable runnable=new MyRunnable();
           Thread thread1=new Thread(runnable);
           Thread thread2=new Thread(runnable);

           thread1.start();
           thread1.join();

           thread2.start();
           thread2.join();

           System.out.println("end main() method");
    }
}

/*OUTPUT IN SUCH MANNER

In main() method
in run() method
i=0 ,ThreadName=Thread-0
i=1 ,ThreadName=Thread-0
i=2 ,ThreadName=Thread-0
i=3 ,ThreadName=Thread-0
i=4 ,ThreadName=Thread-0
in run() method
i=0 ,ThreadName=Thread-1
i=1 ,ThreadName=Thread-1
i=2 ,ThreadName=Thread-1
i=3 ,ThreadName=Thread-1
i=4 ,ThreadName=Thread-1
end main() method

*/
If we note output, all threads ended in order in which they were called and main thread has ended last.

First, main thread was called, it started Thread1 and then we called join() method on Thread1, once Thread1 ended main thread started Thread2 and we called join() method on Thread2, once Thread2 ended main thread also ended.


Q7. What is significance of using Volatile keyword?

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.
 Volatile members are never cached in CPU by jvm, they are always read from main memory i.e. from stack where variable lives. It is possible for multiple CPU’s to exist on machine, so it is possibility that thread might cache different values in different CPU’s for same variable, so it’s important that value is not cached in CPU and always read from main memory.

 Let’s discuss a scenario where non-volatile variable is used :

int x=0;  // Let’s say we have variable x with value 0, in main memory value of x is 0 and in cache value of x is also 0.
x++;  //increment done by thread1, so now in main memory  value of x is 1 but it might happen somehow that value is not updated in cache, so value of x in cache is still 0.
Now, lets say thread2 try to read that value, as value is cached, it will read read value from cache only, so value read of x will be 0 (but actual value of x is 1), which of course is a synchronization problem.

Let’s discuss a scenario where volatile variable is used :
int x=0;  // Let’s say we have variable x with value 0, in main memory value of x is 0 and it’s not cached (as volatile variables are not cached).
x++;  //increment done by thread1, so now in main memory  value of x is 1 and it’s not cached.
Now, lets say thread2 try to read that value, as value is not cached, it will read read value from main memory, so value read of x will be 1 (and actual value of x is 1), we have solved synchronization problem.


Q8. Can transient variables be declared as final or static ?             Answer is NO

The modifier transient can be applied to field members of a class to turn off serialization on these field members. Every field marked as transient will not be serialized. You use the transient keyword to indicate to the Java virtual machine that the transient variable is not part of the persistent state of an object.
The transient modifier applies to variables only.
Java classes often hold some globally relevant value in a static class variable,because it's loaded during the class loading time.
The static member fields belong to class and not to an individual instance. The concept of serialization is concerned with the object's current state. Only data associated with a specific instance of a class is serialized, therefore static member fields  are ignored during serialization (they are not serialized automatically), because they do not belong to the serialized instance, but to the class. To serialize data stored in a static variable one must provide class-specific serialization.

Surprisingly, the java compiler does not complaint if you declare a static member field as transient. However, there is no point in declaring a static member field as transient, since transient means: "do not serialize", and static fields would not be serialized anyway.

On the other hand, an instance member field declared as final could also be transient, but if so, you would face a problem a little bit difficult to solve: As the field is transient, its state would not be serialized, it implies that, when you deserialize the object you would have to initialize the field manually, however, as it is declared final, the compiler would complaint about it.

For instance, maybe you do not want to serialize your class' logger, then you declared it this way:

private transient final Log log = LogFactory.getLog(EJBRefFactory.class);
Now, when you deserialize the class your logger will be a null object, since it was transient. Then you should initialize the logger manually after serialization or during the serialization process. But you can't, because logger is a final member as well.

There is just one exception to this rule, and it is when the transient final field member is initialized to a constant expression as those defined in the JLS 15.28. Hence, field members declared this way would hold their constant value expression even after deserializing the object. I guess that is so because the value of the final field is actually a constant expression as described by the JLS.

This example shows transient final fields that would hold their constant values even after deserializing the object:

class X implements Serializable
{
  transient static String transientStaticVar = "transientStaticVar";
  transient final String transientFinalVar = "transientFinalVar";
  transient static final String transientStaticFinalVar = "transientStaticFinalVar";
  transient String transientVar = "transientVar";
}

public class  Test {
  public static void main( String[] args ){
    try {
      ObjectOutputStream o = new ObjectOutputStream(
                      new FileOutputStream("logInfo.out"));
      X a = new X();
      System.out.println("Before Serialization ...");
      System.out.println("transientStaticVar = " + X.transientStaticVar);
      System.out.println("transientFinalVar = " + a.transientFinalVar);
      System.out.println("transientStaticFinalVar = " +
          X.transientStaticFinalVar);
      System.out.println("transientVar = " + a.transientVar);
      o.writeObject(a);
      o.close();
      X.transientStaticVar = "newTransientStaticVar";
    }
    catch(Exception e) {
      //deal with exception
    }

    try {

      ObjectInputStream in =new ObjectInputStream(
                             new FileInputStream("logInfo.out"));
      X x = (X)in.readObject();
      System.out.println("After Serialization ...");
      System.out.println("transientStaticVar = " + X.transientStaticVar);
      System.out.println("transientFinalVar = " + x.transientFinalVar);
      System.out.println("transientStaticFinalVar = " +
           X.transientStaticFinalVar);
      System.out.println("transientVar = " + x.transientVar);
    }
    catch(Exception e) {
      //deal with exception
    }

  }

}

The output results are:

Before Serialization ...
transientStaticVar = transientStaticVar
transientFinalVar = transientFinalVar
transientStaticFinalVar = transientStaticFinalVar
transientVar = transientVar
After Serialization ...
transientStaticVar = newTransientStaticVar
transientFinalVar = transientFinalVar
transientStaticFinalVar = transientStaticFinalVar
transientVar = null
If we change the way to initialize final variables, you have different variable and you can do not initialize them during the serialization process because they are final.

class X implements Serializable {
  transient static String transientStaticVar;
  transient final String transientFinalVar;
  transient static final String transientStaticFinalVar;
  transient String transientVar = "transientVar";

  static {
    transientStaticVar = "transientStaticVar"
    transientStaticFinalVar = "transientStaticFinalVar";
  }

  {
    transientFinalVar = "transientFinalVar";
  }

}

public class  Test {
  public static void main( String[] args ){
    try {
      ObjectOutputStream o = new ObjectOutputStream(
                      new FileOutputStream("logInfo.out"));
      X a = new X();
      System.out.println("Before Serialization ...");
      System.out.println("transientStaticVar = " + X.transientStaticVar);
      System.out.println("transientFinalVar = " + a.transientFinalVar);
      System.out.println("transientStaticFinalVar = " +
          X.transientStaticFinalVar);
      System.out.println("transientVar = " + a.transientVar);
      o.writeObject(a);
      o.close();
      X.transientStaticVar = "newTransientStaticVar";
    }
    catch(Exception e) {
      //deal with exception
    }

    try {

      ObjectInputStream in =new ObjectInputStream(
                             new FileInputStream("logInfo.out"));
      X x = (X)in.readObject();
      System.out.println("After Serialization ...");
      System.out.println("transientStaticVar = " + X.transientStaticVar);
      System.out.println("transientFinalVar = " + x.transientFinalVar);
      System.out.println("transientStaticFinalVar = " +
          X.transientStaticFinalVar);
      System.out.println("transientVar = " + x.transientVar);
    }
    catch(Exception e) {
      //deal with exception
    }

  }

}

The output results are:

Before Serialization ...
transientStaticVar = transientStaticVar
transientFinalVar = transientFinalVar
transientStaticFinalVar = transientStaticFinalVar
transientVar = transientVar
After Serialization ...
transientStaticVar = newTransientStaticVar
transientFinalVar = null
transientStaticFinalVar = transientStaticFinalVar
transientVar = null


Surprisingly, the java compiler does not complaint if you declare a static member field as transient or a final member field as transient in your classes. These should be compile-time errors. Because a "transient" part of an object's state is assumed to be changing within each instance,
it can not be static or final. Similarly, a "volatile" variable cannot be final (constant). This restriction matters only in the future, though, when transient and volatile are actually used by Java.



Question: Which of the following is true?
A. transient methods must be static
B. native methods violate Java's platform independence.
C. static methods cannot be protected
D. transient variables may not be final or static

Answer:
A is incorrect as the modifier transient applies to variables only.

B is correct  because native methods execute code which lies entirely outside the Java Virtual Machine, this code is compiled for a specific targeted machine and hence makes the application platform independent thereby violating Java's platform independence.

C is incorrect as there is nothing wrong in static methods being protected.

D is correct as transient variables may not be final or static.


Q9. Can static methods be overridden?          Answer is No

If a subclass defines a static method with the same signature as a static method in the superclass, the method in the subclass hides the one in the superclass. The distinction between hiding and overriding has important implications.

If a class declares a static method m, then the declaration m is said to hide any method m', where the signature of m is a subsignature of the signature of m', in the superclasses and superinterfaces of the class that would otherwise be accessible to code in the class. A compile-time error occurs if a static method hides an instance method.

In this respect, hiding of methods differs from hiding of fields, for it is permissible for a static variable to hide an instance variable. Hiding is also distinct from shadowing and obscuring.

A hidden method can be accessed by using a qualified name or by using a method invocation expression that contains the keyword super or a cast to a superclass type. In this respect, hiding of methods is similar to hiding of fields.

Let's look at an example. This example contains two classes. The first is Animal, which contains one instance method and one class method:

public class Animal {
    public static void hide() {
        System.out.format("The hide method in Animal.%n");
    }
    public void override() {
        System.out.format("The override method in Animal.%n");
    }
}
The second class, a subclass of Animal, is called Cat:

public class Cat extends Animal {
    public static void hide() {
        System.out.format("The hide method in Cat.%n");
    }
    public void override() {
        System.out.format("The override method in Cat.%n");
    }

    public static void main(String[] args) {
        Cat myCat = new Cat();
        System.out.println("Create a Cat instance ...");
        myCat.hide();
        Cat.hide();
        myCat.override();
     
        Animal myAnimal = myCat;
        System.out.println("\nCast the Cat instance to Animal...");
        myAnimal.hide();   //BAD STYLE
        Animal.hide();     //Better!
        myAnimal.override();

        Animal myAnimal1 = new Animal();
        System.out.println("\nCreate an Animal instance....");
        myAnimal1.hide();   //BAD STYLE
        Animal.hide();     //Better!
        myAnimal1.override();
    }
}
The output results are:

Create a Cat instance ...
The hide method in Cat.
The hide method in Cat.
The override method in Cat.

Cast the Cat instance to Animal...
The hide method in Animal.
The hide method in Animal.
The override method in Cat.

Create an Animal instance....
The hide method in Animal.
The hide method in Animal.
The override method in Animal.
There are three sections in this example. The first and third ones are normal. The second one is wired one, we cast the Cat type instance to it's parent Animal type. myAnimal.hide() invoke the static method defined in the Animal class.  If this method were truly overridden, we should have invoked static hide() method defined in Cat class, but we didn't.

It is considered bad style to call static methods on instances because hiding can be confusing. So it is better to use the class, for example Animal.hide or Cat.hide. The output from this program is as follows:

The hide method in Animal.
The override method in Cat.
The version of the hidden method that gets invoked is the one in the superclass, and the version of the overridden method that gets invoked is the one in the subclass.

For class methods, the runtime system invokes the method defined in the compile-time type of the reference on which the method is called. In other words, call to static methods are mapped at the compile time and depends on the declared type of the reference(Parent in this case) and not the instance the reference points at runtime. In the example, the compile-time type of myAnimal is Animal. Thus, the runtime system invokes the hide method defined in Animal.

For instance methods, the runtime system invokes the method defined in the runtime type of the reference on which the method is called. In the example, the runtime type of myAnimal is Cat. Thus, the runtime system invokes the override method defined in Cat.

An instance method cannot override a static method, and a static method cannot hide an instance method. The following table summarizes what happens when you define a method with the same signature as a method in a superclass.

How to access the static methods defined in the superclass?

A hidden method can be accessed by using a qualified name or by using a method invocation expression that contains the keyword super or a cast to a superclass type. In this respect, hiding of methods is similar to hiding of fields.

public class Cat extends Animal {
    public static void hide() {
        System.out.format("The hide method in Cat.%n");
    }
    public void override() {
        hide(); //Access Cat's hide() method
        super.hide(); //Access Animal's hide() method
        Animal.hide(); //Access Animal's hide() method
        System.out.format("The override method in Cat.%n");
    }

    public static void main(String[] args) {
           ....
    }
}


Q 10. What is parameters passed by reference or passed by value in method invocation?

In programming, there are two ways to pass arguments to a method, pass-by-value and pass-by-reference:
When you have a pass-by-value parameter, a copy of the argument is stored into the memory location allocated for the formal parameter. In this case, any changes made to the formal parameter inside the method will not affect the value of the argument back in the calling method.
When a parameter is pass-by-reference, the memory address of the argument is passed to the method, making the formal parameter an alias for the argument. This means that changes made to the formal parameter inside the method will be reflected in the value of the argument when control is returned to the calling function.

Technically, all parameters in Java are pass-by-value.

All primitives are pass-by-value, period. When a primitive value is passed into a method, a copy of the primitive is made. The copy is what is actually manipulated in the method. So, the value of the copy can be changed within the method, but the original value remains unchanged.

For example:

public class TestPassPrimitive {
  static void doSomething(int m) {
    m = m + 2;
    System.out.println("The new value is " + m + ".");
  }
  public static void main(String[] args) {
    int m = 5;
    System.out.println("Before doSomething, m is " + m + ".");
    doSomething(m);
    System.out.println("After doSomething, m is " + m + ".");
  }
}

The output result is

Before doSomething, m is 5.
The new value is 7.
After doSomething, m is 5.


Objects, however, work a bit differently. When you pass a Java object or array as a parameter, an object reference or array reference is passed into a method. The method can manipulate the attributes of the object that is referenced by the reference (formal parameter).

This reference is passed-by-value. What does this mean exactly?

Any direct changes made to the reference (formal parameter) inside the method will be reflected in the value of the object back in the calling method;

If you were to reassigns a new instantiation of an object or array to the reference (formal parameter) within the method, the reassignment only affects the copy reference (formal parameter), not the original reference passed by the caller. After that, any direct changes made to the reference (formal parameter) inside the method will be reflected the new reassigned object or array.

For example:

class TestReferenceParameter{
  public static void main (String args[]) {
    String s1 = "one";
    String s2 = doSomething(s1);
    System.out.println(s1 + " " + s2);
  }


  static String doSomething(String s1) {
    s1 = s1 + " two";
    System.out.println(s1 + " ");
    return "three";
  }
}
The output result is

one two
one three


Q11.What is the role for a ClassLoader in Java?

A Java program is made up of a number of custom classes (written by programmers like us) and core classes (which come pre-packaged with Java). When a program is executed, JVM needs to load the content of all the needed class. JVM uses a ClassLoader to find the classes.

Three Java Class Loaders are shown here


1)    System Class Loader - Loads all classes from CLASSPATH
2)    Extension Class Loader - Loads all classes from extension directory
3)    Bootstrap Class Loader - Loads all the Java core files

When JVM needs to find a class, it starts with System Class Loader. If it is not found, it checks with Extension Class Loader. If it not found, it goes to the Bootstrap Class Loader. If a class is still not found, a ClassNotFoundException is thrown.

No comments:

Post a Comment

JSP interview questions and answers

Q1. What is JSP and why do we need it? JSP stands for JavaServer Pages. JSP is java server side technology to create dynamic web pages. J...