几天前我接受了一次采访,并提出了这样一个问题。
问:反转链表。下面的代码给出了:
public class ReverseList {
interface NodeList {
int getItem();
NodeList nextNode();
}
void reverse(NodeList node) {
}
public static void main(String[] args) {
}
}
我很困惑,因为我不知道接口对象可以用作方法参数。面试官解释了一下,但我仍然不确定。有人可以启发我吗?
答案 0 :(得分:57)
这实际上是使用界面最常用和最有用的方法之一。接口定义了一个契约,你的代码可以与任何实现接口的类一起工作,而不必知道具体的类 - 它甚至可以用于编写代码时尚不存在的类。
Java标准API中有许多示例,尤其是在集合框架中。例如,Collections.sort()可以对实现List
接口的任何内容进行排序(不只是ArrayList
或LinkedList
,尽管实现您自己的List
并不常见)且其内容实现Comparable
接口(不仅仅是String
或数字包装类 - 并且为此目的拥有自己的类实现Comparable
相当通用)。
答案 1 :(得分:24)
这不是传递给方法的接口“对象”,仍然只是一个常规对象。这只是一种说法“此参数将接受支持此接口的任何对象”。它等同于接受基类类型的某个对象,即使你传入一个子类。
答案 2 :(得分:8)
这称为接口编程。您不需要编写特定的节点列表实现类,而是编写所有这些实现所实现的接口。
这样,如果有人在您编写了反向方法之后编写了一个新的,更好的NodeList
实现,并且您不必为{{1}的每个新实现调整代码,那么您的代码仍然有效。 }。
答案 3 :(得分:6)
参数需要一个对象,该类实现一个接口(参数)。
在伪 Java代码:
void reverse(NodeList node) {
// your code
}
等于:
reverse(x) {
if(x == null || x instanceof NodeList) {
// your code
}else throw new RuntimeException("Some sort of error.");
}
请注意;在此处阅读有关接口的更多信息:http://java.sun.com/docs/books/tutorial/java/IandI/interfaceAsType.html
答案 4 :(得分:2)
在学习lambda的时候也有同样的困惑。 这段视频没有解释这个概念,但它是一个明确的方式,让您了解它如何在将界面作为参数传递方面发挥作用。
答案 5 :(得分:1)
使用接口IMHO的主要好处是能够轻松测试。假设您有一个名为PatientManager的接口。
您可以为可想象的事情编写特定的单元测试,例如“CachingPatientManager”或“LDAPPatientManager”,用例可能是无数的。
好处是因为接口编程变得高度可重用和可测试。
答案 6 :(得分:1)
您无法创建接口的实例(/对象)。 是的,您可以将Interface作为参数传递给函数。但问题似乎不完整。界面不是由任何类实现的。缺了点什么。如果您尝试运行此命令,编译器将不会显示任何错误。
但是,在reverse()方法中,您需要创建一个实现NodeList接口的类实例。我希望这是有道理的。
答案 7 :(得分:1)
这是一种可能的实施方式:
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());
}
}
节目输出:
Before reversal
1->2->3->null
After reversal
3->2->1->null
我很想知道这个问题是否可以通过使用匿名类来解决。有什么想法吗?