프로그래밍 언어로:무엇을 가장 우아한 방법을 정의 콜백에서 Java?
문제
이 책에서'코드를 완료하는'저자에 대해 이야기한 프로그래밍 로 언어(대신 프로그래밍 언어에서).그 뜻은,당신이하지 않아야에 자신을 제한으로 제한의 선택된 프로그래밍 언어입니다.
콜백은 자주 사용되는 기능입니다.내가 관심있:무엇을 가장 우아한 방법으로 프로그램을 콜백으로 java 언어?
해결책
이 기사를 확인하십시오.
http://www.onjava.com/pub/a/onjava/2003/05/21/delegates.html
콜백은 본질적으로 특별한 경우 OD 대의원이며 (C#의대로),이 기사는 Java에서 C# Delegate와 유사한 것을 구현합니다.
다른 팁
Java는 모든 종류의 상황에 모든 종류의 콜백을 사용합니다. AWT 청취자의 가장 오래된 시절부터 Java는 콜백에 관한 것입니다.
Java 콜백에는 두 가지 기본 "맛"이 있습니다. 첫 번째는 구현 인터페이스 방법입니다.
public class MyThing implements StateChangeListener {
//this method is declared in StateChangeListener
public void stateChanged() {
System.out.println("Callback called!");
}
public MyThing() {
//Here we declare ourselves as a listener, which will eventually
//lead to the stateChanged method being called.
SomeLibraryICareAbout.addListener(this);
}
}
Java 콜백의 두 번째 맛은 익명의 내부 클래스입니다.
public class MyThing {
public MyThing() {
//Here we declare ourselves as a listener, which will eventually
//lead to the stateChanged method being called.
SomeLibraryICareAbout.addListener( new StateChangeListener() {
//this method is declared in StateChangeListener
public void stateChanged() {
System.out.println("Callback called!");
}
});
}
}
반사 사용, 별도의 이벤트 처리 클래스 사용 및 어댑터 패턴을 포함한 다른 방법도 있습니다.
Java의 기능 포인터/대표가없는 상태에서 내가 본 가장 일반적인 방법은 기능을 사용하는 것입니다.
기본적으로 단일 메소드가있는 인터페이스를 정의하고 인스턴스를 콜백으로 사용하십시오.
public interface Callback<T,V>{
public T invoke(V context);
}
C/C ++ 또는 C# 등가보다 더 많은 장점이지만 작동하지만 작동합니다. 표준 라이브러리 에서이 패턴의 예는 비교기 인터페이스입니다.
불행히도 Java에서는 기능이 일류 객체가 아닙니다. 당신이 할 수있는 최선은 인터페이스를 사용하는 것입니다.
public interface MyCallback
{
public void theCallback(int arg);
}
public class Sample
{
public static void takesACallback(MyCallback callback)
{
...
callback.theCallback(arg);
}
}
public class Sample2
{
public static void main(String[] args)
{
Sample.takesACallback(new MyCallback()
{
void theCallback(int arg)
{
// do a little dance
}
});
}
}
매우 일반적인 Call Back Construction은 Swing의 이벤트 핸들러입니다. ActionListeners는 아마도 가장 간단합니다.
살펴보십시오 http://java.sun.com/docs/books/tutorial/uiswing/events/actionlistener.html
귀하는 종종 적절한 인터페이스를 구현하는 익명 클래스의 인스턴스를 제공합니다.
listener = new ActionListener() {
public void actionPerformed(ActionEvent e) {
// do stuff...
}
};
그러면 듣는 사람에게 적절한 스윙 방법을 전달합니다.
나 개인적으로 자바 필사적으로 필요가 일부 형태의밈을 지원합니다.중간에,내가 구현한 반영이다-기초한 일반적 방법을 콜백에서 Java.그 에 게시된 내 웹사이트.
이 방식의 장점은 그것의 제네릭함.이 목표를 작성할 수 있 API 같이 파일 시스템을 걷는 트리없이 인터페이스를 정의하려면 각 시간에,대신 지정하는 방법에 코드를 사용하는 API 를 수행합니다.
예를 들어,걷는 파일 시스템을 프로세스는 각 파일:
프로세스는 디렉토리 트리 API
/**
* Process a directory using callbacks. To interrupt, the callback must throw an (unchecked) exception.
* Subdirectories are processed only if the selector is null or selects the directories, and are done
* after the files in any given directory. When the callback is invoked for a directory, the file
* argument is null;
* <p>
* The callback signature is:
* <pre> void callback(File dir, File ent);</pre>
* <p>
* @return The number of files processed.
*/
static public int processDirectory(File dir, Callback cbk, FileSelector sel) {
return _processDirectory(dir,new Callback.WithParms(cbk,2),sel);
}
static private int _processDirectory(File dir, Callback.WithParms cbk, FileSelector sel) {
int cnt=0;
if(!dir.isDirectory()) {
if(sel==null || sel.accept(dir)) { cbk.invoke(dir.getParent(),dir); cnt++; }
}
else {
cbk.invoke(dir,(Object[])null);
File[] lst=(sel==null ? dir.listFiles() : dir.listFiles(sel));
if(lst!=null) {
for(int xa=0; xa<lst.length; xa++) {
File ent=lst[xa];
if(!ent.isDirectory()) {
cbk.invoke(dir,ent);
lst[xa]=null;
cnt++;
}
}
for(int xa=0; xa<lst.length; xa++) {
File ent=lst[xa];
if(ent!=null) { cnt+=_processDirectory(ent,cbk,sel); }
}
}
}
return cnt;
}
프로세스를 사용하여 디렉토리 API
위의 방법이 기록된 바 내가 지금 아주 쉽게 공정한 디렉토리를 위해 모든 작업은;검사,계산,목록,등등.와 사소한 변경을 콜백을 호출에 디렉토리를 전후에 내림차순으로 작업에 다음과 같이 파일/트리 삭제 수행할 수도 있습(추가 매개 변수가 필요한을 나타내는 전/후의 자연 invocation).
static private final Method COUNT =Callback.getMethod(Xxx.class,"callback_count",true,File.class,File.class);
...
IoUtil.processDirectory(root,new Callback(this,COUNT),selector);
...
private void callback_count(File dir, File fil) {
if(fil!=null) { // file is null for processing a directory
fileTotal++;
if(fil.length()>fileSizeLimit) {
throw new Abort("Failed","File size exceeds maximum of "+TextUtil.formatNumber(fileSizeLimit)+" bytes: "+fil);
}
}
progress("Counting",dir,fileTotal);
}