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[].