2014-11-05 12 views
10

Czy JVM może przeprowadzić optymalizację środowiska wykonawczego w następującym scenariuszu?Czy niezmienna metoda wyliczania może zostać zoptymalizowana przez maszynę JVM w czasie wykonywania?

Mamy następującą sytuację mamy tego interfejsu:

public interface ECSResource { 
    default int getFor(final Entity entity) { 
     return ResourceRetriever.forResource(this).getFor(entity); 
    } 
} 

a konkretną realizację takich jak:

private static enum TestResources implements ECSResource { 
    TR1, TR2; 
} 

Czy JVM móc zorientować się (przy starcie) że instancja wyliczeniowa, taka jak TestResources.TR1, należy do pojedynczego ResourceRetriever, takiego jak ResourceRetriever.forResource(TestResources.TR1)?

W naiwnym wykonaniu każde wywołanie do TestResources.TR1.getFor(...) utworzyłoby nową instancję ResourceRetriever.

W tym przypadku, chociaż wiemy, że (o inspekcji kodu) wezwanie do ResourceRetriever.forResource(this) wezwie następujące:

public class ResourceRetriever { 
    private final ECSResource resource; 

    ResourceRetriever(ECSResource resource) { 
     this.resource = resource; 
    } 

    public static ResourceRetriever forResource(ECSResource resource) { 
     return new ResourceRetriever(resource); 
    } 

    //lots of methods 
} 

Stąd nie ma nic, co można zmienić w czasie wykonywania z powodu przypadkowych wyników, błędów zaokrąglania, itp

Stąd pytanie: czy mapa JVM każdy enumECSResource instancja unikalnej odpowiadającej ResourceRetriever.forResource(this) przykład?

Należy pamiętać, że jest to możliwe do zrobienia czegoś takiego przez własną rękę, przez co następuje:

private static enum TestResources implements ECSResource { 
    TR1, TR2; 

    private static final Map<TestResources, ResourceRetriever> retrieverMapping; 
    static { 
     retrieverMapping = Arrays.stream(TestResources.values()) 
      .collect(Collectors.toMap(res -> res, ResourceRetriever::forResource)); 
    } 

    @Override 
    public int getFor(final Entity entity) { 
     return retrieverMapping.get(this).getFor(entity); 
    } 
} 

Odpowiedz

2

Semantyka słowa kluczowego new prawie na pewno zabronić tego, czego chce zrobić. (Zobacz odniesienia zarówno w The Java Language Specification i The Java Virtual Machine Specification.) Twój sposób zawsze zwraca nowy obiekt. Nie znam żadnych wirtualnych maszyn wirtualnych, które wykonałyby to, co próbujesz zrobić, zważywszy, że nie ma mechanizmu pozwalającego ustalić, że tylko jeden ResourceRetriever powinien zostać utworzony dla danego ECSResource. Wygląda mi to na formę memoization, która byłaby obsługiwana przez język (np. Groovy, który ma adnotację specjalnie do tego celu), a nie przez środowisko wykonawcze (JVM). Gdyby Java naprawiła generyczne, mogłabyś zhakować taką funkcję z czymś takim, jak ResourceRetriever<? extends ECSResource>, ale nie mogę powiedzieć, czy to by działało, a tym bardziej, czy byłby to dobry pomysł, czy nie.

Powiązane problemy