2015-11-11 10 views
7

Ich arbeitete an Switch-Fall.Java 8: Unterschied zwischen class.getName() und String-Literal

Wenn wir verwenden class.getName(), dann erhalte ich Fehler, dass „Fall Ausdrücke konstanter Ausdrücke sein muss“ wie folgt:

switch(param.getClass().getName()) 
    { 
     case String.class.getName(): 
      // to do 
      break; 
    } 

Auch wenn wir folgende, string Klassennamen in einem nehmen konstant, dann auch, immer gleichen Fehler:

public static final String PARAM_NAME = String.class.getName(); 
switch(param.getClass().getName()) 
    { 
     case PARAM_NAME: 
      // to do 
      break; 
    } 

Aber, wenn ich folgende, die Stringliteral "java.lang.String" verwenden, gibt es nicht Fehler:

public static final String PARAM_NAME = "java.lang.String"; 

Kann jemand bitte erklären, warum es nicht die ersten zwei Fälle nimmt und die letzte nimmt? Danke im Voraus.

Antwort

8

classObject.getName() ist ein Methodenaufruf, und die Ergebnisse von Methodenaufrufen sind definitionsgemäß keine Kompilierzeitkonstanten. Ein String-Literal ist eine Kompilierzeitkonstante.

Beachten Sie, dass viele Situationen eine static final Referenz als eine Konstante für die Lebensdauer des Programms dauern können, eine switch muss ihre Optionen zur Kompilierungszeit fest codiert haben. Der Wert eines case Ziels muss entweder ein Enum-Wert oder eine (Kompilierzeit) ConstantExpression sein.

+0

Aber ich nehme das in "statischen finalen" (dh, konstanten) Variablen, dann auch, es nicht zu nehmen? –

+0

der Compiler macht etwas Magie und ich nehme an, die beiden ersten Dinge sind in den gleichen Byte-Code kompilieren. Das letzte, das du gibst, dort wird das String-Literal verwendet und daher funktioniert es –

+2

@KrishnaKumar Ein 'static final'-Feld ist nicht unbedingt eine Kompilierzeitkonstante, auch wenn es für praktische Zwecke eine Konstante zur Laufzeit ist. – chrylis

6

Jedes Case-Label muss ein "konstanter Ausdruck" sein. Was ist ein „konstanter Ausdruck“ wird in der Programmiersprache Java-Standard definiert, §15.28 Constant Expressions:

A compile-time constant expression is an expression denoting a value of primitive type or a String that does not complete abruptly and is composed using only the following:

  • Literals of primitive type and literals of type String

...

  • Simple names that refer to constant variables

Keine Methode Anrufe dort aufgeführt sind, so Ergebnis Methodenaufruf nicht der konstante Ausdruck sein kann, auch wenn die Methode trivial ist. Aber "Einfache Namen, die sich auf konstante Variablen beziehen" sind hier aufgelistet, so dass die Referenz auf die konstante Variable ebenfalls eine Konstante ist.

4

Der Grund, warum dies nicht der Fall funktioniert, dass der Wert des case auf Bedürfnisse wechseln bekannt sein zur Compile-Zeit (weil es hart codiert und inlined im Bytecode ist).

String.class.getName() ist ein Methodenaufruf, der zur Laufzeit ausgewertet wird. Ja, static final garantiert, dass es sich nach dem ersten Laden der Klasse nicht ändert. Aber das alles ist lange nach der Kompilierzeit.

Der Compiler nie ruft beliebigen Code aus Anwendungsquellcode (mit der möglichen Ausnahme der Annotationsverarbeitung). Es kompiliert es nur.