Variables estáticas
Vamos a ver un tipo especial de variable que son las variables de clase (static
)
1
2
3
4
5
6
7
8
9
10
public class Articulo{
private static int numSerie = 0;
private int ID;
private String nombre;
Articulo(String nombre){
this.nombre = nombre;
this.ID = numSerie++;
}
//Se omiten setters y getters
}
Estas variables se definen anteponiendo la palabra reservada static
e implica que esta variable va a ser común para todos los elementos de la clase.
Fijaos que en el constructor se asigna e incrementa el valor de esta variable al atributo ID
1
this.ID = numSerie++;
Por ejemplo, el código siguiente:
1
2
3
4
5
6
7
8
public class MainArticulo {
public static void main(String[] args) {
Articulo a = new Articulo("Ordenador");
System.out.println(a.getID());
Articulo b = new Articulo("Impresora");
System.out.println(b.getID());
}
}
Produce la siguiente salida:
1
2
0
1
Es decir, cuando se ha creado el objeto b
la variable numSerie
ya tenía el valor 1.
En general, se usan este tipo de variables cuando deseamos conservar su estado para todos los objetos de la misma.
Métodos estáticos
Al igual que las variables estáticas, los métodos estáticos se usan para crear métodos que no accedan al estado de los objetos.
Supón que queremos tener una entidad Persona
que almacene el campo DNI
y nos debemos asegurar que este DNI es correcto.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public class Persona {
private String nombre;
private String DNI;
private final char[] letras = { 'T', 'R', 'W', 'A', 'G', 'M', 'Y', 'F', 'P', 'D', 'X', 'B', 'N', 'J', 'Z', 'S', 'Q', 'V', 'H',
'L', 'C', 'K', 'E' };
public Persona(String nombre, String DNI) {
this.nombre = nombre;
if (checkDNI(DNI)) this.DNI = DNI;
else this.DNI = "";
}
public String getNombre() {
return nombre;
}
public void setNombre(String nombre) {
this.nombre = nombre;
}
public String getDNI() {
return DNI;
}
private boolean checkDNI(String DNIAComprobar){
if (DNIAComprobar.length() != 9) return false;
else{
int numero = Integer.parseInt(DNIAComprobar.substring(0, 8));
char letra = DNIAComprobar.charAt(8);
if ( letra != this.letras[numero % 23]) return false;
}
return true;
}
}
El método checkDNI(String DNIAComprobar)
no accede a ningún atributo del objeto al igual que la variable private char[] letras
. Estos son candidatos para convertir el método en static
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public class Persona {
private String nombre;
private String DNI;
private static final char[] letras = { 'T', 'R', 'W', 'A', 'G', 'M', 'Y', 'F', 'P', 'D', 'X', 'B', 'N', 'J', 'Z', 'S', 'Q', 'V', 'H',
'L', 'C', 'K', 'E' };
public Persona(String nombre, String DNI) {
this.nombre = nombre;
if (checkDNI(DNI)) this.DNI = DNI;
else this.DNI = "";
}
public String getNombre() {
return nombre;
}
public void setNombre(String nombre) {
this.nombre = nombre;
}
public String getDNI() {
return DNI;
}
private static boolean checkDNI(String DNIAComprobar){
if (DNIAComprobar.length() != 9) return false;
else{
int numero = Integer.parseInt(DNIAComprobar.substring(0, 8));
char letra = DNIAComprobar.charAt(8);
if ( letra != letras[numero % 23]) return false;
}
return true;
}
}
¿Qué ventaja ofrece este tipo de métodos y variables estáticos? La ventaja se produce en el consumo de memoria. Si tenemos 1.000.000 de objetos Persona
cada uno de ellos con su copia de la variable letras
ocuparán 1.000.000 * 24 * 1 byte por carácter = 24.000.000 Bytes
, es decir, más o menos 24 MB sólo para almacenar las letras mientras que con static
sólo ocupan 24 Bytes.
¿Cuándo usarlo? En general, si un método no accede a ningún atributo del objeto, se debe declarar como
static
. Todas las variables que use un métodostatic
también deben ser declaradas comostatic
. Cualquier otra variable que deseemos compartir entre todos los objetos de la clase también serástatic
Desde un método no estático se puede acceder a una variable o método estático pero no al revés.
Piensa que es como una relación
1:N
entre la clase y el objeto. Desde la parteN
(objeto) se puede acceder a la parte1
(clase) porque sólo hay una, pero ¿desde la parte1
a qué objeto de la parteN
accedo?