Variables globales en Java

217

¿Cómo define variables globales en Java?

aTJ
fuente
20
¿Puede decirnos por qué quiere definir variables globales en Java?
Adam Paynter
44
Para acceder a la variable desde fuera de la clase
aTJ
55
Tal vez debería editar su pregunta para incluir un código de muestra que ilustre exactamente lo que desea. Nos ayudaría a recomendar la mejor solución.
Adam Paynter
77
@ Adam: debería poder cambiar el valor de una variable en una clase de otra clase.
aTJ
2
Usted no No hay variables globales en Java.
Marqués de Lorne

Respuestas:

261

Para definir la variable global, puede utilizar palabras clave estáticas

public class Example {
    public static int a;
    public static int b;
}

ahora puede acceder a ayb desde cualquier lugar llamando

Example.a;

Example.b;
Abi
fuente
66
"Global" es el nombre de la clase.
Jerome
12
Tenga cuidado al hacer esto: cuando la clase Global se descargue, las variables serán nulas indefinidas. Si vende su aplicación, esto sucederá tarde o temprano y sigue buscando errores en todas partes, pero no allí ...
user387184
10
La staticpalabra clave hace que las variables sean accesibles globalmente, mientras se carga su clase.
sjas
22
Acerca de la descarga de clases: si hay una cadena de referencia fuerte desde cualquier raíz de GC a una instancia de Global o sus hijos, o cualquier referencia en tiempo de compilación de una clase cargada y no descargable a Global, entonces el objeto de clase relativo a Global es fuertemente accesible y, por lo tanto, también lo es el ClassLoader que cargó Global; lo que hace que sea imposible descargar Global (ya que la descarga de clases solo puede ocurrir después de que el GC elimine por completo cualquier referencia fuerte al ClassLoader que cargó una clase dada). Si no tiene referencias, ¿cómo podría ser un problema la descarga?
Bruno Reis
44
@Abi, le sugiero que cambie el nombre de su clase Globala otra cosa ( TestClass?) Para no dar a la gente la impresión de que existe una Globalpalabra clave Java. Mejor prevenir que curar :)
Nicolas Rinaudo
53

Usted no Eso es por diseño. No deberías hacerlo incluso si pudieras.

Dicho esto, podría crear un conjunto de miembros públicos estáticos en una clase llamada Globals.

public class Globals {
   public static int globalInt = 0;
   ///
}

pero realmente no deberías :) En serio ... no lo hagas.

Mihai Toader
fuente
66
Entonces, ¿cuál es el mejor enfoque que puedo declarar constantes para que todos los métodos de clase puedan acceder a ellos?
Alston
66
Las publicaciones de esta naturaleza son la razón por la cual los novatos desarrollan una fobia global variable, y luego vemos todo tipo de técnicas atroces que se diseñan para sortear el tabú de la variable global, pero logran el mismo efecto.
Evgeni Sergeev
38
Voto negativo para decir "no lo hagas". sin explicar o referirse a una explicación de por qué.
Jeff McCune
44
@JeffMcCune: para aclarar tu declaración, "no lo hagas" es realmente una mentira. Hazlo cuando sea útil. Por ejemplo, tengo que depurar mi código usando algunos IAbstractLoggerBullshit y, por supuesto, System.err no funciona en este entorno de ingeniería excesiva. No puedo ensuciar mi código pasando la basura del registrador entre cientos de clases de adaptadores inútiles.
Jo So
66
Voy a hacerlo.
Flotante Sunfish
40

Otra forma es crear una interfaz como esta:

public interface GlobalConstants
{
  String name = "Chilly Billy";
  String address = "10 Chicken head Lane";
}

Cualquier clase que necesite usarlos solo tiene que implementar la interfaz:

public class GlobalImpl implements GlobalConstants
{
  public GlobalImpl()
  {
     System.out.println(name);
  }
}
Evan Lévesque
fuente
Me pregunto por qué esta respuesta (antes de la mía) no tiene votos positivos. ¿No proporciona una respuesta alternativa razonable a la proporcionada por todas las otras respuestas?
M_M
12
Java efectivo por Joshua Bloch, Capítulo 4: Clases e interfaces, Elemento 19: Usar interfaces solo para definir tipos "El patrón de interfaz constante es un mal uso de las interfaces". ¡Vale la pena leer este libro! :)
MariuszS
1
Además, desde JDK 1.5+ puede usar la importación estática para sus variables globales, no es necesaria la implementación.
MariuszS
99
.... Correcto, eso en realidad no explica nada, solo dice que algún libro dijo que era malo.
linkhyrule5
14
Aquí hay una cita para ti. Oracle dice: "Para evitar esto, las personas a veces ponen miembros estáticos en una interfaz y heredan de esa interfaz. Esta es una mala idea. De hecho, es una idea tan mala que hay un nombre para ello: el Antipatrón de Interfaz Constante (ver Artículo 17 de Java efectivo.) El problema es que el uso de una clase de los miembros estáticos de otra clase es un mero detalle de implementación. Cuando una clase implementa una interfaz, se convierte en parte de la API pública de la clase. Los detalles de implementación no deben filtrarse API públicas ".
Jolta
23

Es mejor usar la inyección de dependencia:

public class Globals {
    public int a;
    public int b;
}

public class UsesGlobals {
    private final Globals globals;
    public UsesGlobals(Globals globals) {
        this.globals = globals;
    }
}
Peter Lawrey
fuente
55
Es cierto, aunque creo que su uso de "Globals" confunde un poco las cosas :-). Algo así como "Parámetros" sería más apropiado ya que no es necesariamente Global.
Mark Peters el
11

Muchas buenas respuestas, pero quiero dar este ejemplo, ya que se considera la forma más adecuada de acceder a las variables de una clase por otra clase: usando getters y setters.

La razón por la que usa getters y setters de esta manera en lugar de simplemente hacer pública la variable es la siguiente. Digamos que su var será un parámetro global que NUNCA desea que alguien cambie durante la ejecución de su programa (en el caso de que esté desarrollando código con un equipo), algo así como la URL de un sitio web. En teoría, esto podría cambiar y puede usarse muchas veces en su programa, por lo que desea usar una variable global para poder actualizar todo de una vez. Pero no desea que alguien más entre y cambie esta var (posiblemente sin darse cuenta de lo importante que es). En ese caso, simplemente no incluye un método setter, y solo incluye el método getter.

public class Global{
    private static int var = 5;

    public static int getVar(){
        return Global.var;
    }

    //If you do not want to change the var ever then do not include this
    public static void setVar(int var){
        Global.var = var;
    }
}
Dan Ciborowski - MSFT
fuente
10

No hay una variable global en Java

Sin embargo, lo que tenemos es una staticpalabra clave y eso es todo lo que necesitamos. Nada existe fuera de clase en Java. La staticpalabra clave representa una variable de clase que, a diferencia de la variable de instancia, solo tiene una copia y trasciende todas las instancias de esa clase creada, lo que significa que su valor se puede cambiar y acceder a todas las instancias en cualquier momento.

Si necesita una variable global a la que se pueda acceder más allá de los ámbitos, entonces esta es la variable que necesita, pero su alcance existe solo donde está la clase, y eso será todo.

Nishant
fuente
9

En verdad, no hay un concepto de "GLOBAL" en un programa Java OO

Sin embargo, hay algo de verdad detrás de su pregunta porque habrá algunos casos en los que desee ejecutar un método en cualquier parte del programa. Por ejemplo --- método random () en la aplicación Phrase-O-Matic; es un método que se puede llamar desde cualquier parte de un programa.

Entonces, para satisfacer las cosas como arriba "Necesitamos tener variables y métodos similares a los globales"

PARA DECLARAR UNA VARIABLE COMO GLOBAL.

 1.Mark the variable as public static final While declaring.

PARA DECLARAR UN MÉTODO COMO GLOBAL .

 1. Mark the method as public static While declaring.

Debido a que declaró que las variables globales y el método son estáticos, puede llamarlos a cualquier lugar que desee simplemente con la ayuda del siguiente código

ClassName.X

NOTA : X puede ser el nombre del método o el nombre de la variable según el requisito y ClassName es el nombre de la clase en la que los declaró.

JAVA
fuente
9

Nada debe ser global, excepto las constantes.

public class MyMainClass {
    public final static boolean DEBUGMODE=true;
}

Pon esto dentro de tu clase principal. En otros archivos .java, úsalo a través de:

if(MyMainClass.DEBUGMODE) System.out.println("Some debugging info");

Asegúrese de que cuando mueva su código del piso de la sala de corte y lo libere, quite o comente esta funcionalidad.

Si tiene un método de caballo de batalla, como un aleatorizador, le sugiero que cree un paquete "Toolbox". Todos los codificadores deben tener uno, luego, cuando quiera usarlo en un .java, ¡simplemente impórtelo!

David Bowman
fuente
5

No existe una variable verdaderamente global en Java. Cada variable estática debe pertenecer a alguna clase (como System.out), pero cuando haya decidido en qué clase entrará, puede consultarla desde cualquier lugar cargado por el mismo cargador de clases.

Tenga en cuenta que las variables estáticas siempre deben protegerse al actualizar para evitar condiciones de carrera.

Thorbjørn Ravn Andersen
fuente
1
Java no proporciona una variable global funcionalmente, pero si desea tener un concepto de variable global, podemos hacer uso de la palabra clave estática
Abi
3
public class GlobalClass {
     public static int x = 37;
     public static String s = "aaa";
}

De esta manera puede acceder a ellos con GlobalClass.xyGlobalClass.s

Mark Baijens
fuente
2
public class GlobalImpl {   

 public static int global = 5;

}

Puedes llamar a donde quieras:

GlobalImpl.global // 5

fuente
1

Como probablemente adivine por la respuesta, no hay variables globales en Java y lo único que puede hacer es crear una clase con miembros estáticos:

public class Global {
    public static int a;
}

Puedes usarlo en Global.aotro lugar. Sin embargo, si usa Java 1.5 o superior, puede usar la import staticmagia para que se vea aún más como una variable global real:

import static test.Global.*;

public class UseGlobal {
    public void foo() {
        int i = a;
    }
}

Y voilà !

Ahora, esto está lejos de ser una mejor práctica, como puede ver en los comerciales: no haga esto en casa

gabuzo
fuente
1

No hay variables globales en Java, pero hay clases globales con campos públicos. Puede usar la función de importación estática de java 5 para que se vea casi como variables globales.

fastcodejava
fuente
1

Generalmente, la variable global (supongo que la está comparando con C, Cpp) se define como public static final

me gusta

class GlobalConstant{
    public static final String CODE  = "cd";
}

Los ENUM también son útiles en tal escenario:

Por ejemplo Calendar.JANUARY)

Jigar Joshi
fuente
¿Una variable global necesita ser final? ¿Por qué?
Konerak
1
"final" significa "constante", por lo que esta es una constante global.
duffymo
1
no, eso es lo que significa la variable Global si quieres compartir esa variable y cambiar los datos y luego simplemente eliminar, finalpero ciertamente depende de cómo quieras compartir, dónde estás usando y todo,
Jigar Joshi
¿Cuál es el tipo de CODEen este ejemplo? ¿Dónde se define?
M_M
También tenga en cuenta: CODE está en mayúsculas, como su notación común de Java para usar todas las mayúsculas para las variables que declara como finales, y no tiene la intención de cambiar durante el curso de un programa.
Dan Ciborowski - MSFT
1

Crear un archivo independiente, por ejemplo. Example.java para usar la primera solución, está bien. Puede hacerlo también dentro de la aplicación, por ejemplo, si las variables globales son especiales para su aplicación actual, etc.

Crea una clase al principio y declara tus variables allí:

class Globals {
  static int month_number;
  static String month_name;
}

Luego puede acceder a estas variables, utilizándolas como 'Globals.month_number', etc., desde cualquier lugar de su aplicación.

Apostolos
fuente
En lugar de votar a favor, ¿puede decirme qué hay de malo en esta solución? Lo estoy usando de manera constante y es el más conveniente. Así que no puedo hacer otra cosa que considerar este voto negativo como algo personal o simplemente hecho por una persona estúpida.
Apostolos
1

Si necesita actualizar la propiedad global, se puede usar una clase de contenedor getter / setter simple como variable global. Un ejemplo típico se muestra a continuación.

public class GlobalHolder {

    private static final GlobalHolder INSTANCE = new GlobalHolder();

    private volatile int globalProperty;

    public static GlobalHolder getInstance() {
        return INSTANCE;
    }

    public int getGlobalProperty() {
        return globalProperty;
    }

    public void setGlobalProperty(int globalProperty) {
        this.globalProperty = globalProperty;
    }

    public static void main(String[] args) {
        GlobalHolder.getInstance().setGlobalProperty(10);
        System.out.println(GlobalHolder.getInstance().getGlobalProperty());
    }
}
Turkdogan Tasdelen
fuente
0

Siguiendo el concepto, las variables globales, también conocidas como variables de instancia, son las variables de nivel de clase, es decir, se definen dentro de una clase pero fuera de los métodos. Para que estén disponibles por completo y usarlos directamente, proporcione la palabra clave estática. Entonces, si estoy escribiendo un programa para una operación aritmética simple y requiere un par de números, entonces dos variables de instancia se definen como tales:

public class Add {
    static int a;
    static int b; 
    static int c;

    public static void main(String arg[]) {
        c=sum();
        System.out.println("Sum is: "+c); 
    }

    static int sum() {
       a=20;
       b=30;
       return a+b;   
    }
}

Output: Sum is: 50

Además, el uso de palabras clave estáticas antes de las variables de instancia nos permite no especificar tipos de datos para las mismas variables una y otra vez. Simplemente escriba la variable directamente.

BIJAY
fuente
1
No hay variables globales en Java; no se conocen también como variables de instancia; definirlos como static"no los hace disponibles por completo". El primer párrafo no tiene sentido. El ejemplo es una mala práctica.
Marqués de Lorne
0

En general, Java no tiene ninguna variable global. Aparte de las variables locales, todas las variables entran dentro del alcance de cualquier clase definida en el programa. Podemos tener variables estáticas para tener el alcance de las variables globales.

principiante
fuente
0

sin staticesto también es posible:

class Main {
  String globalVar = "Global Value";

  class Class1 {
    Class1() {
      System.out.println("Class1: "+globalVar);
      globalVar += " - changed";
  } }
  class Class2 {
    Class2() {
      System.out.println("Class2: "+globalVar);
  } }

  public static void main(String[] args) {  
    Main m = new Main();
    m.mainCode();
  }
  void mainCode() {
    Class1 o1 = new Class1();
    Class2 o2 = new Class2();
  }
}

/*
Output:
Class1: Global Value
Class2: Global Value - changed
*/
zemiak
fuente
0

La programación orientada a objetos se construye con el entendimiento de que el alcance de las variables es muy exclusivo del objeto de clase que encapsula esas variables.

El problema con la creación de "variables globales" es que no es estándar de la industria para Java. No es un estándar de la industria porque permite que múltiples clases manipulen datos asincronizados, si está ejecutando una aplicación multiproceso, esto se vuelve un poco más complicado y peligroso en términos de seguridad de subprocesos. Hay varias otras razones por las cuales el uso de variables globales no es efectivo, pero si desea evitar eso, le sugiero que recurra a la Programación Orientada a Aspectos .

La Programación Orientada a Aspectos niega este problema al poner a la clase padre a cargo del alcance a través de algo llamado "consejos", que agrega un comportamiento adicional al código sin modificarlo realmente. Ofrece soluciones a problemas transversales o uso de variables globales.

Spring es un marco de Java que utiliza AOP, y aunque se usa tradicionalmente para aplicaciones web, la aplicación central se puede usar universalmente en todo el marco de Java (8.0 incluido). Esta podría ser una dirección que desea explorar más.

sheepiiHD
fuente
0

Entendiendo el problema

Considero la calificación de la variable global como una variable a la que se puede acceder y cambiar en cualquier parte del código sin preocuparse por la llamada estática / instancia o pasar cualquier referencia de una clase a otra.

Usualmente si tienes clase A

public class A {
    private int myVar;

    public A(int myVar) {
        this.myVar = myVar;
    }

    public int getMyVar() {
        return myVar;
    }

    public void setMyVar(int mewVar) {
        this.myVar = newVar;
    }
}

y desea acceder y actualizar myvaren una clase B,

public class B{

    private A a;

    public void passA(A a){
        this.a = a;
    }

    public void changeMyVar(int newVar){
        a.setMyvar(newVar);
    }
}

necesitará tener una referencia de una instancia de la clase A y actualizar el valor en la clase B de esta manera:

int initialValue = 2;
int newValue = 3;
A a = new A(initialValue);
B b = new B();
b.passA(a);
b.changeMyVar(newValue);
assertEquals(a.getMyVar(),newValue); // true

Solución

Entonces, mi solución a esto, (incluso si no estoy seguro de si es una buena práctica), es usar un singleton:


public class Globals {
    private static Globals globalsInstance = new Globals();

    public static Globals getInstance() {
        return globalsInstance;
    }

    private int myVar = 2;

    private Globals() {
    }

    public int getMyVar() {
        return myVar;
    }

    public void setMyVar(int myVar) {
        this.myVar = myVar;
    }
}

Ahora puede obtener la instancia única global en cualquier lugar con:

Globals globals = Globals.getInstance();
// and read and write to myVar with the getter and setter like 
int myVar = globals.getMyVar();
global.setMyVar(3);
Mendrika Sandratra
fuente
-1
// Get the access of global while retaining priveleges.
// You can access variables in one class from another, with provisions.
// The primitive must be protected or no modifier (seen in example).

// the first class
public class farm{

  int eggs; // an integer to be set by constructor
  fox afox; // declaration of a fox object

  // the constructor inits
  farm(){
    eggs = 4;
    afox = new fox(); // an instance of a fox object

    // show count of eggs before the fox arrives
    System.out.println("Count of eggs before: " + eggs);

    // call class fox, afox method, pass myFarm as a reference
    afox.stealEgg(this);

    // show the farm class, myFarm, primitive value
    System.out.println("Count of eggs after : " + eggs);

  } // end constructor

  public static void main(String[] args){

    // instance of a farm class object
    farm myFarm = new farm();

  }; // end main

} // end class

// the second class
public class fox{

  // theFarm is the myFarm object instance
  // any public, protected, or "no modifier" variable is accessible
  void stealEgg(farm theFarm){ --theFarm.eggs; }

} // end class
Matt Thomas
fuente
2
¿Qué agrega esta respuesta que las otras respuestas no? No puedo ver ningún valor "nuevo" en esta respuesta.
EWit
-2

Para definir la variable global, puede utilizar palabras clave estáticas

public final class Tools {
  public static int a;
  public static int b;
}

ahora puede acceder a ayb desde cualquier lugar llamando

Tools.a;
Tools.b;

Tienes razón ... especialmente en J2ME ... Puedes evitar NullPointerException poniendo dentro de tu constructor MidLet (inicialización de proggy) esta línea de código:

new Tools();

Esto asegura que las Herramientas se asignarán antes de cualquier instrucción que lo use.

¡Eso es!

usuario2616742
fuente
3
Um ... Lo siento, pero ¿qué agrega esto que no está cubierto por las respuestas existentes?
Mysticial
Tal vez tengas razón ... pero esta respuesta explica cosas como la asignación de memoria.
user2616742
No hay clases estáticas de nivel superior en Java
Andremoniy