2011-11-21 5 views
10

Prendere il seguente test:Posso disambigare forzatamente i metodi di overload chiamati da Rhino?

public static class Scripted { 
    public void setThing(List<?> list) { 
     System.out.println("Set via list"); 
    } 

    public void setThing(Object[] array) { 
     System.out.println("Set array"); 
    } 
} 

@Test 
public void testScripting() throws Exception { 
    ScriptEngine engine = new ScriptEngineManager().getEngineByExtension("js"); 
    engine.getContext().setAttribute("s", new Scripted(), ScriptContext.ENGINE_SCOPE); 
    engine.eval("s.thing = Array(1, 2, 3);"); 
} 

Con la versione di trasporto di Rhino con Java 7, se si esegue questo, si otterrà un'eccezione in questo modo:

javax.script.ScriptException: sun.org.mozilla.javascript.internal.EvaluatorException: The choice of Java constructor setThing matching JavaScript argument types (object) is ambiguous; candidate constructors are: 
    void setThing(java.util.List) 
    void setThing(java.lang.Object[]) (<Unknown source>#1) in <Unknown source> at line number 1 

L'esistenza Object[] sovraccarico nel il primo posto è perché la versione precedente di Rhino non sarebbe convertire automaticamente gli array a List, ma sarebbe convertirli in Object[].

Se questo fosse un progetto personale questo è dove vorrei solo eliminare il Object[] sovraccarico. Il problema è che questa è un'API pubblica e potrebbe esserci qualcuno che lo chiama in questo momento. Vorrei ancora aggiornare a Java 7, ma vorrei evitare di sconvolgere gli utenti JavaScript o le persone che utilizzano la versione di array del metodo.

C'è un modo per nascondere i Object[] metodi di overload da Rhino, mentre altri sarebbe ancora in grado di chiamarli?

risposta

10

Anche se non è molto elegante c'è un modo di specificamente chiamare un metodo Java sovraccarico. È definito nell'ultima sezione della specifica Java Method Overloading and LiveConnect 3. Fondamentalmente si utilizza l'intera firma del metodo che si desidera chiamare come viene visualizzato nel messaggio di errore, utilizzando la notazione delle parentesi quadre. Nel tuo caso il seguente dovrebbe funzionare:

s["setThing(java.util.List)"](Array(1, 2, 3)); 

È un po 'un peccato che il cambiamento che abbiamo fatto con gli array JavaScript attuazione java.util.List rompe codice esistente. Forse sarebbe meglio sceglierne uno nel caso ci fossero più metodi di corrispondenza.

+0

Sono d'accordo ... Sarebbe stato meglio se appena chiamato l'elenco una senza fallire in questo modo. Ma Java 7 ha rotto parecchie altre cose nella nostra applicazione, questo è solo uno dei tanti (gli altri, come i cambiamenti di Locale, sono tutti risolti). – Trejkaz