2014-11-05 16 views
10

La JVM può eseguire l'ottimizzazione del runtime nel seguente scenario?È possibile ottimizzare un metodo enum non modificabile da JVM in fase di runtime?

Abbiamo la seguente situazione, abbiamo questa interfaccia:

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

E una concreta attuazione, quali:

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

Sarebbe la JVM essere in grado di capire (in fase di esecuzione) che un'istanza di enum come TestResources.TR1 appartiene a un singolo ResourceRetriever come ResourceRetriever.forResource(TestResources.TR1)?

Nell'implementazione ingenua ogni chiamata a TestResources.TR1.getFor(...) creerebbe una nuova istanza ResourceRetriever.

In questo caso però, sappiamo che (mediante ispezione codice) una chiamata a ResourceRetriever.forResource(this) chiamerà la seguente:

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 
} 

Quindi non v'è nulla che può cambiare in fase di esecuzione a causa di risultati casuali, errori di arrotondamento, ecc

di qui la domanda: Può la mappa JVM ogni enumECSResource esempio per la sua unica corrispondente ResourceRetriever.forResource(this) esempio?

Si noti che è possibile fare una cosa da soli, tramite il seguente:

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); 
    } 
} 

risposta

2

La semantica della parola chiave new quasi certamente vietano quello che hai intenzione di fare. (Vedi riferimenti sia in The Java Language Specification e The Java Virtual Machine Specification.) Il tuo metodo forResource restituirà sempre un nuovo oggetto. Non conosco alcuna JVM che faccia ciò che stai cercando di fare, dato che non esiste un meccanismo per determinare che solo uno ResourceRetriever debba essere creato per qualsiasi dato ECSResource. Mi sembra una forma di memoization per me, che sarebbe gestita dal linguaggio (ad esempio Groovy, che ha un'annotazione specifica per questo) e non dal runtime (JVM). Se Java avesse generato generici reificati, sarebbe possibile hackerare una caratteristica del genere con qualcosa come ResourceRetriever<? extends ECSResource> ma non posso dire se ciò funzionerebbe, né tanto meno se sarebbe una buona idea o meno.

Problemi correlati