2011-11-21 6 views
10

Weźmy następujący test:Czy mogę wymuszać disambiguate overloaded metody zwane przez 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);"); 
} 

z wersją Rhino wysyłce z Java 7, jeśli uruchomić ten, dostaniesz wyjątek takiego:

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 

istnienia Object[] przeciążenie w pierwsze miejsce to, ponieważ poprzednia wersja Rhino nie automatycznie konwertuje tablic na List, ale to będzie przekształcić je na Object[].

Jeśli był to projekt osobisty, to właśnie tam po prostu usunąłbym przeciążenie Object[]. Problem polega na tym, że jest to publiczny interfejs API i teraz może być ktoś, kto tę metodę nazywa. Nadal chciałbym dokonać upgrade'u do wersji Java 7, ale chciałbym uniknąć nieprzyjemnego zachowania użytkowników JavaScriptu lub osób używających wersji tablicy tej metody.

Czy istnieje sposób na ukrycie przeciążonych metod Object[] od Rhino, podczas gdy inni nadal mogliby do nich zadzwonić?

Odpowiedz

10

Chociaż nie jest zbyt elegancka, istnieje sposób na wywołanie jednej przeciążonej metody Java. Jest on zdefiniowany w ostatniej sekcji specyfikacji Java Method Overloading and LiveConnect 3. Zasadniczo używasz całego podpisu metody, którą chcesz wywołać, ponieważ jest ona wyświetlana w komunikacie o błędzie, używając notacji nawiasów kwadratowych. W twoim przypadku następuje powinno działać:

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

To trochę niefortunne, że zmiana zrobiliśmy z tablicami JavaScript realizacji java.util.List łamie istniejącego kodu. Może lepiej wybrać jedną, na wypadek gdyby istniało wiele metod dopasowywania.

+0

zgadzam ... Byłoby lepiej, gdyby to właśnie nazywa się Lista jeden niezawodnie tak. Ale Java 7 złamała kilka innych rzeczy w naszej aplikacji, to tylko jeden z wielu (pozostałe, takie jak zmiany Locale, są rozwiązane.) – Trejkaz

Powiązane problemy