鉴于来自JNotify的以下示例,我在理解 implements 时遇到了一些麻烦。 class Listner
实现JNotifyListener的方法 - fileRenamed
,fileModified
等是否是有效的Java语法 - 但是将返回类型从void修改为Integer?
我想在JNotify之上编写一个Clojure库,并在未来使用Clojure代码块,直到Listener的一个方法返回。
class Listener implements JNotifyListener {
public void fileRenamed(int wd, String rootPath, String oldName,
String newName) {
print("renamed " + rootPath + " : " + oldName + " -> " + newName);
}
public void fileModified(int wd, String rootPath, String name) {
print("modified " + rootPath + " : " + name);
}
public void fileDeleted(int wd, String rootPath, String name) {
print("deleted " + rootPath + " : " + name);
}
public void fileCreated(int wd, String rootPath, String name) {
print("created " + rootPath + " : " + name);
}
void print(String msg) {
System.err.println(msg);
}
}
答案 0 :(得分:3)
没有。实现签名中的返回值类型必须与它实现的接口的返回值类型匹配,具有完全匹配或实现/扩展类型。
对评论的回应(不是原始问题)
interface I {
A foo();
}
class A {}
class B extends A {}
class C implements I {
public B foo() { return null; }
}
Java 6编译器接受上面的代码,这意味着返回值在覆盖时间是协变的,因此评论者是正确的,匹配不一定是准确的。
答案 1 :(得分:3)
回应OP澄清的意见:
是的,这是Observer模式的一个简单示例:
public interface JNotifyListener {
void fileRenamed(int wd, String rootPath, String oldName, String newName);
void fileModified(int wd, String rootPath, String name);
void fileDeleted(int wd, String rootPath, String name);
void fileCreated(int wd, String rootPath, String name);
}
public enum Type {
RENAMED,
MODIFIED,
DELETED,
CREATED;
}
public class FileChangeEvent {
final Type type;
final int wd;
final String rootPath;
final String name;
final String newName;
public FileChangeEvent(Type type, int wd, String rootPath, String name, String newName) {
this.type = type;
this.wd = wd;
this.rootPath = rootPath;
this.name = name;
this.newName = newName;
}
public FileChangeEvent(Type type, int wd, String rootPath, String name) {
this(type, wd, rootPath, name, null);
}
public int getWd() {
return wd;
}
public String getRootPath() {
return rootPath;
}
public String getName() {
return name;
}
public String getNewName() {
return newName;
}
}
public interface FileChangeEventListener {
void notify(FileChangeEvent fileChangeEvent);
}
public class FileChangeEventNotifyer implements JNotifyListener {
final Collection<FileChangeEventListener> listeners = new ConcurrentLinkedQueue<FileChangeEventListener>();
@Override
public void fileRenamed(int wd, String rootPath, String oldName, String newName) {
notifyAll(new FileChangeEvent(Type.RENAMED, wd, rootPath, oldName, newName));
}
@Override
public void fileModified(int wd, String rootPath, String name) {
notifyAll(new FileChangeEvent(Type.MODIFIED, wd, rootPath, name));
}
@Override
public void fileDeleted(int wd, String rootPath, String name) {
notifyAll(new FileChangeEvent(Type.DELETED, wd, rootPath, name));
}
@Override
public void fileCreated(int wd, String rootPath, String name) {
notifyAll(new FileChangeEvent(Type.CREATED, wd, rootPath, name));
}
private void notifyAll(final FileChangeEvent changeEvent) {
for (final FileChangeEventListener changeEventListener : listeners) {
changeEventListener.notify(changeEvent);
}
}
public void registerListener(final FileChangeEventListener eventListener) {
listeners.add(eventListener);
}
public void unregisterListener(final FileChangeEventListener eventListener) {
listeners.remove(eventListener);
}
}
您可以看到class
只需要实施FileChangeEventListener
并注明其对主FileChangeEventNotifyer
的兴趣。然后它将使用事件调用其notify
方法。
这里有一些常见的陷阱。一个是该实现不使用synchronized
,因此如果一个类在事件发生时被注册,则它可能会错过通知。优点是这是非阻塞的。因此,您需要确定是否更喜欢使用非阻塞集合或阻止集合。
此外,您需要确保之后注册的任何已注册的侦听器都未注册,否则它们会堆积起来并最终导致内存泄漏。
我已将其实现为具有FileChangeEvent
的单个Type
- 显然您可以拥有父FileChangeEvent
类,然后使用类的子类扩展它。这又取决于你的需求。
无论如何,这应该让你开始。
答案 2 :(得分:0)
从Clojure方面考虑使用promise / deliver而不是future。然后,监听器中的方法可以实现承诺。 http://clojuredocs.org/clojure_core/clojure.core/promise
如果这是一个库,最好传递一个函数而不是使用future或promise。这将允许库的用户传入他们自己的闭包,而不必引入另一个线程更改。