Clouds
Home

Core Java

Java Fundamentals 1

Java Fundamentals 2

Java Fundamentals 3

Java Swing

Java Applet

Java Memory & Performance

Core Java Fundamentals Interview Questions


Explain types of references in Java? java.lang.ref package can be used to declare soft, weak and phantom references.

  • Garbage Collector wonít remove a strong reference.
  • A soft reference will only get removed if memory is low. So it is useful for implementing caches while avoiding memory leaks.
  • A weak reference will get removed on the next garbage collection cycle. Can be used for implementing canonical maps. The java.util.WeakHashMap implements a HashMap with keys held by weak references.
  • A phantom reference will be finalized but the memory will not be reclaimed. Can be useful when you want to be notified that an object is about to be collected.

Discuss the Java error handling mechanism? What is the difference between Runtime (unchecked) exceptions and checked exceptions? What is the implication of catching all the exceptions with the type "Exception"?

Errors: When a dynamic linking failure or some other "hard" failure in the virtual machine occurs, the virtual machine throws an Error. Typical Java programs should not catch Errors. In addition, itís unlikely that typical Java programs will ever throw Errors either.

Exceptions: Most programs throw and catch objects that derive from the Exception class. Exceptions indicate that a problem occurred but that the problem is not a serious JVM problem. An Exception class has many subclasses. These descendants indicate various types of exceptions that can occur. For example, NegativeArraySizeException indicates that a program attempted to create an array with a negative size. One exception subclass has special meaning in the Java language: RuntimeException. All the exceptions except RuntimeException are compiler checked exceptions. If a method is capable of throwing a checked exception it must declare it in its method header or handle it in a try/catch block. Failure to do so raises a compiler error. So checked exceptions can, at compile time, greatly reduce the occurrence of unhandled exceptions surfacing at runtime in a given application at the expense of requiring large throws declarations and encouraging use of poorlyconstructed try/catch blocks. Checked exceptions are present in other languages like C++, C#, and Python.

Runtime Exceptions (unchecked exception) A RuntimeException class represents exceptions that occur within the Java virtual machine (during runtime). An example of a runtime exception is NullPointerException. The cost of checking for the runtime exception often outweighs the benefit of catching it. Attempting to catch or specify all of them all the time would make your code unreadable and unmaintainable. The compiler allows runtime exceptions to go uncaught and unspecified. If you like, you can catch these exceptions just like other exceptions. However, you do not have to declare it in your "throws" clause or catch it in your catch clause. In addition, you can create your own RuntimeException subclasses and this approach is probably preferred at times because checked exceptions can complicate method signatures and can be difficult to follow.

Why is it not advisable to catch type "Exception"?

Exception handling in Java is polymorphic in nature. For example if you catch type Exception in your code then it can catch or throw its descendent types like IOException as well. So if you catch the type Exception before the type IOException then the type Exception block will catch the entire exceptions and type IOException block is never reached. In order to catch the type IOException and handle it differently to type Exception, IOException should be caught first (remember that you canít have a bigger basket above a smaller basket).

Why should you throw an exception early?

The exception stack trace helps you pinpoint where an exception occurred by showing you the exact sequence of method calls that lead to the exception. By throwing your exception early, the exception becomes more accurate and more specific. Avoid suppressing or ignoring exceptions. Also avoid using exceptions just to get a flow control.
Instead of:
// assume this line throws an exception because filename == null. InputStream in = new FileInputStream(fileName); Use the following code because you get a more accurate stack trace:
if(filename == null) {
    throw new IllegalArgumentException("file name is null");
}
InputStream in = new FileInputStream(fileName);

Why should you catch a checked exception late in a catch {} block?

You should not try to catch the exception before your program can handle it in an appropriate manner. The natural tendency when a compiler complains about a checked exception is to catch it so that the compiler stops reporting errors. It is a bad practice to sweep the exceptions under the carpet by catching it and not doing anything with it. The best practice is to catch the exception at the appropriate layer (e.g. an exception thrown at an integration layer can be caught at a presentation layer in a catch {} block), where your program can either meaningfully recover from the exception and continue to execute or log the exception only once in detail, so that user can identify the cause of the exception.

When should you use a checked exception and when should you use an unchecked exception?

Due to heavy use of checked exceptions and minimal use of unchecked exceptions, there has been a hot debate in the Java community regarding true value of checked exceptions. Use checked exceptions when the client code can take some useful recovery action based on information in exception. Use unchecked exception when client code cannot do anything. For example Convert your SQLException into another checked exception if the client code can recover from it. Convert your SQLException into an unchecked (i.e. RuntimeException) exception, if the client code can not recover from it.

What is the difference between processes and threads?

A process is an execution of a program but a thread is a single execution sequence within the process. A process can contain multiple threads. A thread is sometimes called a lightweight process. A JVM runs in a single process and threads in a JVM share the heap belonging to that process. That is why several threads may access the same object. Threads share the heap and have their own stack space. This is how one threadís invocation of a method and its local variables are kept thread safe from other threads. But the heap is not thread-safe and must be synchronized for thread safety.

Explain different ways of creating a thread?

Threads can be used by either :
  • Extending the Thread class
  • Implementing the Runnable interface.
class Counter extends Thread {
    //method where the thread execution will start
    public void run(){
      //logic to execute in a thread
    }
    //letís see how to start the threads
    public static void main(String[] args){
      Thread t1 = new Counter();
      Thread t2 = new Counter();
      t1.start(); //start the first thread. This calls the run() method.
      t2.start(); //this starts the 2nd thread. This calls the run() method.
    }
}
class Counter extends Base implements Runnable {
    //method where the thread execution will start
    public void run(){
      //logic to execute in a thread
    }
    //let us see how to start the threads public static void main(String[] args){
      Thread t1 = new Thread(new Counter());
      Thread t2 = new Thread(new Counter());
      t1.start(); //start the first thread. This calls the run() method.
      t2.start(); //this starts the 2nd thread. This calls the run() method.
    }
}

Which one would you prefer and why?

The Runnable interface is preferred, as it does not require your object to inherit a thread because when you need multiple inheritance, only interfaces can help you. In the above example we had to extend the Base class so implementing Runnable interface is an obvious choice. Also note how the threads are started in each of the different cases as shown in the code sample. In an OO approach you should only extend a class when you want to make it different from itís superclass, and change itís behavior. By implementing a Runnable interface instead of extending the Thread class, you are telling to the user that the class Counter that an object of type Counter will run as a thread.

Briefly explain high-level thread states?

The state chart diagram below describes the thread states.
  • Runnable: waiting for its turn to be picked for execution by the thread scheduler based on thread priorities.
  • Running: The processor is actively executing the thread code. It runs until it becomes blocked, or voluntarily gives up its turn with this static method Thread.yield(). Because of context switching overhead, yield() should not be used very frequently.
  • Waiting: A thread is in a blocked state while it waits for some external processing such as file I/O to finish.
  • Sleeping: Java threads are forcibly put to sleep (suspended) with this overloaded method: Thread.sleep(milliseconds), Thread.sleep(milliseconds, nanoseconds);
  • Blocked on I/O: Will move to runnable after I/O condition like reading bytes of data etc changes.
  • Blocked on synchronization: Will move to Runnable when a lock is acquired.
  • Dead: The thread is finished working.

What is the difference between yield and sleeping? What is the difference between the methods sleep() and wait()?

When a task invokes yield(), it changes from running state to runnable state. When a task invokes sleep(), it changes from running state to waiting/sleeping state. The method wait(1000), causes the current thread to sleep up to one second. A thread could sleep less than 1 second if it receives the notify() or notifyAll() method call. Refer Q48 in Java section on thread communication. The call to sleep(1000) causes the current thread to sleep for exactly 1 second.

How does thread synchronization occurs inside a monitor? What levels of synchronization can you apply? What is the difference between synchronized method and synchronized block?

In Java programming, each object has a lock. A thread can acquire the lock for an object by using the synchronized keyword. The synchronized keyword can be applied in method level (coarse grained lock) can affect performance adversely) or block level of code (fine grained lock). Often using a lock on a method level is too coarse. Why lock up a piece of code that does not access any shared resources by locking up an entire method. Since each object has a lock, dummy objects can be created to implement block level synchronization.The block level is more efficient because it does not lock the whole method.
The JVM uses locks in conjunction with monitors. A monitor is basically a guardian who watches over a sequence of synchronized code and making sure only one thread at a time executes a synchronized piece of code. Each monitor is associated with an object reference. When a thread arrives at the first instruction in a block of code it must obtain a lock on the referenced object. The thread is not allowed to execute the code until it obtains the lock. Once it has obtained the lock, the thread enters the block of protected code. When the thread leaves the block, no matter how it leaves the block, it releases the lock on the associated object.

Why synchronization is important?

Without synchronization, it is possible for one thread to modify a shared object while another thread is in the process of using or updating that objectís value. This often causes dirty data and leads to significant errors. The disadvantage of synchronization is that it can cause deadlocks when two threads are waiting on each other to do something. Also synchronized code has the overhead of acquiring lock, which can adversely affect the performance.

What is a ThreadLocal class?

ThreadLocal is a handy class for simplifying development of thread-safe concurrent programs by making the object stored in this class not sharable between threads. ThreadLocal class encapsulates non-thread-safe classes to be safely used in a multi-threaded environment and also allows you to create per-thread-singleton.

What is a daemon thread?

Daemon threads are sometimes called "service" or "background" threads. These are threads that normally run at a low priority and provide a basic service to a program when activity on a machine is reduced. An example of a daemon thread that is continuously running is the garbage collector thread. The JVM exits whenever all nondaemon threads have completed, which means that all daemon threads are automatically stopped. To make a thread as a daemon thread in Java -> myThread.setDaemon(true);

How can threads communicate with each other? How would you implement a producer (one thread) and a consumer (another thread) passing data (via stack)?

The wait(), notify(), and notifyAll() methods are used to provide an efficient way for threads to communicate with each other. This communication solves the Ďconsumer-producer problemí. This problem occurs when the producer thread is completing work that the other thread (consumer thread) will use.
Example: If you imagine an application in which one thread (the producer) writes data to a file while a second thread (the consumer) reads data from the same file. In this example the concurrent threads share the same resource file. Because these threads share the common resource file they should be synchronized. Also these two threads should communicate with each other because the consumer thread, which reads the file, should wait until the producer thread, which writes data to the file and notifies the consumer thread that it has completed its writing operation.

Explain threads blocking on I/O?

Occasionally threads have to block on conditions other than object locks. I/O is the best example of this. Threads block on I/O (i.e. enters the waiting state) so that other threads may execute while the I/O operation is performed. When threads are blocked (say due to time consuming reads or writes) on an I/O call inside an object's synchronized method and also if the other methods of the object are also synchronized then the object is essentially frozen while the thread is blocked. Be sure to not synchronize code that makes blocking calls, or make sure that a non-synchronized method exists on an object with synchronized blocking code. Although this technique requires some care to ensure that the resulting code is still thread safe, it allows objects to be responsive to other threads when a thread holding its locks is blocked.

What is a singleton pattern? How do you code it in Java?

A singleton is a class that can be instantiated only one time in a JVM per class loader. Repeated calls always return the same instance. Ensures that a class has only one instance, and provide a global point of access. It can be an issue if singleton class gets loaded by multiple class loaders or JVMs. public class OnlyOne {
    private static OnlyOne one = new OnlyOne();
    // private constructor. This class cannot be instantiated from outside and
    // prevents subclassing.
    private OnlyOne(){}
    public static OnlyOne getInstance() {
      return one;
    }
}

To use it:
//No matter how many times you call, you get the same instance of the object.
OnlyOne myOne = OnlyOne.getInstance();
Note: The constructor must be explicitly declared and should have the private access modifier, so that it cannot be instantiated from out side the class. The only way to instantiate an instance of class OnlyOne is through the getInstance() method with a public access modifier.

When to use: Use it when only a single instance of an object is required in memory for a single point of access. For example the following situations require a single point of access, which gets invoked from various parts of the code.

Accessing application specific properties through a singleton object, which reads them for the first time from a properties file and subsequent accesses are returned from in-memory objects. Also there could be another piece of code, which periodically synchronizes the in-memory properties when the values get modified in the underlying properties file. This piece of code accesses the in-memory objects through the singleton object (i.e. global point of access).
Accessing in-memory object cache or object pool, or non-memory based resource pools like sockets, connections etc through a singleton object (i.e. global point of access).

What is the difference between a singleton class and a static class?

Static class is one approach to make a class singleton by declaring all the methods as static so that you canít create any instance of that class and can call the static methods directly.

What is a factory pattern?

A Factory method pattern (aka Factory pattern) is a creational pattern. The creational patterns abstract the object instantiation process by hiding how the objects are created and make the system independent of the object creation process. An Abstract factory pattern is one level of abstraction higher than a factory method pattern, which means it returns the factory classes.

Why use factory pattern or abstract factory pattern?

Factory pattern returns an instance of several (product hierarchy) subclasses (like Circle, Square etc), but the calling code is unaware of the actual implementation class. The calling code invokes the method on the interface for example Shape and using polymorphism the correct draw() method gets invoked [Refer Q10 in Java section for polymorphism]. So, as you can see, the factory pattern reduces the coupling or the dependencies between the calling code and called objects like Circle, Square etc. This is a very powerful and common feature in many frameworks. You do not have to create a new Circle or a new Square on each invocation as shown in the sample code, which is for the purpose of illustration and simplicity. In future, to conserve memory you can decide to cache objects or reuse objects in your factory with no changes required to your calling code. You can also load objects in your factory based on attribute(s) read from an external properties file or some other condition. Another benefit going for the factory is that unlike calling constructors directly, factory patterns have more meaningful names like getShape(), getInstance() etc, which may make calling code more clear.

Can we use the singleton pattern within our factory pattern code?

Yes. Another important aspect to consider when writing your factory class is that, it does not make sense to create a new factory object for each invocation as it is shown in the sample code, which is just fine for the illustration purpose.
ShapeFactory factory = new SimpleShapeFactory();
To overcome this, you can incorporate the singleton design pattern into your factory pattern code. The singleton design pattern will create only a single instance of your SimpleShapeFactory class. Since an abstract factory pattern is unlike factory pattern, where you need to have an instance for each of the two factories (i.e. SimpleShapeFactory and ComplexShapeFactory) returned, you can still incorporate the singleton pattern as an access point and have an instance of a HashMap, store your instances of both factories. Now your calling method uses a static method to get the same instance of your factory, hence conserving memory and promoting object reuse:
ShapeFactory factory = ShapeFactory. getFactoryInstance();//returns a singleton
factory.getShape();

What is a socket? How do you facilitate inter process communication in Java?

A socket is a communication channel, which facilitates inter-process communication (For example communicating between two JVMs, which may or may not be running on two different physical machines). A socket is an endpoint for communication. There are two kinds of sockets, depending on whether one wishes to use a connectionless or a connection-oriented protocol. The connectionless communication protocol of the Internet is called UDP. The connection-oriented communication protocol of the Internet is called TCP. UDP sockets are also called datagram sockets. Each socket is uniquely identified on the entire Internet with two numbers. The first number is a 32-bit (IPV4 or 128-bit is IPV6) integer called the Internet Address (or IP address). The second number is a 16-bit integer called the port of the socket. The IP address is the location of the machine, which you are trying to connect to and the port number is the port on which the server you are trying to connect is running. The port numbers 0 to 1023 are reserved for standard services such as e-mail, FTP, HTTP etc.
The lifetime of the socket is made of 3 phases: Open Socket -> Read and Write to Socket -> Close Socket
To make a socket connection you need to know two things: An IP address and port on which to listen/connect. In Java you can use the Socket (client side) and ServerSocket (Server side) classes.

Explain some of the new features in J2SE 5.0, which improves ease of development?

The J2SE 5.0 release is focused along the key areas of ease of development, scalability, performance, quality, etc. The new features include generics, metadata (aka annotations), autoboxing and auto-unboxing of primitive types, enhanced for loop, enumerated type, static import, C style formatted output, formatted input, varargs, etc. package sample;
//static import
import static sample.SampleStaticValues.NUM_ZERO;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class CombinedNewFeatures {
    enum OddEven {odd,even} //use of enum keyword. An enum is a special classs.
    public static void main(String[] args) {
      //read from keyboard using the java.util.Scanner
      Scanner keyboard = new Scanner(System.in);
      System.out.println("Enter your first number?");
      int i1 = keyboard.nextInt();
      System.out.println("Enter your second number?");
      int i2 = keyboard.nextInt();
      //using generics for type safety
      List numList = new ArrayList();
      //using auto-boxing to convert primitive int i1,i2 to wrapper Integer object.
      numList.add(i1);
      numList.add(i2);
      //numList.add("just to prove type safety");//won't compile! Requires an Integer to be added
      //":" should be read as "foreach". So should read as, foreach "num" value in numList.
      for (Integer num : numList) {
        //using auto-unboxing feature to convert wrapper Integer object "num" to primitive.
        if(num >= 9){
          // C style printf. System.out.printf(String arg0, Object ...arg1).
          // this feature is possible due to var-args feature.
          System.out.printf("num is: %1s, list size: %2s \n", num, numList.size());
          //"%" symbol means we are using the format specifier, "1" means first arg
          . // Refer java.util.Formatter class API for the format specification details.
        }
        //need not do SampleStaticValues.NUM_ZERO due to static import feature
        if(num % 2 == NUM_ZERO){
          System.out.println("The num " + num + " is: " + OddEven.even);
        }
        else {
        System.out.println("The num " + num + " is: " + OddEven.odd);
        }
      }
      CombinedNewFeatures cnf = new CombinedNewFeatures();
      //invoking methods using varargs
      cnf.addNumbers(i1);
      cnf.addNumbers(i1,i2);
      cnf.addNumbers(i1,i2,5);
    }
    //method using varargs
    public void addNumbers(Object ...args){
      int sum = 0;
      for (Object object : args) {
        sum += (Integer)object;
      }
      System.out.println("sum is " + sum);
    }
    @SuppressWarnings("deprecation") //metatag (annotation)
    public static void end(){
      Thread.currentThread().stop(); //stop() is a deprecated method
    }
}

package sample;
public class SampleStaticValues {
    public static int NUM_ZERO = 0;
    public static int NUM_ONE = 0;
}

package sample;
public class ExtendedCombinedNewFeatures extends CombinedNewFeatures {
    @Override //metatag. If you spell the methodName incorrectly, you will get a compile error.
    public void addNumbers(Object ...args) {
      //overrides baseclass methods
    }
    @Override //metatag
    public void addValues(Object ...args) { //compile error! must override a superclass method
      //
    }
}

Scanner

API provide a more robust mechanism for reading in data types rather than simply parsing strings from buffered System.in calls. Prior to Scanner feature was introduced, to read from standard input it would be necessary to write exception handling code and wrap an InputStreamReader and a BufferedReader around System.in Scanner class throws an unchecked exception InputMismatchException, which you could optionally catch. Scanner API simplifies your code as follows:

Scanner keyboard = new Scanner(System.in); //no more wrapping with InputStreamReader and
//BufferedReader around System.in
System.out.println("Enter your first number?");
int i1 = keyboard.nextInt(); //no more parsing strings e.g. new Integer("5").intValue();
System.out.println("Enter your second number?");
int i2 = keyboard.nextInt(); //no more parsing strings e.g. new Integer(str).intValue();


Generics

It allows you to pass types as arguments to classes just like values are passed to methods as parameters. Generics are mainly intended for Java Collections API. The J2SE 5.0 compiler will check the type for you. So, the error detection has been moved to compile time as opposed to runtime and ClassCastException is not likely to be thrown. It is used in a typsafe manner and you do not have to cast when taking values out of the list.

List<Integer> numList = new ArrayList<Integer>(); //used in a typesafe way.
//numList.add("just to prove type safety"); //won't compile! An Integer value is required.
//Error detection has been moved to compile time as opposed to Runtime.
for (Integer num : numList) { //you do not have to cast when you take values out of the list.
}


Auto boxing/unboxing

It makes a programmerís life easier by not having to write manual code for conversion between primitive types such as int, float etc and wrapper types Integer, Float etc. The J2SE 5.0 will automatically box and unbox this for you. So this is a convenience feature and is not a performance booster.

//using auto-boxing to convert primitive int i1,i2 to wrapper Integer object.
numList.add(i1); // no more code like -> numList.add(new Integer(i1)); autoboxed for you
numList.add(i2); // no more code like -> numList.add(new Integer(i2)); autoboxed for you
for (Integer num : numList) {
//using auto-unboxing feature to convert wrapper Integer object "num" to primitive.
if(num >= 9){ // no more code like if(num.intValue() >= 9) unboxed for you
}


printf method (C style) takes the arguments of a format string and varargs format specifiers. The varargs feature allows you to have as many format specifiers as you want. Refer java.util.Formatter API for format details. The printf() feature would not be possible if not for varargs feature, which will be discussed next.

// System.out.printf(String arg0, Object ...arg1).this feature is possible due to var-args feature.
System.out.printf("num is: %1s, list size: %2s \n", num, numList.size());//format specifiers in bold
//"%" symbol means we are using the format specifier, "1" means first arg.
//Refer java.util.Formatter class API for the format specification details.


Varargs

It enables the compiler to assemble the array for you based on the argument list you pass to a method. The three periods next to the parameter type (e.g. public void myMethod(Object : args)) denotes varargs. The type must be Object and it must be the last argument or the only argument to the method. You can also pass primitive values due to the new Autoboxing feature.

//method using varargs
public void addNumbers(Object ...args){ //only argument to the method....means varargs
    int sum = 0;
    for (Object object : args) { // compiler converts to an object array ?? Object[] args
      sum += (Integer)object;
    }
    System.out.println("sum is " + sum);
}


The above method can be called following ways:

//invoking methods using varargs
cnf.addNumbers(i1); // one arg -> gets converted to Object[] args of size 1
cnf.addNumbers(i1,i2); // two arguments -> gets converted to Object[] args of size 2
cnf.addNumbers(i1,i2,5); // three arguments -> gets converted to Object[] args of size 3


The printf() method would not be possible, if not for varargs feature.

// C style printf. System.out.printf(String arg0, Object ...arg1).
// this feature is possible due to var-args feature.
System.out.printf("num is: %1s, list size: %2s \n", num, numList.size()); // two arguments


Static imports let you avoid qualifying static members with class names. Once the static member is imported then you can use it in your code without the class name prefix.

//static import
import static sample.SampleStaticValues.NUM_ZERO;
//need not do SampleConstants.NUM_ZERO due to static import feature
if(num % 2 == NUM_ZERO){
    System.out.println("The num " + num + " is: " + OddEven.even);

}

package sample;
public class SampleStaticValues {
    public static int NUM_ZERO = 0;
    public static int NUM_ONE = 0;
}


Enhanced for loop

eliminates error-proneness of iterators and does not require any index variables. Also known as a "foreach" loop.

//":" should be read as "foreach". So should read as, foreach "num" value in numList.
for (Integer num : numList) { // no index variables.
    //
}


Enumerated types

They are type safe and force users of your class to use one of the acceptable values. Using static final integer values are type-unsafe and can lead to subtle bugs in your code as shown below:

public class PartyNeeds {
    public static final int PLATES = 1;
    public static final int CUPS = 2;
}


For simplicity assume that PartyNeeds has 2 values 1 for plates and 2 for cups, but nothing is stoping the programmer from assigning any other values like 3 or 4.

int partyItem = 3; //oops not a proper value as per class PartyNeeds but can happen and go //unnoticed

Enum will solve the above problem and it is a special type of class.

enum OddEven {odd,even} //use of "enum" keyword. An "enum" is a special classs.
if(num % 2 == NUM_ZERO){
    System.out.println("The num " + num + " is: " + OddEven.even);
}
else {
    System.out.println("The num " + num + " is: " + OddEven.odd);
}


Metadata lets you avoid writing boilerplate code, by enabling tools to generate it from annotations provided by the coder. This is a declarative style programming.

public class CombinedNewFeatures {
    ... public void addNumbers(Object ...args){
      int sum = 0;
      for (Object object : args) {
        sum += (Integer)object;
      }
      System.out.println("sum is " + sum);
    }
}


Now, the subclass of the above class with the @Override annotation can be written as shown below. If you misspell the overridden method name, you will get a compile error. This will safeguard your method from not being called at runtime. By adding the @Override metatag, the compiler complaints if you do not actually perform an override.

package sample;
public class ExtendedCombinedNewFeatures extends CombinedNewFeatures {
    @Override //metatag. If you spell the methodName incorrectly, you will get a compile error.
    public void addNumbers(Object ...args) {
      //overrides baseclass methods
    }
    @Override //metatag
    public void addValues(Object ...args) { //compile error! must override a superclass method
      // ....
    }
}




Java Swing >>>


Home Clouds