2009-12-18 9 views
62

Estoy comenzando a programar en Java y me pregunto si existe el equivalente a C++ #define.#define en Java

Una búsqueda rápida de Google dice que no, pero ¿alguien podría decirme si existe algo similar en Java? Estoy tratando de hacer que mi código sea más legible.

Quiero escribir myArray[PROTEINS] por ejemplo.

+8

En C++ moderno debe usar una constante tipada en lugar de una #define para eso –

+2

Sí, #define tiene estilo C. En C++ use const en su lugar. Ver el libro "Effective C++" de Scott Meyers, artículo 1. – Jabba

Respuesta

84

No, porque no hay precompilador.

Sin embargo, Hotspot es bastante sorprendentemente bueno en la optimización siempre que sea posible, por lo que en su caso se podría lograr lo mismo de la siguiente manera:

class MyClass 
{ 
    private static final int PROTEINS = 0; 

    ... 

    MyArray[] foo = new MyArray[PROTEINS]; 

} 

El compilador dará cuenta de que PROTEINS puede nunca, nunca cambia y también lo hará enlínea que es más o menos lo que quieres.

Tenga en cuenta que el modificador de acceso en la constante no es importante aquí, por lo que podría ser public o protected en lugar de privado, si desea reutilizar la misma constante en varias clases.

+13

Esto responde la pregunta pero hace un mal uso de algunos términos. Inline se realiza en tiempo de ejecución cuando el compilador JIT advierte que un método es lo suficientemente simple y no se anula (no conozco todas las reglas y eso puede cambiar de una versión a otra). Un 'final estático' de un tipo primitivo o de tipo cadena está definido por la especificación del compilador de Java (no JIT) como una constante. No está "en línea" en el sentido de JIT, en realidad se compila directamente en esa parte del código al igual que #define en C. –

5
static final int PROTEINS = 1 
... 
myArray[PROTEINS] 

Normalmente pondrías "constantes" en la clase. Y tenga en cuenta que un compilador puede optimizar las referencias a él, así que no lo cambie a menos que recompile todas las clases que lo usan.

class Foo { 
    public static final int SIZE = 5; 

    public static int[] arr = new int[SIZE]; 
} 
class Bar { 
    int last = arr[Foo.SIZE - 1]; 
} 

Editar ciclo ... SIZE=4. ¡También compile Bar porque su compilador puede haber escrito "4" en el último ciclo de compilación!

4

Java no tiene una directiva de preprocesador de propósito general define.

En el caso de las constantes, se recomienda para declarar como static finals, como en

private static final int PROTEINS = 100; 

Tales declaraciones serían inline por los compiladores (si el valor es una constante de tiempo de compilación).

Tenga en cuenta también que los campos constantes finales estáticos públicos son parte de la interfaz pública y sus valores no deberían cambiar (a medida que el compilador los inscribe). Si cambia el valor, deberá recompilar todas las fuentes que hicieron referencia a ese campo constante.

+0

Bueno, las finales estáticas * privadas * no son realmente parte de la interfaz * public *. :) Para 'públicos estáticos finales 'esto es cierto, sin embargo. – Bombe

+0

@Mombe, correcto. Lo escribí inicialmente como público, pero luego cambié sin actualizar la respuesta. – notnoop

34

Espacio de comentarios demasiado pequeño, así que aquí hay más información para usted sobre el uso de static final. Como dije en mi comentario al Andrzej's answer, solo las primitivas y String se compilan directamente en el código como literales.Para demostrar esto, intente lo siguiente:

Se puede ver esto en acción mediante la creación de tres clases (en archivos separados):

public class DisplayValue { 
    private String value; 

    public DisplayValue(String value) { 
     this.value = value; 
    } 

    public String toString() { 
     return value; 
    } 
} 

public class Constants { 
    public static final int INT_VALUE = 0; 
    public static final DisplayValue VALUE = new DisplayValue("A"); 
} 

public class Test { 
    public static void main(String[] args) { 
     System.out.println("Int = " + Constants.INT_VALUE); 
     System.out.println("Value = " + Constants.VALUE); 
    } 
} 

compilarlas y ejecución de prueba, que imprime:

Int = 0 
Value = A 

Ahora, cambie Constants para tener un valor diferente para cada uno y simplemente compile la clase Constants. Cuando ejecuta Test nuevamente (sin volver a compilar el archivo de clase) todavía imprime el valor anterior para INT_VALUE pero no VALUE. Por ejemplo:

public class Constants { 
    public static final int INT_VALUE = 2; 
    public static final DisplayValue VALUE = new DisplayValue("X"); 
} 

Ejecutar prueba sin tener que recompilar Test.java:

Int = 0 
Value = X 

Tenga en cuenta que cualquier otro tipo que se utiliza con static final se mantiene como referencia.

similar a C/C++ #if/#endif, una constante literal o uno definido a través de static final con primitivas, utilizado en una condición normal Java if y evalúa a false hará que el compilador para despojar el código de bytes de las normas dentro de la if bloque (no se generarán).

private static final boolean DEBUG = false; 

if (DEBUG) { 
    ...code here... 
} 

El código en "... código aquí ..." no se compilará en el código de bytes. Pero si cambió DEBUG a true, entonces sería.

+1

¡Definitivamente un +1 solo por el esfuerzo! –

+0

Solo quiero agregar que java no hace lo mismo para 'enum's. –

0

La respuesta más simple es "No es un método directo de obtenerlo porque no hay un precompilador" Pero puede hacerlo usted mismo. Use las clases y luego defina las variables como final para que se asuma que son constantes en todo el programa
No se olvide de utilizar final y variable como pública o protegida no privada, de lo contrario no podrá acceder a ella desde fuera de esa clase

0

La mayoría solución legible está utilizando Static Import. Entonces usted no necesita usar AnotherClass.constant.

Escriba una clase con la constante como campo public static.

package ConstantPackage; 

public class Constant { 
    public static int PROTEINS = 1; 
} 

Entonces sólo tiene que utilizar estático importación donde se necesita la constante.

import static ConstantPackage.Constant.PROTEINS; 

public class StaticImportDemo { 

    public static void main(String[]args) { 

     int[] myArray = new int[5]; 
     myArray[PROTEINS] = 0; 

    } 
} 

saber más sobre estático de importación por favor ver this stack overflow question.

2

Hay preprocessor for Java que proporciona directivas como #define, #ifdef, #ifndef y muchas otras, por ejemplo, el equipo de PostgresJDBC lo usa para generar fuentes para casos diferentes y para no duplicar el código.