2.1.3.- Programación
en Android: Unos conceptos (V) - Arrays, strings, ámbitos...
En este capítulo cerraremos
la serie de "unos conceptos" (de java), no hemos arañado
ni la parte superficial de Java, pero tampoco es la intención
de esta guía, existen libros y recursos suficientes sobre esta
materia en español, no así como de Android, que es la
raiz principal de esta serie.
A medida que continuemos con la
programación en Android iremos viendo a Java en más
profundidad, pero para comenzar a dar nuestros primeros pasos creo
que es suficiente. Así que terminaremos esta serie
introductoria hablando de los arrays, los strings, y los ámbitos.
Arrays,
arreglos o matrices.
Hablaremos de unos tipos de datos
que son los llamados arrays (arreglos en
algunos libros y matrices en otros) y que no son más
que un conjunto de valores del mismo tipo.
Los arrays al igual
que otros tipos de variables antes de ser utilizados tienen que ser
declarados. Para declararlo hay que indicar el tipo de
array que va a ser, osea el tipo de datos que va a contener, y su
nombre. La forma genérica de declarar un array sería:
//
forma genérica: tipo[] nombre;
//
Ejemplo:
//Vamos
a declarar un array de ints
int[]
arrayInts;
|
Los [] después
del tipo son obligatorios ya que son los que indican que se trata de
un array. Hasta ahora sólo hemos declarado el tipo de array,
pero todavía no le hemos asignado memoria para contener los
elementos. En caso de que queramos acceder a cualquier elemento del
array sin haberle asignado memoria el compilador nos dará un
error.
Para asignar memoria a nuestro array
debemos de ejemplarizarlo, y esto lo hacemos con el operador
new. Veamos otro ejemplo dónde además de
declarar el array lo ejemplarizamos:
//
Ahora declaramos y ejemplarizamos el array en la misma línea.
//
Este es un array de 5 elementos (de 0 a 4)
int[]
arrayInts2=new
int[5];
|
Despues de asignarle la memoria al
array ya podemos comenzar a introducirle valores. Para referirnos a
un elemento individual del array, debemos indicar el número de
éste entre corchetes, de la siguiente manera:
arrayInts2[2]
= 245;
|
En este ejemplo nos estamos
refiriendo al tercer elemento del array. Ya que los arrays comienzan
a contar sus elementos desde cero (0).
Debemos tener cuidado con esto ya
que nos puede llevar a engaños porque si nos fijamos en la
ejemplarización pusimos [5], y sí son cinco elementos
pero contanto desde 0, con lo que el último sería
[4]. De todas formas, podemos utilizar el método
length para conocer cúal es el tamaño del
array.
arrayInts[0]
= arrayInts2.length;
|
El tipo con el que se pueden crear
arrays puede ser cualquier tipo de dato legal en Java. Por
ejemplo: ints, floats, string, char, objetos en general, etc.
Cuando el tipo es un objeto,
entonces los elementos del array son de tipo referencia (en
C++ serían punteros o referencias) a dicho objeto, cada
elemento del array referenciaría un objeto de ese tipo. En
este caso hay que recordar despues de reservar memoria para las
referencias, también se debe hacer para cada objeto individual
o en caso contrario nos dará una excepción de tipo
"NullPointerException".
//Arrays
de objetos
String[]
arrayStrings=new
String[5];
//Ahora
tendríamos memoria para las 5 referencias, pero también
//debemos
reservar memoria para los Strings individuales.
for
(int
i=0;i<arrayStrings.length;i++)
{
//Al
utilizar new asignamos memoria a cada string.
arrayStrings[i]=new
String
("Hola cadena"+i);
}
|
String,
cadenas de texto.
Los objetos de tipo string contienen
una secuencia de datos de tipo carácter.
Aunque en algunas referencias se
indica que los objetos String son inmutables, lo cierto es que
nos puede parecer lo contrario, por ejemplo el siguiente fragmento de
código utiliza el método replace para cambiar la cadena
de texto, y como podemos observar en la salida nos cambia dicha
cadena. Cuando se refieren a que son inmutables, se refieren
a que en este caso no se cambia el texto y se amplía la
memoria reservada para el string, sino que se crea un
nuevo objeto string con la modificación, y la
otra se deja intacta. Dicho de otro modo estamos creando otra cadena
de texto. Con una cadena no pasa nada, pero multiplicandolo por
miles es una gran pérdida de tiempo y memoria.
//Objetos
String
String
cadena;
cadena
= "Una cadena de texto";
System.out.println(cadena);
cadena
= cadena.replace("Una cadena",
"Doscientas cadenas");
System.out.println(cadena);
|
Si por el contrario sabemos que
vamos a tener que trabajar con la cadena "on the fly",
añadiendo y reemplazando carácteres, etc... lo mejor es
utilizar la clase StringBuffer, que está
optimizada para eso. Por ejemplo:
//Si
queremos trabajar con las cadenas y modificarlas al vuelo
//
es más eficiente utilizar la clase StringBuffer.
StringBuffer
cadenaModificable;
//Estamos
creando una string:
cadenaModificable
= new
StringBuffer("Una
cadena modificable");
System.out.println(cadenaModificable);
//Le
añadimos más texto. Pero se crea también un
String:
cadenaModificable.append(".
Otra String.");
System.out.println(cadenaModificable);
|
Hay que hacer notar que cada vez que
le añadimos un texto a nuestro objeto StringBuffer
entre comillas (como por ejemplo ". Otra String."),
el compilador los convierte en objetos String, y aunque
es más eficiente StringBuffer, se debe tener en
cuenta que posiblemente genere más objetos de los que
esperabamos.
No quería terminar esta seríe
de introducción sin hablar de algo tan importante como los
ámbitos de las variables.
Ámbitos
El alcance o ámbito
determina tanto la visibilidad como la vida de las variables
definidas en ese ámbito. Los ámbitos se determinan
mediante la utilización de las llaves { }. Las
variables que se definen dentro de un ámbito sólo están
disponibles hasta que se salga de dicho ámbito. El ámbito
de las variables en java difiere un poco de las de C++.
Por ejemplo, en el siguiente
fragmento de código:
private
static
void
ambitoVariable()
{
//Ejemplos
de ámbitos de variables:
int
unavariable
= 1;
{
//Estamos
en otro ámbito más "interior"
int
otravariable = 2;
//Pódemos
acceder a la variable del ámbito "superior"
//
o el que engloba a este.
unavariable
= otravariable;
{
//Y
otro ámbito más "interior"
int
terceravariable = 3;
//Podemos
acceder a las variables de los ámbitos "superiores"
unavariable
= otravariable = terceravariable;
//Aqui
termina el ámbito de terceravariable
}
//Esta
linea nos daría error, ya que no estamos en el ámbito
de esa variable
//otravariable=terceravariable;
//Aqui
termina el ámbito de otra variable
}
//Aqui
solo tenemos disponible a esta variable:
unavariable
= 40;
//Estas
líneas dan error ya que están en otro ámbito.
//otravariable
= 2;
//terceravariable
= 3;
}
|
Los modificadores de acceso
controlan el acceso a los miembros de la clase, ya que
podemos tener algunas variables u objetos que pueden ser accedidos
desde fuera de la clase y sin embargo tener otros que son utilizados
de modo interno a dicha clase y no deberían ser utilizados
externamente. Mediante los especificadores de acceso se protegen las
variables y los métodos de la clase cuando son declarados. En
Java existen cuatro niveles de acceso: private,
protected, public y package.
Veamos quién puede acceder:
Especificador
|
Clase
|
Subclase
|
Package
|
Mundo
|
Private
|
SI
|
|||
Protected
|
SI
|
SI(*)
|
SI
|
|
Public
|
SI
|
SI
|
SI
|
SI
|
Package
|
SI
|
SI
|
En la primera columna observamos que
con cualquier especificador de acceso que utilizemos la propia
clase siempre tendrá acceso al miembro.
En la segunda columna se observa que
en las subclases, osea las que hereden de esta clase, sólo
tendran acceso a los miembros con los especificadores protected
o public.
En la tercera cMiemolumna vemos como
las clases del mismo paquete, tienen acceso a los miembros.
Y en la cuarta columna se indica si
todas las clases, incluso las de otros paquetes tienen acceso a los
miembros.
Se puede observar que el acceso más
permisivo lo tenemos con el especificador public, y el
más restrictivo con el especificador private.
Private: Es el nivel de
acceso más restrictivo. Los miembros así definidos
sólo se pueden acceder desde la clase en la que se definen.
Protected: Permite a la
clase, las subclases y las demás clases en el mismo paquete
acceder a los miembros. Se utiliza cuando se necesita que una
subclase pueda tener acceso a los miembros, pero no las clases que no
estén relacionadas. Si una clase es subclase o está
en el mismo paquete que el miembro protected
entonces la clase tiene acceso a dicho miembro.
Public: Todas las clases, en
todos los paquetes tienen acceso a los miembros públicos de
dicha clase. Ancha es Castilla, como se suele decir. Sólo se
deben declarar así los miembros cuando se sepa que su acceso
no dará resultados indeseados al ser utilizados por terceros.
Package: Este es el acceso
que tenemos en caso de no especificar ningún modificador de
acceso. Se permite a las clases del mismo paquete que se acceda a
los miembros.
Cuándo hablamos de las
clases, hablamos de que les podían añadir unos
modificadores para indicar el tipo de acceso, vamos a recordarlos:
Public: Indica
que la clase puede ser utilizada por objetos fuera del paquete
actual. En caso de utilizarlo suele ser el primer elemento de la
declaración.
Abstract: Declara la
clase como abstracta. Las clases abstractas pueden contener métodos
para los que no se ha creado la implementación. Las clases de
este tipo están diseñadas para ser superclases y no
pueden ejemplarizarse.
Final: Al añadir
este modificador, indicamos que la clase no puede tener subclases.
No se puede heredar.
No tiene mucho sentido utilizar los
modificadores abstract y final juntos, ya que si no implementamos los
métodos, ni dejamos que se implementen, en fin...
Se puede descargar un ejemplo de
este capítulo aquí.
Ver. 1.0 – Revisión
25.1.2012
No hay comentarios:
Publicar un comentario