Skip to main content

Interfaces

  • interface is a keyword which is used to define User Defined Datatypes.
  • Interface is a special class which is fully abstracted.
  • Interface can be used to achieve the multiple inheritance in Java.
  • One interface can extend one or more interfaces.
  • One class can implement one or more interfaces.

Syntax to declare interface​

<modifiers>interface<InterfaceName>
{
// Members
}

Interface can contain following members:​

  • public final static variables
  • public abstract methods
  • public static inner classes

  • Variables declared in the interface are by default public final static. So it is unnecessary to use these modifiers for variables.
  • Methods declared in the interface are by default public abstract. So it is unnecessary to use these modifiers for methods.

Lab540.java​

interfaceInter1{
voidm1();

publicabstractvoidm2();

intA=10;

publicfinalintB=20;
}

classHelloextendsInter1{ }

classLab540{
publicstaticvoidmain(Stringargs[]){
System.out.println("Hello Guys!");
}
}

Lab541.java​

interfaceInter1{
voidm1();

publicabstractvoidm2();

intA=10;

publicfinalintB=20;
}
classHelloimplementsInter1{ }

classLab541{
publicstaticvoidmain(Stringargs[]){
System.out.println("Hello Guys!");
}
}

Lab542.java​

interfaceInter1{
voidm1();

publicabstractvoidm2();

intA=10;

publicfinalintB=20;
}

abstractclassHelloimplementsInter1{ }

classLab542{
publicstaticvoidmain(Stringargs[]){
System.out.println("Hello Guys!");
}
}

Lab543.java​

interfaceInter1{
voidm1();

publicabstractvoidm2();

intA=10;

publicfinalintB=20;
}

classHelloimplementsInter1{

voidm1(){
System.out.println("Hello -> m1()");
}

publicvoidm2(){
System.out.println("Hello -> m2()");
}
}

classLab543{
publicstaticvoidmain(Stringargs[]){
System.out.println("Hello Guys!");
}
}

Lab544.java​

interfaceInter1{
voidm1();

publicabstractvoidm2();

intA=10;

publicfinalintB=20;
}

classHelloimplementsInter1{

publicvoidm1(){
System.out.println("Hello -> m1() :"+A);
}

publicvoidm2(){
System.out.println("Hello -> m2() :"+B);
}
}
classLab544{
publicstaticvoidmain(Stringargs[]){
Inter1ref=null;

// ref = new Inter1();

ref=newHello();

ref.m1();
ref.m2();
}
}

Lab545.java​

interfaceInter1{
voidm1();

publicabstractvoidm2();

intA=10;

publicfinalintB=20;
}

abstractclassHelloimplementsInter1{

publicvoidm1(){
System.out.println("Hello -> m1() :"+A);
}
}
classHaiextendsHello{

publicvoidm2(){
System.out.println("Hai -> m2() :"+B);
}

voidm3(){
System.out.println("Hai -> m3()");
}
}

classLab545{
publicstaticvoidmain(Stringargs[]){
Inter1ref=newHai();

ref.m1();
ref.m2();

// ref.m3();
}
}

Lab546.java​

interfaceInter1{
voidm1();
intA=10;
}

interfaceInter2{
voidm2();
intB=11;
}
classHelloimplementsInter1,Inter2{

publicvoidm1(){
System.out.println("Hello -> m1()");
}

publicvoidm2(){
System.out.println("Hello -> m2()");
}
}
classLab546{
publicstaticvoidmain(Stringargs[]){
Helloh=newHello();

System.out.println(h.A);
System.out.println(h.B);

h.m1();
h.m2();
}
}

Inter1.java​

interfaceInter1{
voidm1();
voidm2();

intA=10;
intB=20;
}

Inter2.java​

interfaceInter2{
voidm2();
voidm3();

intA=11;
intC=30;
}

Lab547.java​

classHelloimplementsInter1,Inter2{

publicvoidm1(){
System.out.println("Hello -> m1()");
}

publicvoidm2(){
System.out.println("Hello -> m2()");
}

publicvoidm3(){
System.out.println("Hello -> m3()");

System.out.println(B);
System.out.println(C);
}
}
classLab547{
publicstaticvoidmain(Stringargs[]){
Helloh=newHello();

h.m1();
h.m2();
h.m3();
}
}

Lab548.java​

classHelloimplementsInter1,Inter2{

publicvoidm1(){
System.out.println("Hello -> m1()");
}

publicvoidm2(){
System.out.println("Hello -> m2()");
}

publicvoidm3(){
System.out.println("Hello -> m3()");

System.out.println(A);
System.out.println(B);
System.out.println(C);
}
}
classLab548{
publicstaticvoidmain(Stringargs[]){
Helloh=newHello();

h.m1();
h.m2();
h.m3();
}
}

Lab549.java​

classHelloimplementsInter1,Inter2{

publicvoidm1(){
System.out.println("Hello -> m1()");
}

publicvoidm2(){
System.out.println("Hello -> m2()");
}

publicvoidm3(){
System.out.println("Hello -> m3()");

System.out.println(Inter1.A);
System.out.println(Inter2.A);

System.out.println(B);
System.out.println(C);
}
}

classLab549{
publicstaticvoidmain(Stringargs[]){
Helloh=newHello();

h.m1();
h.m2();
h.m3();
}
}

Lab550.java​

classHelloimplementsInter1,Inter2{
// Same as Lab549
}
classLab550{
publicstaticvoidmain(Stringargs[]){
Helloh=newHello();

Inter1ref1=h;

ref1.m1();
ref1.m2();

Inter2ref2=h;

ref2.m2();
ref2.m3();
}
}

Lab551.java​

interfaceInter1{
voidshow();
}

classA{
publicvoidshow(){
System.out.println("A -> show()");
}
}

classBextendsAimplementsInter1{ }
classLab551{
publicstaticvoidmain(String[]args){
Bref=newB();

b.show();
}
}

Inter1.java​

interfaceInter1{
intAB=90;
}
classHaiimplementsInter1{

voidshow(){
System.out.println(super.AB);
}
}

Inter1.java​

interfaceInter1{
intAB=90;
}

classHello{
StringAB="JavaWorld";
}
classHaiextendsHelloimplementsInter1{

voidshow(){
System.out.println(super.AB);
System.out.println(Inter1.AB);
}
}

Limitation of Multiple Inheritance

Lab552.java​

interfaceInter1{
voidshow();
}
interfaceInter2{
intshow();
}
classAimplementsInter1{

publicvoidshow(){ }
}
classBimplementsInter2{

publicintshow(){
return0;
}
}
classCimplementsInter1,Inter2{

publicvoidshow(){ }

publicintshow(){
return0;
}
}

Lab553.java​

interfaceInter1{
voidshow();
}
classA{

publicstaticvoidshow(){
System.out.println("show method");
}
}
classBextendsAimplementsInter1{

publicvoidshow(){ }
}

Notes​

  1. Always super keyword is used only in classes. It is avoided in interface.
  2. One static method cannot be overridden as instance method.

Problem with Multiple Inheritance using Classes​

Diagram Explanation​

A
void show()
int x = 11;

/ \
/ \
B C

B: C:
void show(){} void show(){}
int x = 90; int x = 80;

\ /
\ /
D

Inside class D​

voidshow(){
super.show();
super.x=88;
}

D(){
super();
}

➡ This causes Ambiguity Error

Because D does not know whether super refers to class B or class C.


Important Points

  • When a class extends multiple classes, some members may be common in super classes.
  • When you refer those common members from the subclass, it results in an ambiguity problem.
  • When you create a subclass object, first superclass constructor should be invoked.
  • If multiple superclasses are present, then it becomes confusing which superclass constructor should be invoked first.

Multiple Inheritance using Interfaces

Diagram​

I1
void show();
int x = 11;

/ \
/ \
I2 I3

void show(); void show();
int x = 90; int x = 80;

\ /
\ /
A

Class A​

voidshow(){
super.show();

I1.x
I2.x
I3.x
}

A(){
super();
}

Important Notes

1. super can't be used for interfaces​

  • Interface methods do not have implementation.
  • So super.show() is not possible in interfaces.

2. Accessing variables in interfaces​

Because interface variables are static, we can access them using the interface name.

Example:

I1.x
I2.x
I3.x

3. Interfaces don't have constructors​

So constructor ambiguity problems will not occur in interfaces.


Calling Interface Members

Calling interface methods​

InterfaceName.method();

Accessing interface variables​

InterfaceName.variable;

Why Multiple Inheritance works with Interfaces but not Classes

Multiple inheritance using classes causes:

  1. Ambiguity problem (same methods/variables from multiple superclasses)
  2. Constructor confusion (which superclass constructor should be called?)

Interfaces avoid these problems because:

  • Interface methods normally don't have implementation.
  • Variables are static and accessed using interface names.
  • Interfaces don't have constructors.

Using Assignment and Type Casting with Reference Type

A.java​

classA{ }

classBextendsA{ }

classCextendsA{ }

classDextendsB{ }

classE{ }

Lab554.java

classLab554{
publicstaticvoidmain(Stringargs[]){
Ddobj=newD();

Aaobj=dobj;// Upcasting

Bbobj=aobj;// Error

Ddobj1=aobj;// Error
}
}

Notes​

  • Upcasting is allowed directly.
  • Downcasting requires explicit type casting.

Lab555.java

classLab555{
publicstaticvoidmain(Stringargs[]){
Ddobj=newD();

Aaobj=dobj;

Bbobj= (B)aobj;

Ddobj1= (D)aobj;

System.out.println("Hello Guys");
}
}

Output​

Hello Guys

Notes​

  • Downcasting is possible using explicit casting.

Lab556.java

classLab556{
publicstaticvoidmain(Stringargs[]){
Aaobj=newD();

Ccobj= (C)aobj;

System.out.println("Hello Guys");
}
}

Notes​

  • Compiles successfully.
  • Runtime error occurs (ClassCastException).
  • Because D and C are not related.

Using instanceof with Reference Type

Lab557.java

classLab557{
publicstaticvoidmain(Stringargs[]){
Aaobj=newD();

if(aobjinstanceofC){
Ccobj= (C)aobj;
}

System.out.println("Hello Guys");
}
}

Notes​

  • instanceof prevents invalid casting.

Lab558.java

classLab558{
publicstaticvoidmain(Stringargs[]){
Aaobj=newD();

Eeobj= (E)aobj;

System.out.println("Hello Guys");
}
}

Notes​

  • Compile-time error.
  • A and E have no relationship.

Lab559.java

classLab559{
publicstaticvoidmain(Stringargs[]){
Aaobj=newD();

System.out.println(aobjinstanceofA);
System.out.println(aobjinstanceofB);
System.out.println(aobjinstanceofC);
System.out.println(aobjinstanceofD);
}
}

Output​

true
true
false
true

Lab560.java

classLab560{
publicstaticvoidmain(Stringargs[]){
Aaobj=newD();

System.out.println(aobjinstanceofE);
}
}

Notes​

  • Compile-time error.
  • A and E are incompatible types.

Using == Operator with Reference Type

To compare, both references should be comparable.


Lab561.java

classLab561{
publicstaticvoidmain(Stringargs[]){
Aaob=newD();
Bbob=newB();

Ddob=newD();
Ccob=newC();

System.out.println(aob==dob);
System.out.println(aob==bob);
System.out.println(aob==cob);
}
}

Output​

false
false
false

Notes​

  • Different objects have different memory addresses.
  • Comparison is allowed because the reference types are related/comparable.

Lab562.java

classLab562{
publicstaticvoidmain(Stringargs[]){
Aaob=newD();
Eeob=newE();

System.out.println(aob==eob);

Bbob=newB();
Ccob=newC();

System.out.println(bob==cob);
}
}

Notes​

  • Compile-time error.
  • References are not comparable because classes are unrelated.

Using Array with User Defined Type


Inter1.java

interfaceInter1extendsObject { }

Notes​

  • Every interface internally extends Object.

Lab563.java

interfaceInter1{
voidm1();
}

classHelloimplementsInter1{

publicvoidm1(){
System.out.println("Hello -> m1");
}

publicvoidm2(){
System.out.println("Hello -> m2");
}
}

classLab563{
publicstaticvoidmain(Stringargs[]){
Inter1in1=newHello();

in1.m1();
}
}

Notes​

  • m1() can be accessed.
  • m2() cannot be accessed because it is not part of the interface reference type.

Lab564.java

interfaceInter1{
voidm1();
}

classHelloimplementsInter1{

publicvoidm1(){
System.out.println("Hello -> m1");
}

publicvoidm2(){
System.out.println("Hello -> m2");
}
}

classLab564{
publicstaticvoidmain(Stringargs[]){
Inter1in1=newHello();

in1.m2();
}
}

Notes​

  • Compile-time error.
  • Interface reference cannot access methods not declared in the interface.

Lab565.java

interfaceInter1{
voidm1();
}

classHelloimplementsInter1{

publicvoidm1(){
System.out.println("Hello -> m1");
}

publicvoidm2(){
System.out.println("Hello -> m2");
}
}

classLab565{
publicstaticvoidmain(Stringargs[]){
Inter1in1=newHello();

Objectobj=in1;

System.out.println(in1.toString());
}
}

Notes​

  • Interface references can access methods inherited from Object.
  • toString() is available because every interface indirectly relates to Object.

Lab566.java

interfaceInter1{ }

classAimplementsInter1{ }

classBextendsA{ }

classCextendsA{ }

classLab566{
publicstaticvoidmain(Stringargs[]){

Inter1arr[]=newInter1[3];

arr[0]=newA();
arr[1]=newB();
arr[2]=newC();

for(Inter1r :arr){
System.out.println(r);
}
}
}

Notes​

  • Interface array can store objects of implementing classes and subclasses.

Lab567.java

interfaceInter1{ }

classAimplementsInter1{ }

classBextendsA{ }

classCextendsA{ }

classLab567{
publicstaticvoidmain(Stringargs[]){

Inter1arr[]=newA[3];

arr[0]=newA();
arr[1]=newB();
arr[2]=newC();

for(inti=0;i<arr.length;i++){
System.out.println(arr[i]);
}
}
}

Notes​

  • Array type A[] can store A, B, and C objects because B and C extend A.

Lab568.java

interfaceInter1{ }

classAimplementsInter1{ }

classBextendsA{ }

classCextendsA{ }

classLab568{
publicstaticvoidmain(Stringargs[]){

Inter1arr[]=null;

arr=newA[3];

arr[0]=newA();

for(inti=0;i<arr.length;i++){
System.out.println(arr[i]);
}
}
}

Notes​

  • Interface reference can refer to an array object of implementing class type.

Lab569.java

interfaceInter1{ }

classAimplementsInter1{ }

classBextendsA{ }

classCextendsA{ }

classLab569{
publicstaticvoidmain(Stringargs[]){

Inter1arr[]=null;

arr=newB[3];

arr[0]=newB();
arr[1]=newB();
arr[2]=newB();

for(inti=0;i<arr.length;i++){
System.out.println(arr[i]);
}
}
}

Notes​

  • Inter1 reference array can refer to subclass array objects.

Lab570.java

interfaceInter1{ }

classAimplementsInter1{ }

classBextendsA{ }

classCextendsA{ }

classLab570{
publicstaticvoidmain(Stringargs[]){

Inter1arr[]=newB[3];

arr[0]=newB();
arr[1]=newB();
arr[2]=newC();

for(inti=0;i<arr.length;i++){
System.out.println(arr[i]);
}
}
}

Notes​

  • Runtime error occurs.
  • Because array actual type is B[].
  • C object cannot be stored inside B[].