INTERVIEW QUESTIONS FOR JAVA
1. What is Default Access?
When a class or member is declared with default access, it can be accessed by any other class or member within the same package, but not by classes or members outside the package. This provides a level of encapsulation, as it allows classes within a package to communicate with each other without exposing their implementation details to outside classes.
To declare a class or member with default access in Java, simply omit any access modifier keyword (such as public or private) from the declaration.
For example:
class MyClass {void myMethod() {
// default access
}
}
2. What are Static variables?
In Java, a static variable is a variable that belongs to a class rather than an instance of the class. This means that all instances (objects) of the class share the same copy of the variable, as opposed to having their own separate copies.
To declare a static variable in Java, you use the static keywordpublic class MyClass
static int myStaticVariable = 42;
}
}
Static variables can be accessed directly using the class name, without needing to create an instance of the class.
For example:
Static variables can also be modified directly using the class name:
3. What is Dynamic binding?
In Java, dynamic binding is achieved through method overriding, which is the ability of a subclass to provide its own implementation of a method that is already defined in its superclass.
Consider the following example:
class Animal {public void speak() {
System.out.println("I am an animal");
}
}
class Dog extends Animal {
public void speak() {
System. out.println("I am a dog");
}
}
public class Main {
public static void main(String[] args) {
Animal animal1 = new Animal();
Animal animal2 = new Dog();
animal1.speak(); // Output: "I am an animal"
animal2.speak(); // Output: "I am a dog"
}
}
Here, we have a superclass Animal and a subclass Dog. Both classes have a speak() method, but the implementation in Dog overrides the implementation in Animal. In the main() method, we create an instance of Animal and an instance of Dog and assign them to variables of type Animal.
When we call the speak() method on each of these variables, we see that the output depends on the actual type of the object at runtime: the speak() method of Animal is called on the animal1 object, while the speak() method of Dog is called on the animal2 object.
This is an example of dynamic binding in Java. The speak() method is bound at runtime to the actual implementation of the method based on the object's actual type. This allows for greater flexibility and extensibility in object-oriented programming, as subclasses can override and provide their own implementations of methods defined in their superclasses, without affecting the behavior of the superclass or other subclasses.
4. What is Serilization?
Serialization is the process of converting an object into a format that can be easily transmitted across a network or stored in a file. In Java, serialization is achieved through the use of the java.io.Serializable interface and the ObjectOutputStream and ObjectInputStream classes.To make a class serializable, it must implement the Serializable interface:
import java.io.Serializable;
public class MyClass implements Serializable {
// class implementation
}
Once a class is made serializable, instances of the class can be written to an output stream using an ObjectOutputStream and read from an input stream using an ObjectInputStream.
// Writing object to a file
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("file.txt"));
// Reading object from a file
ObjectInputStream in = new ObjectInputStream(new FileInputStream("file.txt"));
MyClass obj2 = (MyClass) in.readObject();
In the example above, an instance of MyClass is created and written to a file using an ObjectOutputStream. Later, the object is read from the file using an ObjectInputStream and cast to the appropriate type.
Serialization is particularly useful when dealing with distributed applications, where objects need to be sent over a network or stored in a file. It allows objects to be easily transmitted or stored without having to worry about the underlying implementation details. However, care should be taken when serializing objects that contain sensitive data, as the data can be easily accessed if the serialization process is not properly secured.
5. Which of the following is tightly bound? Inheritance or Composition?
Inheritance and composition are both mechanisms for building complex classes from simpler ones, but they differ in the way that the classes are related to each other. In inheritance, a subclass extends and inherits properties and behaviors from a superclass, whereas in composition, a class contains one or more instances of other classes as part of its internal state.
Inheritance creates a tight coupling between the superclass and subclass, as the subclass depends on the superclass for its implementation. Changes to the superclass can have a direct impact on the behavior of the subclass, and the subclass cannot function without the superclass. Therefore, inheritance is considered to be tightly bound.
Composition, on the other hand, creates a looser coupling between classes, as the containing class can be composed of any number of instances of other classes and the internal structure of the containing class can be modified without affecting the classes that it contains. Therefore, the composition is considered to be loosely bound.In summary, inheritance is tightly bound, while the composition is loosely bound.
6. Difference between Hash and Hash Table?
Both HashMap and HashTable are classes in Java that implement the Map interface and are used to store key-value pairs. However, there are several differences between them:
Synchronization: HashTable is synchronized, which means that it is thread-safe and can be accessed by multiple threads at the same time without any problem. On the other hand, HashMap is not synchronized, which means that it is not thread-safe and can cause problems if accessed by multiple threads simultaneously. However, ConcurrentHashMap can be used for thread-safe operations with HashMap.
Null values: HashTable does not allow null keys or values, whereas HashMap allows one null key and any number of null values.
Iteration: HashTable iterator is not fail-fast, whereas the HashMap iterator is fail-fast. This means that if the collection is modified during the iteration, HashMap will throw ConcurrentModificationException while HashTable will not.
Performance: HashMap is generally faster than HashTable as it is not synchronized, but this comes at the cost of being not thread-safe.
Legacy: HashTable is a legacy class and was present in Java from earlier versions, while HashMap is a newer implementation that was introduced in Java 1.2.
In general, HashMap is preferred over HashTable for non-concurrent use due to its better performance, ability to handle null values, and iterator fail-fast behavior. However, if thread safety is required, HashTable or ConcurrentHashMap can be used.
Yes, using static after the access modifier public in a method declaration will result in a compilation error in Java. The correct syntax for a method with public access modifier and a static keyword is:
// method body
}
The order of the access modifier and the static keyword cannot be interchanged. In Java, the access modifier must come before the static keyword.
8. Can we make the constructor final?
9. Does the constructor returns any value?
Unlike methods, constructors cannot return a value explicitly. Instead, the constructor initializes the state of the object and returns the reference to the newly created object. So, you cannot use the return statement inside a constructor to return a value.
In summary, constructors do not return any value, and their role is to initialize the state of an object when it is created.
10. What is the Difference between String and String Buffer?
Both String and StringBuffer are used to represent text in Java, but they differ in the way they are implemented and how they handle changes to the text.
The string is an immutable class, which means that once a String object is created, its value cannot be changed. Any operation that modifies the string, such as concatenation, results in a new String object being created. This can lead to performance issues when working with large strings, as creating new objects can be time-consuming and memory-intensive.
On the other hand, StringBuffer is a mutable class that allows for the dynamic modification of its contents. When modifications are made to a StringBuffer object, the object itself is modified, rather than creating a new object. This can result in better performance when working with large strings that require frequent modifications.
Here's an example of using String and StringBuffer:
String str = "Hello";
str += " world"; // This creates a new String object
StringBuffer sb = new StringBuffer("Hello");
sb.append(" world"); // This modifies the existing StringBuffer object
In general, use String when you need to represent text that will not change, and use StringBuffer when you need to modify the text frequently. However, it's worth noting that in Java 5 and later, the StringBuilder class is preferred over StringBuffer because it is not synchronized, making it faster in single-threaded environments.