2012-05-11 27 views
13

Estoy analizando la siguiente pieza de código usando una herramienta de análisis estático llamada FindBugs.comparando cadena con la enumeración

if(str.equals(enum.SOMEVALUE)) {// do something}; 

donde str es una Cadena y enumeración es una enumeración. La herramienta genera la siguiente advertencia para este código y estados

Este método llama a igual (Objeto) en dos referencias de tipos de clases diferentes sin subclases comunes. De acuerdo con el contrato de iguales(), los objetos de diferentes clases siempre deben compararse como desiguales; por lo tanto, de acuerdo con el contrato definido por java.lang.Object.equals (Object), el resultado de esta comparación siempre será falso en el tiempo de ejecución.

si se sustituye la línea de código anterior con esto:

if(str.equals(enum.SOMEVALUE.toString())) {// do something}; 

entonces la advertencia disappears.But no estoy seguro de si la advertencia de que la herramienta genera es realmente cierto y si estoy arreglando la manera correcta ? porque he visto tales comparaciones antes y parece estar funcionando correctamente.

Respuesta

18

Su primera comparación es básicamente mal. Está comparando objetos de tipos completamente diferentes (String y Enum) y nunca pueden ser iguales. incluso me da una advertencia aquí. Compila solo porque equals() acepta Object, no String.

La segunda comparación es correcta.

Aunque JavaDoc is a bit harsh on name() método, no me habría importado consejos usarlo en caso dado enumeración ha anulado toString():

if(str.equals(FooEnum.SOMEVALUE.name())) 
+0

Muchas gracias por el consejo de usar name(), haciendo obsoleto mi enfoque actual de un campo de id. En situaciones similares. – Bananeweizen

+0

Tenga en cuenta que los objetos de diferentes tipos definitivamente pueden ser iguales de igual a igual(). Both FindBugs e IntelliJ son incorrectos.Incluso hay un ejemplo en la API estándar de Java donde se hace esto: las implementaciones de la implementación de la interfaz de la Lista son iguales al comparar los elementos, incluso para diferentes subclases de la Lista. – herman

+0

@herman: tiene razón, pero 'equals()' tiene que ser * symmetrics *, lo cual se hace fácilmente con las implementaciones 'List' (todas están basadas en' AbstractList') pero no en el caso OP. –

2

me gustaría sugerir el uso de:

if (SomeEnum.SOMEVALUE == SomeEnum.valueOf(str)) { 

} 
+2

Tenga en cuenta que esto arrojará una excepción si 'str' no representa ningún valor' SomeEnum' –

+0

que sería útil utilizar en las sentencias switch –

3

Creo que la sustitución de la constante para el toString() puede ser lo correcto, lo cambiaría por .name() porque se debe sobrescribir toString.

1

Por lo que yo sé, estás en el camino correcto.

if(str.equals(enum.SOMEVALUE.toString())) {// do something}; 

Esto debería estar bien.

3

puede probar

enum.SOMEVALUE.name() 

ya que

Devuelve el nombre de esta constante de enumeración, tal y como declaró en su declaración de enumeración.