Natürlich,Geht sowas
public static void m(Object o) {
}
public static void main(String[] args) {
Runnable r = null;
Supplier<String> s = null;
m(r);
m(s);
}
Man kann prüfen, on ein Super-Interface mit @FunctionalInterface annotiert und ein "SAM-type" istEs gibt allerdings keinerlei Möglichkeit herauszufinden ob o ein Funktionales Interface is.
Dann muss es trotzdem ein SAM-Type sein.ja und wenn es nicht annotiert is?
Und wie kannst du daraufhin prüfen?Dann muss es trotzdem ein SAM-Type sein.
Es darf nur eine Instanz-Methode geben, die abstrakt ist (Single-Abstract-Method-Type), also müssen alle bis auf eine default, private, oder static sein.Und wie kannst du daraufhin prüfen?
public static boolean test(Class<?> clazz) {
if (!clazz.isInterface()) {
return false;
}
return Arrays.stream(clazz.getMethods())
.filter(not(Method::isDefault))
.filter(not(method -> Modifier.isStatic(method.getModifiers())))
.count() == 1;
}
public static void main(String[] args) {
System.out.println("Function: "+test(Function.class));
System.out.println("Runnable: "+test(Runnable.class));
System.out.println("List: "+test(List.class));
}
Function: true
Runnable: true
List: false
private static class Toll {
public static void toll() {
}
}
public static boolean m(Object o) {
return Arrays.stream(o.getClass().getDeclaredMethods()).filter(Predicate.not(Method::isDefault))
.filter(Predicate.not(method -> Modifier.isStatic(method.getModifiers()))).count() == 1;
}
public static void main(String[] args) {
Runnable r = new Runnable() {
@Override
public void run() {
}
};
Supplier<String> s = new Supplier<String>() {
@Override
public String get() {
return null;
}
};
System.out.println(m(r));
System.out.println(m(s));
}
Das mein Code eine Antwort auf die Frage war, wie man testet, ob ein Interface (=Class) ein SAM-Type ist, ist dir schon bewusst?Ein einfaches Nein auf eine Frage eines TE ist für dich nicht akzeptierbar oder?
Natürlich ist nicht nach einer Methode gefragt die ein Class<?> bekommt.
Danach hat der TE aber nicht gefragt.Das mein Code eine Antwort auf die Frage war, wie man testet, ob ein Interface (=Class) ein SAM-Type ist, ist dir schon bewusst?
Ich dachte du bist so gut, und dann bekommst du das nicht selber hin?Dann schreibe doch eine Methode, die prüft, ob o ein funktionales Interface ist...
Wenn das nicht möglich ist, ist meine Antwort auch nicht falsch.
(int i) -> i > 42
...import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.*;
import java.util.function.*;
import static java.util.function.Predicate.*;
public class SamTest implements Predicate<Object> {
public boolean test(Object o) {
return getParentClasses(o.getClass()).stream().anyMatch(c -> test(c));
}
private static Set<Class<?>> getParentClasses(Class<?> clazz) {
Set<Class<?>> classes = new HashSet<>();
Queue<Class<?>> toDo = new ArrayDeque<>();
toDo.add(clazz);
do {
Class<?> next = toDo.remove();
if (classes.contains(next)) {
continue;
}
classes.add(next);
Collections.addAll(toDo, next.getInterfaces());
if (next.getSuperclass() != null) { toDo.add(next.getSuperclass()); }
} while (!toDo.isEmpty());
return classes;
}
public static boolean test(Class<?> clazz) {
if (!clazz.isInterface()) {
return false;
}
return Arrays.stream(clazz.getMethods())
.filter(not(Method::isDefault))
.filter(not(method -> Modifier.isStatic(method.getModifiers())))
.count() == 1;
}
public static void main(String[] args) {
Predicate<Object> samTest = new SamTest();
Runnable r = new Runnable() {
@Override
public void run() {
}
};
System.out.println("new Runnable(): " + samTest.test(r));
System.out.println("new ArrayList(): " + samTest.test(new ArrayList<>()));
System.out.println("new Object(): " + samTest.test(new Object()));
}
}
Supplier<String> sup = () -> "greeting from supplier";
Class<?>[] interfaces = sup.getClass().getInterfaces();
for (Class<?> intrface : interfaces) {
System.out.println(intrface);
Annotation[] annotations = intrface.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println("\t" + annotation);
}
}
Nein, mit @FunctionalInterface kann man entsprechende Interfaces anmontieren (und auch nur solche), es ist aber kein Muss. Closeable zB ist ein SAM-Type ohne Annotation.Ist nicht jedes @java.lang.FunctionalInterface() ein SAM aber nicht jedes SAM ein @java.lang.FunctionalInterface() ?
Dürfte an den Grenzen der Typeinference liegen, es ist halt nicht klar, was für ein Typ das sein soll - kann hab Runnable oder Closeable sein.Apropos, wenn ich "Object o" als Parameter nehme gehen der direkte Aufruf ueber Method-Referenzen nicht mehr.
// geht nicht
main.method(main::someMethod)
// geht
Runnable r = main::someMethod;
main.method(r);
Kommt mir irgendwie komisch vor, dass die Methoden-Referenz main::someMethod nur "Sinn" macht wenn eine main.method(Runnable r) existiert. Ein main.method(Object o) fuehrt zum Compilerfehler. Irgendwie sind Method-References weird.
Ja, so könnte man auf die Annotation prüfen (wobei du alle interfaces rekursiv durchlaufen müsstest).Java:Supplier<String> sup = () -> "greeting from supplier"; Class<?>[] interfaces = sup.getClass().getInterfaces(); for (Class<?> intrface : interfaces) { System.out.println(intrface); Annotation[] annotations = intrface.getAnnotations(); for (Annotation annotation : annotations) { System.out.println("\t" + annotation); } }
Hm, sieht für mich ungenügend aus... vielleicht geht das auch nicht.... achja das hatte ich ja im ersten Beitrag geschrieben.Ich dachte du bist so gut, und dann bekommst du das nicht selber hin
Für welchen Fall klappt es denn nicht?Hm, sieht für mich ungenügend aus... vielleicht geht das auch nicht.... achja das hatte ich ja im ersten Beitrag geschrieben.