interface as a method parameter in Java
Asked Answered
C

9

73

I had an interview days ago and was thrown a question like this.

Q: Reverse a linked list. Following code is given:

public class ReverseList { 
    interface NodeList {
        int getItem();
        NodeList nextNode();
    }
    void reverse(NodeList node) {

    }
    public static void main(String[] args) {

    }
}

I was confused because I did not know an interface object could be used as a method parameter. The interviewer explained a little bit but I am still not sure about this. Could somebody enlighten me?

Charliecharline answered 4/4, 2010 at 18:21 Comment(1)
Per Java Champion Ben Evans at Red Hat, "Java permits only two sorts of values: primitive types and object references," and since interfaces are not primitives, and because reverse() accepts a formal parameter (from the caller's formal argument) of an interface type NodeList, then reverse() accepts an object reference, not an interface. You can confirm this by looking at the bytecode, where you would see invokeinterface as part of a vtable parsing, which implements dynamic method dispatch. See blogs.oracle.com/javamagazine/post/…Glenda
G
82

This is in fact one of the most common and useful ways to use an interface. The interface defines a contract, and your code can work with any class that implements the interface, without having to know the concrete class - it can even work with classes that didn't exist yet when the code was written.

There are many examples in the Java standard API, especially in the collections framework. For example, Collections.sort() can sort anything that implements the List interface (not just ArrayList or LinkedList, though implementing your own List is uncommon) and whose contents implement the Comparable interface (not just String or the numerical wrapper classes - and having your own class implement Comparable for that purpose is quite common).

Groh answered 4/4, 2010 at 18:28 Comment(1)
Thanks Mike! List example is really instructive and easy to understand.Charliecharline
O
44

It's not the interface "object" being passed to the method, still just a regular object. It's just a way of saying "this parameter will accept any object that supports this interface". It's equivalent to accepting some object of a base class type, even if you're passing in a subclass.

Outland answered 4/4, 2010 at 18:28 Comment(1)
Great, helped !! :DCaliban
H
11

This is called programming to interfaces. You don't code to a specific implementation class of node lists but to the interface implemented by all those implementations.

That way your code will still work if someone writes a new and much better implementation of NodeList after you wrote your reverse method and you don't have to adapt your code for each new implementation of NodeList.

Harmonic answered 4/4, 2010 at 18:31 Comment(1)
Inside reverse() we can not work directly on node to which we must rather assign an instance of a class that implements NodeList. After all, we need to work on a concrete object.Saturated
F
7

The argument needs an object, which class implements an interface (the parameter).

In pseudo Java the code:

void reverse(NodeList node) {
    // your code
}

is equal to:

reverse(x) {
    if(x == null || x instanceof NodeList) {
         // your code
    }else throw new RuntimeException("Some sort of error.");
}

Note; read more on Interfaces here: http://java.sun.com/docs/books/tutorial/java/IandI/interfaceAsType.html

Fluoride answered 4/4, 2010 at 18:27 Comment(3)
<pedant> The parameter is an interface type, the argument is an object </pedant>Dermal
And to be REALLY much a pedent. The argument is a reference to an object :}Copyboy
Thanks for the link to Sun tutorial!Charliecharline
S
3

This is one possible implementation:

public class ReverseList { 
interface NodeList {
    int getItem();
    NodeList nextNode();
}

static class Node implements NodeList {
    private int item;
    private Node next;

    @Override
    public int getItem() {
        return item;
    }

    public void setItem(int si) {
        item = si;
    }

    @Override
    public NodeList nextNode() {
        return this.next;
    }

    public void setNext(Node n) {this.next=n;}

}

Node reverse(NodeList head) {
    Node node = (Node) head;
    Node previous = null;
    while(node.nextNode() !=null) {
        Node tempNext = (Node) node.nextNode();
        node.setNext(previous);
        previous = node;
        node = tempNext;
    }
    node.setNext(previous);
    return node;

}
public static void main(String[] args) {
    //Initialization block
    ReverseList rl = new ReverseList();
    Node n1= new Node(); n1.setItem(1);
    Node n2=new Node(); n2.setItem(2);
    Node n3 =new Node(); n3.setItem(3);
    n1.setNext(n2); n2.setNext(n3); n3.setNext(null);

    //Reversing the list
    System.out.println("Before reversal");      
    System.out.println(n1.getItem() +"->" 
                    + n1.nextNode().getItem() + "->"
                    + n1.nextNode().nextNode().getItem() + "->"
                    +n1.nextNode().nextNode().nextNode());


    rl.reverse(n1);

    System.out.println("\nAfter reversal");
    System.out.println(n3.getItem() +"->" 
            + n3.nextNode().getItem() + "->"
            + n3.nextNode().nextNode().getItem() + "->"
            +n3.nextNode().nextNode().nextNode());
        }
}

Program output:

Before reversal
1->2->3->null

After reversal
3->2->1->null

I am very curious to know if this problem can be solved by using an anonymous class. Any ideas?

Silvana answered 19/9, 2016 at 1:56 Comment(0)
I
3

Had this same confusion while learning lambda stuff. This video didnt explain the concept, but it's a clear way for you to see how it works in terms of passing an interface as a parameter.

https://www.youtube.com/watch?v=mk3erzL70yM

Immersion answered 24/1, 2018 at 6:41 Comment(0)
Z
1

The major benefit of using interfaces, IMHO, is being able to test easily. Suppose you have an interface called, PatientManager.

You can write specific unit tests for imaginable things like "CachingPatientManager" or "LDAPPatientManager", the use case could be myriad.

The benefit is because the programming to interface becomes highly reusable and testable.

Zoolatry answered 12/4, 2015 at 3:17 Comment(0)
P
1

You cannot create an instance (/object ) of an Interface. Yes, you can pass Interface as a parameter in the function. But the question seems incomplete. Interface isn't implemented by any class. Something is missing. If you try to run this, compiler will not show any error.

But, in the reverse() method you need to create an instance of class that implements NodeList interface. I hope this makes sense.

Pantisocracy answered 14/2, 2016 at 1:29 Comment(0)
I
0

Maybe it's too late, but still i leave my answer here as I found your question helpful.


When an interface is used as the parameter type of a method, it means that this method accepts any object that contains implementations of the interface.

There is a good example for this usage, and it's when you try to pass an ArrayList to a method. As you know, you can pass your ArrayList as List as below:

public int getListSize(List<String> myList){
   return myList.size();
}

and then, this will give you the flexibility to pass any object which implements List methods. For example, you can do:

List<String> myList1 = new ArrayList<>();
List<String> myList2 = new LinkedList<>();
List<String> myList3 = new Vector<>();

int size1 = getListSize(myList1); // Valid, myList1 is an ArrayList
int size2 = getListSize(myList2); // Valid, myList2 is a LinkedList
int size3 = getListSize(myList3); // Valid, myList3 is a Vector
Ier answered 1/10, 2023 at 8:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.