Skip to content

Instantly share code, notes, and snippets.

@krishnadey30
Last active January 30, 2021 21:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save krishnadey30/e5a6a23346c375f61a319e788078fa7a to your computer and use it in GitHub Desktop.
Save krishnadey30/e5a6a23346c375f61a319e788078fa7a to your computer and use it in GitHub Desktop.

Inheritance in Java:

Inheritance in Java is a mechanism in which one object acquires all the properties and behaviors of a parent object. When you inherit from an existing class, you can reuse methods and fields of the parent class. Moreover, you can add new methods and fields in your current class also.

Why use inheritance in java

  • For Method Overriding (so runtime polymorphism can be achieved).
  • For Code Reusability.

The syntax of Java Inheritance

class Subclass-name extends Superclass-name  
{  
    //methods and fields  
} 

Inheritance in Java

The relationship between the two classes is Programmer IS-A Employee. It means that Programmer is a type of Employee.

Types of inheritance in java

On the basis of class, there can be three types of inheritance in java: single, multilevel and hierarchical.Types of inheritance in Java

Multiple inheritance in Java

Note: Multiple inheritance is not supported in Java through class.`

Why multiple inheritance is not supported in java?

To reduce the complexity and simplify the language, multiple inheritance is not supported in java.

Consider a scenario where A, B, and C are three classes. The C class inherits A and B classes. If A and B classes have the same method and you call it from child class object, there will be ambiguity to call the method of A or B class.

Since compile-time errors are better than runtime errors, Java renders compile-time error if you inherit 2 classes. So whether you have same method or different, there will be compile time error.

Aggregation in Java

If a class have an entity reference, it is known as Aggregation. Aggregation represents HAS-A relationship.

class Employee{  
    int id;  
    String name;  
    Address address;//Address is a class  
	...  
}

Employee HAS-A address

Why use Aggregation?

  • For Code Reusability.

Method Overloading in Java

If a class has multiple methods having same name but different in parameters, it is known as Method Overloading.

Advantage of method overloading

Method overloading increases the readability of the program.

Different ways to overload the method

There are two ways to overload the method in java

  1. By changing number of arguments
  2. By changing the data type

In java, Method Overloading is not possible by changing the return type of the method only.

Why Method Overloading is not possible by changing the return type of method only?

In java, method overloading is not possible by changing the return type of the method only because of ambiguity.

Note: Compile Time Error is better than Run Time Error. So, java compiler renders compiler time error if you declare the same method having same parameters.

Method Overriding in Java

If subclass (child class) has the same method as declared in the parent class, it is known as method overriding in Java.

In other words, If a subclass provides the specific implementation of the method that has been declared by one of its parent class, it is known as method overriding.

Usage of Java Method Overriding

  • Method overriding is used to provide the specific implementation of a method which is already provided by its superclass.
  • Method overriding is used for runtime polymorphism

Rules for Java Method Overriding

  1. The method must have the same name as in the parent class
  2. The method must have the same parameter as in the parent class.
  3. There must be an IS-A relationship (inheritance).

Can we override static method?

No, a static method cannot be overridden. It can be proved by runtime polymorphism.


Why can we not override static method?

It is because the static method is bound with class whereas instance method is bound with an object. Static belongs to the class area, and an instance belongs to the heap area.


Can we override java main method?

No, because the main is a static method.

Difference between method Overloading and Method Overriding in java

No. Method Overloading Method Overriding
1) Method overloading is used to increase the readability of the program. Method overriding is used to provide the specific implementation of the method that is already provided by its super class.
2) Method overloading is performed within class. Method overriding occurs in two classes that have IS-A (inheritance) relationship.
3) In case of method overloading, parameter must be different. In case of method overriding, parameter must be same.
4) Method overloading is the example of compile time polymorphism. Method overriding is the example of run time polymorphism.
5) In java, method overloading can't be performed by changing return type of the method only. Return type can be same or different in method overloading. But you must have to change the parameter. Return type must be same or covariant in method overriding.

Covariant Return Type

The covariant return type specifies that the return type may vary in the same direction as the subclass.

class A{  
	A get(){
        return this;
    }  
}  
  
class B1 extends A{  
	B1 get(){
        return this;
    }  
	void message(){
        System.out.println("welcome to covariant return type");
    }  
  
	public static void main(String args[]){  
		new B1().get().message();  
	}  
}  

The return type of the get() method of A class is A but the return type of the get() method of B class is B. Both methods have different return type but it is method overriding. This is known as covariant return type.

How is Covariant return types implemented?

Java doesn't allow the return type based overloading but JVM always allows return type based overloading. JVM uses full signature of a method for lookup/resolution. Full signature means it includes return type in addition to argument types. i.e. , a class can have two or more methods differing only by return type. javac uses this fact to implement covariant return types.

Super Keyword in Java

The super keyword in Java is a reference variable which is used to refer immediate parent class object.

Whenever you create the instance of subclass, an instance of parent class is created implicitly which is referred by super reference variable.

Usage of Java super Keyword

  1. super can be used to refer immediate parent class instance variable.
  2. super can be used to invoke immediate parent class method.
  3. super() can be used to invoke immediate parent class constructor.

Instance initializer block

Instance Initializer block is used to initialize the instance data member. It run each time when object of the class is created. The initialization of the instance variable can be done directly but there can be performed extra operations while initializing the instance variable in the instance initializer block.

There are three places in java where you can perform operations:

  1. method
  2. constructor
  3. block

Instance initializer block is invoked at the time of object creation. The java compiler copies the instance initializer block in the constructor after the first statement super(). So firstly, constructor is invoked.

instance initializer block

Rules for instance initializer block :

There are mainly three rules for the instance initializer block. They are as follows:

  1. The instance initializer block is created when instance of the class is created.
  2. The instance initializer block is invoked after the parent class constructor is invoked (i.e. after super() constructor call).
  3. The instance initializer block comes in the order in which they appear.

Final Keyword In Java

The final keyword in java is used to restrict the user. The java final keyword can be used in many context. Final can be:

  1. variable
  2. method
  3. class

If you make any variable as final, you cannot change the value of final variable(It will be constant).

If you make any method as final, you cannot override it.

If you make any class as final, you cannot extend it.

Is final method inherited?

Yes, final method is inherited but you cannot override it.

What is blank or uninitialized final variable?

A final variable that is not initialized at the time of declaration is known as blank final variable. If you want to create a variable that is initialized at the time of creating object and once initialized may not be changed, it is useful. For example PAN CARD number of an employee.

It can be initialized only in constructor.

static blank final variable

A static final variable that is not initialized at the time of declaration is known as static blank final variable. It can be initialized only in static block.

class A{  
    static final int data;//static blank final variable  
    static{ data=50;}  
    public static void main(String args[]){  
        System.out.println(A.data);  
    }  
}  

Runtime Polymorphism in Java

Runtime polymorphism or Dynamic Method Dispatch is a process in which a call to an overridden method is resolved at runtime rather than compile-time. In this process, an overridden method is called through the reference variable of a superclass. The determination of the method to be called is based on the object being referred to by the reference variable.

Upcasting

class A{}  
class B extends A{}  
A a=new B();//upcasting  
Example
class Bike{  
  void run(){System.out.println("running");}  
}  
class Splendor extends Bike{  
  void run(){System.out.println("running safely with 60km");}  
  
  public static void main(String args[]){  
    Bike b = new Splendor();//upcasting  
    b.run();  // running safely with km
  }  
}  

Rule: Runtime polymorphism can't be achieved by data members.

Static Binding and Dynamic Binding

Connecting a method call to the method body is known as binding.

There are two types of binding

  1. Static Binding (also known as Early Binding).
  2. Dynamic Binding (also known as Late Binding).

Static binding

When type of the object is determined at compiled time(by the compiler), it is known as static binding. If there is any private, final or static method in a class, there is static binding.

Dynamic binding

When type of the object is determined at run-time, it is known as dynamic binding.

Java instanceof

The java instanceof operator is used to test whether the object is an instance of the specified type (class or subclass or interface). The instanceof in java is also known as type comparison operator because it compares the instance with type. It returns either true or false. If we apply the instanceof operator with any variable that has null value, it returns false.

An object of subclass type is also a type of parent class.

Downcasting with java instanceof operator

When Subclass type refers to the object of Parent class, it is known as downcasting. If we perform it directly, compiler gives Compilation error. If you perform it by typecasting, ClassCastException is thrown at runtime. But if we use instanceof operator, downcasting is possible.

	Dog d=**new** Animal();//Compilation error 

If we perform downcasting by typecasting, ClassCastException is thrown at runtime.

    Dog d=(Dog)**new** Animal();  
    //Compiles successfully but ClassCastException is thrown at runtime  

Downcasting with instanceof

Let's see the example, where downcasting is possible by instanceof operator.

class Animal { }  

class Dog3 extends Animal {  
    static void method(Animal a) {  
        if(a instanceof Dog3){  
            Dog3 d=(Dog3)a;//downcasting  
            System.out.println("ok downcasting performed");  
        }  
    }  

    public static void main (String [] args) {  
        Animal a=new Dog3();  
        Dog3.method(a);  
    }  

}  

Downcasting without the use of java instanceof

Downcasting can also be performed without the use of instanceof operator as displayed in the following example:

class Animal { }  
class Dog4 extends Animal {  
    static void method(Animal a) {  
        Dog4 d=(Dog4)a;//downcasting  
        System.out.println("ok downcasting performed");  
    }  
    public static void main (String [] args) {  
        Animal a=new Dog4();  
        Dog4.method(a);  
    }  
}  

But what will happen if we write:

Animal a=new Animal();  

Dog.method(a);  
//Now ClassCastException but not in case of instanceof operator  

Abstract class in Java

A class which is declared with the abstract keyword is known as an abstract class in Java. It can have abstract and non-abstract methods (method with the body). It needs to be extended and its method implemented. It cannot be instantiated.

Points to Remember

  • An abstract class must be declared with an abstract keyword.
  • It can have abstract and non-abstract methods.
  • It cannot be instantiated.
  • It can have constructors and static methods also.
  • It can have final methods which will force the subclass not to change the body of the method.

Abstraction is a process of hiding the implementation details and showing only functionality to the user.

Ways to achieve Abstraction

There are two ways to achieve abstraction in java

  1. Abstract class (0 to 100%)
  2. Interface (100%)

**Rule: If there is an abstract method in a class, that class must be abstract. **

**Rule: If you are extending an abstract class that has an abstract method, you must either provide the implementation of the method or make this class abstract. **

Interface in Java

An interface in java is a blueprint of a class.

  • It has static constants and abstract methods. The interface in Java is a mechanism to achieve abstraction.

  • There can be only abstract methods in the Java interface, not method body.

  • It is used to achieve abstraction and multiple inheritance in Java.

  • Java Interface also represents the IS-A relationship.

  • It cannot be instantiated just like the abstract class.

  • Since Java 8, we can have default and static methods in an interface.

  • Since Java 9, we can have private methods in an interface.

  • All the fields are public, static and final by default.

  • A class that implements an interface must implement all the methods declared in the interface.

There are mainly three reasons to use interface. They are given below.

  • It is used to achieve abstraction.
  • By interface, we can support the functionality of multiple inheritance.
  • It can be used to achieve loose coupling.

The relationship between class and interface

Multiple inheritance is not supported through class in java, but it is possible by an interface, why?

As we have explained in the inheritance chapter, multiple inheritance is not supported in the case of class because of ambiguity. However, it is supported in case of an interface because there is no ambiguity. It is because its implementation is provided by the implementation class.

Java 8 Default Method in Interface

Since Java 8, we can have method body in interface. But we need to make it default method.

interface Drawable{  
    void draw();  
    default void msg(){System.out.println("default method");}  
}  
class Rectangle implements Drawable{  
    public void draw(){System.out.println("drawing rectangle");}  
}  
class TestInterfaceDefault{  
    public static void main(String args[]){  
        Drawable d=new Rectangle();  
        d.draw();  
        d.msg();  
    }
} 

Java 8 Static Method in Interface

Since Java 8, we can have static method in interface. Let's see an example:

interface Drawable{  
    void draw();  
    static int cube(int x){return x*x*x;}  
}  
class Rectangle implements Drawable{  
    public void draw(){System.out.println("drawing rectangle");}  
}  

class TestInterfaceStatic{  
    public static void main(String args[]){  
        Drawable d=new Rectangle();  
        d.draw();  
        System.out.println(Drawable.cube(3));  
    }
}  

What is marker or tagged interface?

An interface which has no member is known as a marker or tagged interface

Abstract class Interface
Abstract class can have abstract and non-abstractmethods. Interface can have only abstract methods. Since Java 8, it can have default and static methods also.
Abstract class doesn't support multiple inheritance. Interface supports multiple inheritance.
Abstract class can have final, non-final, static and non-static variables. Interface has only static and final variables.
Abstract class can provide the implementation of interface. Interface can't provide the implementation of abstract class.
The abstract keyword is used to declare abstract class. The interface keyword is used to declare interface.
An abstract classcan extend another Java class and implement multiple Java interfaces. An interface can extend another Java interface only.
An abstract classcan be extended using keyword "extends". An interface classcan be implemented using keyword "implements".
A Javaabstract classcan have class members like private, protected, etc. Members of a Java interface are public by default.
Example: public abstract class Shape{ public abstract void draw(); } Example: public interface Drawable{ void draw(); }

Iterators in Java

Enumeration

It is a interface used to get elements of legacy collections(Vector, Hashtable). Enumeration is the first iterator present from JDK 1.0, rests are included in JDK 1.2 with more functionality. **We can create Enumeration object by calling elements() method of vector class on any vector object **

There are two methods in Enumeration interface namely :

// Tests if this enumeration contains more elements
public boolean hasMoreElements();

// Returns the next element of this enumeration 
// It throws NoSuchElementException
// if no more element present
public Object nextElement();

Limitations of Enumeration :

  • Enumeration is for legacy classes(Vector, Hashtable) only. Hence it is not a universal iterator.
  • Remove operations can’t be performed using Enumeration.
  • Only forward direction iterating is possible.

Iterators

It is a universal iterator as we can apply it to any Collection object. By using Iterator, we can perform both read and remove operations. It is improved version of Enumeration with additional functionality of remove-ability of a element.

Iterator object can be created by calling iterator() method present in Collection interface.

// Here "c" is any Collection object. itr is of
// type Iterator interface and refers to "c"
Iterator itr = c.iterator();

Iterator interface defines three methods:

// Returns true if the iteration has more elements
public boolean hasNext();

// Returns the next element in the iteration
// It throws NoSuchElementException if no more 
// element present
public Object next();

// Remove the next element in the iteration
// This method can be called only once per call
// to next()
public void remove();

remove() method can throw two exceptions

  • UnsupportedOperationException : If the remove operation is not supported by this iterator
  • IllegalStateException If the next method has not yet been called, or the remove method has already been called after the last call to the next method

Limitations of Iterator :

  • Only forward direction iterating is possible.
  • Replacement and addition of new element is not supported by Iterator.

ListIterator

It is only applicable for List collection implemented classes like arraylist, linkedlist etc. It provides bi-directional iteration.

ListIterator must be used when we want to enumerate elements of List. This cursor has more functionality(methods) than iterator.

ListIterator object can be created by calling listIterator() method present in List interface.

// Here "l" is any List object, ltr is of type
// ListIterator interface and refers to "l"
ListIterator ltr = l.listIterator();

ListIterator interface extends Iterator interface. So all three methods of Iterator interface are available for ListIterator. In addition there are six more methods.

// Forward direction

// Returns true if the iteration has more elements
public boolean hasNext();

// same as next() method of Iterator
public Object next();

// Returns the next element index 
// or list size if the list iterator
// is at the end of the list
public int nextIndex();

// Backward direction

// Returns true if the iteration has more elements
// while traversing backward
public boolean hasPrevious();

// Returns the previous element in the iteration
// and can throws NoSuchElementException
// if no more element present
public Object previous();

// Returns the previous element index 
//  or -1 if the list iterator is at the 
// beginning of the list
public int previousIndex();

// Other Methods
 
// same as remove() method of Iterator
public void remove();

// Replaces the last element returned by 
// next() or previous() with the specified element 
public void set(Object obj);

// Inserts the specified element into the list at
// position before the element that would be returned 
// by next(),
public void add(Object obj);

ListIterator has no current element; its cursor position always lies between the element that would be returned by a call to previous() and the element that would be returned by a call to next()

set() method can throw four exceptions

  • UnsupportedOperationException – if the set operation is not supported by this list iterator
  • ClassCastException : If the class of the specified element prevents it from being added to this list
  • IllegalArgumentException : If some aspect of the specified element prevents it from being added to this list
  • IllegalStateException : If neither next nor previous have been called, or remove or add have been called after the last call to next or previous

add() method can throw three exceptions

  • UnsupportedOperationException : If the add method is not supported by this list iterator
  • ClassCastException : If the class of the specified element prevents it from being added to this list
  • IllegalArgumentException : If some aspect of this element prevents it from being added to this list

Hashtable in Java

This class implements a hash table, which maps keys to values. Any non-null object can be used as a key or as a value. To successfully store and retrieve objects from a hashtable, the objects used as keys must implement the hashCode method and the equals method.

  • It is similar to HashMap, but is synchronised.
  • Hashtable stores key/value pair in hash table.
  • In Hashtable we specify an object that is used as a key, and the value we want to associate to that key. The key is then hashed, and the resulting hash code is used as the index at which the value is stored within the table.

Constructors:

  • Hashtable(): This is the default constructor.
  • Hashtable(int size): This creates a hash table that has initial size specified by size.
  • Hashtable(int size, float fillRatio): This version creates a hash table that has initial size specified by size and fill ratio specified by fillRatio. fill ratio: Basically it determines how full hash table can be before it is resized upward.and its Value lie between 0.0 to 1.0
  • Hashtable(Map m): This creates a hash table that is initialised with the elements in m.

Methods:

  1. clear(): method clears the hashtable so that it contains no keys.

  2. clone(): used to create a shallow copy of this hashtable.

  3. computeIfAbsent(Key, Function): The computeIfAbsent(Key, Function) method of Hashtable class which allows you to compute value of a mapping for specified key if key is not already associated with a value (or is mapped to null).

        table.computeIfAbsent("newPen", k -> 600); 
        table.computeIfAbsent("newBook", k -> 800); 
  4. contains(Object value): The java.util.Hashtable.contains(Object value) method in Java is used to check whether a particular value is being mapped by any keys present in the Hashtable.

  5. containsKey(Object key): tests if some key maps into the specified value in this hashtable.

  6. containsValue(Object value): returns true if this hash table maps one or more keys to this value.

  7. entrySet(): used to get a set view of the entries contained in this hash table.

  8. equals(Object o): used to compare specified object with this Map for equality.

  9. get(Object key): used to get the object that contains the value associated with key.

  10. hashCode(): returns the hash code value for this Map as per the definition in the Map interface.

  11. isEmpty(): used to test if this hashtable maps no keys to values.

  12. elements(): Returns an enumeration of the values obtained in hash table.

  13. keys(): used to get enumeration of the keys contained in the hash table.

  14. put(Object key, Object value): maps the specified key to the specified value in this hashtable.

  15. putIfAbsent(Key, Function): This method of Hashtable class allows to map a value to a given key if given key is not associated with a value or mapped to null. A null value is returned if such key-value set is already present in the HashMap.

  16. KeySet(): used to get a Set view of the keys contained in this hash table.

  17. putAll(Map t): copies all of the mappings from the specified map to this hashtable.

  18. rehash(): Increase the size of the hash table and rehashes all its keys.

  19. remove(Object key): Removes key and its value.

  20. size(): returns the number of entries in hash table.

  21. toString(): returns the string equivalent of a hash table.

  22. values(): used to get a Collection view of the values contained in this Hashtable.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment