What are the fundamental principles of object-oriented programming?
Object-oriented programming has four principles, namely Inheritance, Encapsulation, Abstraction and Polymorphism.
Encapsulation refers to having behaviour, data and data manipulation logic enclosed within the object.
Abstraction is the ability to hide implementation details from anyone who is making use of the object.
What is inheritance? Can you do multiple inheritance in Java?
Inheritance allows a developer to mark a class as a parent and embed the parent class’s behaviour and attributes as if these are part of the child class without the need to duplicate code. Java supports single inheritance only and thus does not support multiple inheritance. A developer may use Interfaces to enforce different behaviours since a class can implement multiple interfaces.
What is polymorphism?
Java supports two types of polymorphism. Compile-time polymorphism is also known as overloading. Overloading refers to the ability to provide more than one set of parameters for a class method. The second type of polymorphism is Runtime polymorphism which is also known as overriding. Overriding refers to the ability of a subclass to redefine the behaviour for a parents method.
What is constructor overloading? Provide an example
Constructor overloading is when a class provides multiple constructors with a different set of parameters.
The class java.lang.Exception provides overloaded constructors through which you can initialise an exception class in different ways. The different constructors allow the developer to choose to initialise the Exception class without any information or with a message only or with a cause only or with both cause and message.
Below is the list of the four public constructors for the Exception class.
- Exception()
- Exception(String message)
- Exception(String message, Throwable cause)
- Exception(Throwable cause)
What is method overloading?
An overloaded method is one which provides multiple signatures and thus can be invoked using a different number of parameters and/or parameter types.
What is method overriding? Provide an example
Method overriding is when a method of the parent class is reimplemented in the child class using the same name and method signature to reflect a difference in behaviour for the child class.
The below code shows two classes Circle and Square. These two classes inherit the class shape and override the method draw. The below code creates an instance of each class, stores it in an array of shapes and calls the method draw on each instance. Java resolves the draw method behaviour according to the instance type.
import java.util.Arrays;
public class AppLauncher {
public static void main(String[] args) {
Shape[] shapes = {new Shape(), new Circle(), new Square()};
Arrays.stream(shapes).forEach(shape -> shape.draw());
}
}
class Shape {
public void draw() {
System.out.println("I am a generic shape, not sure what to draw");
}
}
class Circle extends Shape {
public void draw() {
System.out.println("I am a circle");
}
}
class Square extends Shape {
public void draw() {
System.out.println("I am a square");
}
}
Executing the above code will result in the output shown below. The output shows the behaviour of invoking an overridden method.
Output:
I am a generic shape, not sure what to draw
I am a circle
I am a square
What is an unchecked exception in java
An unchecked exception occurs in an abnormal situation and is not required to be handled or declared in the throws clause. Unchecked exceptions are all exception which has RuntimeException or Error as their direct or indirect parent.
What is the difference between static and non-static methods
Non-static methods can only be invoked on an instance of a class and can access both static and non-static fields.
A class can invoke a static method without the need to create an instance. However, these static methods can only access static fields.
What is garbage collection?
Java automatically manages heap memory. When an object is unreferenced, java can reclaim the allocated heap memory. This automatic memory reclamation process is called garbage collection.
Garbage collection is a two-step process, where the collector first has to analyse heap memory contents, identify the objects which are unreferenced and marking these memory areas. In a second stage, the collector will delete the unreferenced memory and may also compact the remaining referenced memory to simplify and speed up the process of future memory allocations.
An empirical analysis of applications shows that most objects are short-lived. To improve Garbage collection performance, Java separates heap memory into three main generations, namely young, tenured and permanent generation. Objects are created in the young generation and eventually promoted to the tenured generation after the objects reach a certain threshold age.
What are the differences between final, finally and finalize in java?
Final prevents changes to the value of a variable.
Finally provides code to execute on the completion of a code block irrespective of whether the code completes the try part successfully or ends up terminating execution of the try block prematurely due to an error.
The Finalize method is invoked by the garbage collector when an object becomes unreferenced and should contain code that performs cleanups and frees any resources held by the class.
NOTE: the finalise method was declared deprecated in JDK 9, and thus developers should avoid using this method as much as possible.
What is the use of the final keyword in Java?
The final keyword applies to a class, method, method parameter and class fields.
A final class is one that cannot be extended any further by the developer (i.e. it marks a leaf in the inheritance tree).
A final method is a method that cannot be overridden by any subclasses of the class.
When the final keyword precedes a method parameter or class field, this means that the parameter or field cannot have their value changed for the primitive types. For the reference types, however, this means that the parameter or field cannot change to refer to another object, however, the internal state of the object is still allowed to change.
What is the difference between ArrayList and HashSet in Java?
An ArrayList implements the list interface and makes use of arrays, keeps the items stored in the order in which they were inserted and can have duplicate items. Insertion, removal and retrieval have a time complexity of O(n)
A HashSet implements the set interface and uses a HashMap as the underlying structure. A HashSet is unordered and thus does not keep any representation of the item insertion order. It does not accept duplicate items and has a time complexity of O(1) for insertion, removal and retrieval.
What is a Volatile variable in Java?
A volatile variable has changes that occur to its value, synchronised immediately to main memory, thus making the new value immediately available and readable by other threads.
What is the difference between transient and volatile variables in Java?
A transient variable is one which is ignored by the serialisation process, and thus when an object is serialised, a transient variable’s value is not persisted. A volatile variable is one for which the value is written immediately to main memory which makes it’s value visible across different threads.
What is the difference between an interface and an abstract class in Java?
A class can implement multiple interfaces but can only inherit a single abstract class. An abstract class can specify data members while an interface is not allowed to specify data members. An abstract class can provide implementations for constructors while an interface cannot. All methods defined within an interface have to be declared public in the implementing class. An abstract class in comparison can specify access modifiers for its’ methods. Abstract classes can provide static members while interfaces are not allowed to define static members.
An interface can provide a default implementation for a method (assuming Java 8 or later). This method must operate in terms of signatures within the interface and cannot use any underlying implementations’ state.
An abstract class is allowed to mark specific methods as abstract meaning that it can postpone implementation of these methods to the child class. All non-abstract methods in an abstract class must provide an implementation.
What is the difference between this and super in Java?
The keyword ‘this’ refers to the current instance of the current implementation, whereas ‘super’ refers to the immediate parent class of the current class. Super can be used to invoke the parents class constructor, in which case the call to the super constructor should be on the first line of the constructor.
The keywords this and super can both be used as constructors. The ‘this’ constructor is used to invoke an overloaded constructor from a constructor within the same class.
The ‘super’ constructor is used to invoke a parameterised constructor of the parent’s constructor instead of the default constructor. If super is not explicitly invoked java will still chain the default constructors.
What is the difference between String, StringBuilder and StringBuffer?
A string is an immutable object which stores a character sequence. Java creates a new instance when the developer changes the value of the string. The ‘+’ operator is supported for strings and performs a concatenation operation.
StringBuffer provides an alternative class for storing a mutable object that stores a character sequence. The class saves the content and the length and offers several methods to alter the contents. The StringBuffer class is thread-safe and performs synchronisation where necessary.
Similar to StringBuffer, the class StringBuilder, provides mutable access to a character sequence and allows manipulation through its methods. It provides the same features that the StringBuffer class offers. StringBuilder does not perform method synchronisation and thus is faster than StringBuffer. The StringBuilder class was created in JDK-5, to replace StringBuffer in situations where a single thread uses the class.
What is a shallow and deep copy?
A shallow copy creates a copy of the primitive types and the address of reference types only. If an object A has a reference to an object B, a shallow copy of A creates a new object A`. Both A and A` refer to object B.
A deep copy creates a copy of all the primitive types and reference types. Thus if an object A has a reference to an object B, then a deep copy of A will create a new object A` which will reference a new object B`.