interface作为Java中的方法参数

时间:2022-03-31 09:42:15

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?

我很困惑,因为我不知道接口对象可以用作方法参数。面试官解释了一下,但我仍然不确定。有人可以开导我吗?

8 个解决方案

#1


52  

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).

Java标准API中有许多示例,尤其是在集合框架中。例如,Collections.sort()可以对实现List接口的任何内容进行排序(不仅仅是ArrayList或LinkedList,尽管实现自己的List是不常见的)并且其内容实现了Comparable接口(不仅仅是String或数字包装类 - 并且具有你自己的类实现为此目的可比较是很常见的。

#2


19  

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.

它不是传递给方法的接口“对象”,仍然只是一个常规对象。这只是一种说法“此参数将接受支持此接口的任何对象”。它等同于接受基类类型的某个对象,即使您传入的是子类。

#3


8  

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.

这样,如果有人在编写反向方法后编写了一个新的更好的NodeList实现,并且您不必为NodeList的每个新实现调整代码,那么代码仍然可以工作。

#4


6  

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

参数需要一个对象,该类实现一个接口(参数)。

In pseudo Java the code:

在伪Java中代码:

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

注意;在此处阅读有关接口的更多信息:http://java.sun.com/docs/books/tutorial/java/IandI/interfaceAsType.html

#5


1  

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

使用接口IMHO的主要好处是能够轻松测试。假设您有一个名为PatientManager的接口。

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

您可以为可想象的事情编写特定的单元测试,例如“CachingPatientManager”或“LDAPPatientManager”,用例可能是无数的。

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

好处是因为接口编程变得高度可重用和可测试。

#6


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.

您无法创建接口的实例(/对象)。是的,您可以将Interface作为参数传递给函数。但问题似乎不完整。任何类都不实现接口。缺了点什么。如果您尝试运行此命令,编译器将不会显示任何错误。

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

但是,在reverse()方法中,您需要创建一个实现NodeList接口的类实例。我希望这是有道理的。

#7


1  

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?

我很想知道这个问题是否可以通过使用匿名类来解决。有任何想法吗?

#8


1  

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.

在学习lambda的时候也有同样的困惑。这个视频没有解释这个概念,但是你可以清楚地看到它如何将接口作为参数传递。

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

#1


52  

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).

Java标准API中有许多示例,尤其是在集合框架中。例如,Collections.sort()可以对实现List接口的任何内容进行排序(不仅仅是ArrayList或LinkedList,尽管实现自己的List是不常见的)并且其内容实现了Comparable接口(不仅仅是String或数字包装类 - 并且具有你自己的类实现为此目的可比较是很常见的。

#2


19  

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.

它不是传递给方法的接口“对象”,仍然只是一个常规对象。这只是一种说法“此参数将接受支持此接口的任何对象”。它等同于接受基类类型的某个对象,即使您传入的是子类。

#3


8  

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.

这样,如果有人在编写反向方法后编写了一个新的更好的NodeList实现,并且您不必为NodeList的每个新实现调整代码,那么代码仍然可以工作。

#4


6  

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

参数需要一个对象,该类实现一个接口(参数)。

In pseudo Java the code:

在伪Java中代码:

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

注意;在此处阅读有关接口的更多信息:http://java.sun.com/docs/books/tutorial/java/IandI/interfaceAsType.html

#5


1  

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

使用接口IMHO的主要好处是能够轻松测试。假设您有一个名为PatientManager的接口。

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

您可以为可想象的事情编写特定的单元测试,例如“CachingPatientManager”或“LDAPPatientManager”,用例可能是无数的。

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

好处是因为接口编程变得高度可重用和可测试。

#6


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.

您无法创建接口的实例(/对象)。是的,您可以将Interface作为参数传递给函数。但问题似乎不完整。任何类都不实现接口。缺了点什么。如果您尝试运行此命令,编译器将不会显示任何错误。

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

但是,在reverse()方法中,您需要创建一个实现NodeList接口的类实例。我希望这是有道理的。

#7


1  

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?

我很想知道这个问题是否可以通过使用匿名类来解决。有任何想法吗?

#8


1  

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.

在学习lambda的时候也有同样的困惑。这个视频没有解释这个概念,但是你可以清楚地看到它如何将接口作为参数传递。

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