Da Java 8-Schnittstellen Standardmethoden haben können. mit Reflexion zum Beispiel auf einem Proxy- Ich weiß, wie die Methode explizit von der Implementierung Methode aufzurufen, das heißt (siehe Explicitly calling a default method in Java)Wie explizit die Standardmethode von einem dynamischen Proxy aufrufen?
Aber wie ich explizit die Standard-Methode aufrufen?
Beispiel:
interface ExampleMixin {
String getText();
default void printInfo(){
System.out.println(getText());
}
}
class Example {
public static void main(String... args) throws Exception {
Object target = new Object();
Map<String, BiFunction<Object, Object[], Object>> behavior = new HashMap<>();
ExampleMixin dynamic =
(ExampleMixin) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),new Class[]{ExampleMixin.class}, (Object proxy, Method method, Object[] arguments) -> {
//custom mixin behavior
if(behavior.containsKey(method.getName())) {
return behavior.get(method.getName()).apply(target, arguments);
//default mixin behavior
} else if (method.isDefault()) {
//this block throws java.lang.IllegalAccessException: no private access for invokespecial
return MethodHandles.lookup()
.in(method.getDeclaringClass())
.unreflectSpecial(method, method.getDeclaringClass())
.bindTo(target)
.invokeWithArguments();
//no mixin behavior
} else if (ExampleMixin.class == method.getDeclaringClass()) {
throw new UnsupportedOperationException(method.getName() + " is not supported");
//base class behavior
} else{
return method.invoke(target, arguments);
}
});
//define behavior for abstract method getText()
behavior.put("getText", (o, a) -> o.toString() + " myText");
System.out.println(dynamic.getClass());
System.out.println(dynamic.toString());
System.out.println(dynamic.getText());
//print info should by default implementation
dynamic.printInfo();
}
}
Edit: Ich weiß, eine ähnliche Frage in How do I invoke Java 8 default methods refletively gefragt wurde, aber das hat mein Problem aus zwei Gründen nicht gelöst:
- das Problem beschrieben in dieser Frage auf, wie man es über Reflexion im Allgemeinen - so dass keine Unterscheidung zwischen d Efault und Override-Methode wurde gemacht - und das ist einfach, Sie brauchen nur eine Instanz.
- eine der Antworten - mit Methode behandelt - funktioniert nur mit bösen Hack (imho) wie Ändern von Zugriffsmodifizierer auf Felder der Suchklasse, die die gleiche Kategorie von "Lösungen" ist wie folgt: Change private static final field using Java reflection: es ist gut zu weiß, es ist möglich, aber ich würde es nicht in der Produktion verwenden - Ich bin auf der Suche nach einem "offiziellen" Weg, es zu tun.
Die IllegalAccessException
geworfen in unreflectSpecial
Caused by: java.lang.IllegalAccessException: no private access for invokespecial: interface example.ExampleMixin, from example.ExampleMixin/package
at java.lang.invoke.MemberName.makeAccessException(MemberName.java:852)
at java.lang.invoke.MethodHandles$Lookup.checkSpecialCaller(MethodHandles.java:1568)
at java.lang.invoke.MethodHandles$Lookup.unreflectSpecial(MethodHandles.java:1227)
at example.Example.lambda$main$0(Example.java:30)
at example.Example$$Lambda$1/1342443276.invoke(Unknown Source)
Ist es nicht ein Duplikat dieser http://stackoverflow.com/questions/22614746/how-do-i-invoke-java-8-default-methods-refletively –
„* Ich bin auf der Suche für einen "offiziellen" Weg, es zu tun * "Ich mag mich irren, aber ich fürchte, dass Sie offiziell nicht in der Lage sein sollten, die Methode vom Supertyp aufzurufen, wenn Ihr Subtyp es überschrieben hat. Nehmen wir an, Ihr Supertyp hat eine 'acceptSquare' Methode, die beliebige Squares akzeptieren kann, aber Ihr Subtyp ist * spezialisiert * nur mit roten Quadraten, also überschreibt er es entsprechend um Test für Farbe hinzuzufügen (danach ruft er' super.addSquare' auf). Es könnte also eine große Sicherheitslücke sein, jemandem zu erlauben, von außerhalb der Implementierung von einem Supertyp (sogar durch Reflektion) einer solchen Methode aus aufzurufen. – Pshemo
Wie wäre es mit Mixins - Hinzufügen von Funktionalität zu einer bestehenden Klasse mit einem dynamischen Proxy? d. h. ich habe eine Instanz und möchte zusätzliche Funktionalität hinzufügen, indem ich Interfaces mit Standardmethoden zur Laufzeit zur Instanz hinzufüge. Es muss einen Weg geben –