それも可能ですか?
回答:
匿名関数を意味し、Java 8より前のバージョンのJavaを使用している場合、一言で言えば、いいえ。(Java 8+を使用している場合はラムダ式について読んでください)
ただし、次のような関数を使用してインターフェイスを実装できます。
Comparator<String> c = new Comparator<String>() {
int compare(String s, String s2) { ... }
};
これを内部クラスで使用して、ほぼ匿名の関数を取得できます:)
これは匿名の内部クラスの例です。
System.out.println(new Object() {
@Override public String toString() {
return "Hello world!";
}
}); // prints "Hello world!"
これはそのままではあまり役に立ちませんが、匿名内部クラスのインスタンスextends Object
と@Override
そのtoString()
メソッドを作成する方法を示しています。
匿名の内部クラスは、interface
再利用性が低い(したがって、独自の名前付きクラスにリファクタリングする価値がない)を実装する必要がある場合に非常に便利です。有益な例はjava.util.Comparator<T>
、並べ替えにカスタムを使用することです。
にString[]
基づいてを並べ替える方法の例を次に示しますString.length()
。
import java.util.*;
//...
String[] arr = { "xxx", "cd", "ab", "z" };
Arrays.sort(arr, new Comparator<String>() {
@Override public int compare(String s1, String s2) {
return s1.length() - s2.length();
}
});
System.out.println(Arrays.toString(arr));
// prints "[z, cd, ab, xxx]"
ここで使用されている減算による比較のトリックに注意してください。このテクニックは一般的に壊れていると言うべきです:それがオーバーフローしないことを保証できる場合にのみ適用できます(String
長さの場合など)。
EventListener
、平均的なSwingアプリケーションの(サブ)実装として見つけることができます。
Linked
サイドバーを追加したので、それを利用するために最善を尽くしています。
Java 8のラムダ式の導入により、匿名メソッドを使用できるようになりました。
クラスがAlpha
ありAlpha
、特定の条件でs をフィルタリングしたいとします。これを行うには、を使用できますPredicate<Alpha>
。これは、test
を受け入れてAlpha
を返すメソッドを持つ機能的なインターフェースboolean
です。
filterメソッドに次のシグネチャがあると仮定します。
List<Alpha> filter(Predicate<Alpha> filterPredicate)
古い匿名クラスソリューションでは、次のようなものが必要になります。
filter(new Predicate<Alpha>() {
boolean test(Alpha alpha) {
return alpha.centauri > 1;
}
});
Java 8ラムダを使用すると、次のことができます。
filter(alpha -> alpha.centauri > 1);
詳細については、ラムダ式のチュートリアルをご覧ください。
既存のタイプのインターフェースを実装または拡張する匿名の内部クラスは、他の回答でも行われていますが、複数のメソッドを実装できることは注目に値します(多くの場合、JavaBeanスタイルのイベントなど)。
少し認識されている機能は、匿名の内部クラスには名前がありませんが、型はあります。新しいメソッドをインターフェースに追加できます。これらのメソッドは、限られた場合にのみ呼び出すことができます。主に直接new
式自体とクラス内(インスタンス初期化子を含む)。初心者を混乱させるかもしれませんが、再帰には「興味深い」場合があります。
private static String pretty(Node node) {
return "Node: " + new Object() {
String print(Node cur) {
return cur.isTerminal() ?
cur.name() :
("("+print(cur.left())+":"+print(cur.right())+")");
}
}.print(node);
}
(私はもともとメソッドではnode
なく、これを使用してこれを書きcur
ましたprint
。「暗黙的にfinal
」ローカルをキャプチャするためにNOと言いますか?)
node
final
ここで宣言する必要があります。
cur
。
"Node" +
2番目のメソッドを必要とするのに少し関係がないことに注意してください)。/私には名前がありません。おそらく、私はネーミング「ポール」(CW)の質問を作成し、忘却に反対投票することができます。
はい。バージョン8である最新のJavaを使用している場合は可能です。Java8を使用すると、以前のバージョンでは不可能だった匿名関数を定義できます。
Javaドキュメントから例を取り、匿名関数、クラスを宣言する方法を知ってみましょう
次の例、HelloWorldAnonymousClassesは、ローカル変数frenchGreetingおよびspanishGreetingの初期化ステートメントで匿名クラスを使用しますが、変数englishGreetingの初期化にはローカルクラスを使用します。
public class HelloWorldAnonymousClasses {
interface HelloWorld {
public void greet();
public void greetSomeone(String someone);
}
public void sayHello() {
class EnglishGreeting implements HelloWorld {
String name = "world";
public void greet() {
greetSomeone("world");
}
public void greetSomeone(String someone) {
name = someone;
System.out.println("Hello " + name);
}
}
HelloWorld englishGreeting = new EnglishGreeting();
HelloWorld frenchGreeting = new HelloWorld() {
String name = "tout le monde";
public void greet() {
greetSomeone("tout le monde");
}
public void greetSomeone(String someone) {
name = someone;
System.out.println("Salut " + name);
}
};
HelloWorld spanishGreeting = new HelloWorld() {
String name = "mundo";
public void greet() {
greetSomeone("mundo");
}
public void greetSomeone(String someone) {
name = someone;
System.out.println("Hola, " + name);
}
};
englishGreeting.greet();
frenchGreeting.greetSomeone("Fred");
spanishGreeting.greet();
}
public static void main(String... args) {
HelloWorldAnonymousClasses myApp =
new HelloWorldAnonymousClasses();
myApp.sayHello();
}
}
匿名クラスの構文
frenchGreetingオブジェクトのインスタンス化を検討してください。
HelloWorld frenchGreeting = new HelloWorld() {
String name = "tout le monde";
public void greet() {
greetSomeone("tout le monde");
}
public void greetSomeone(String someone) {
name = someone;
System.out.println("Salut " + name);
}
};
匿名クラス式は、次のもので構成されています。
new
オペレータ実装するインターフェースまたは拡張するクラスの名前。この例では、匿名クラスがインターフェイスHelloWorldを実装しています。
通常のクラスインスタンス作成式と同様に、コンストラクターへの引数を含む括弧。注:インターフェースを実装する場合、コンストラクターはないため、この例のように、空の括弧のペアを使用します。
クラス宣言本体である本体。具体的には、本文ではメソッド宣言は許可されていますが、ステートメントは許可されていません。