Android

Android


ELEMENTOS DE JAVA

Página 19 de 25

Figura A.11.

Bloque switch dentro de un bucle for.

A.10. Métodos

Un método es un bloque de sentencias que se puede ejecutar repetidas veces invocando su nombre. Los métodos pueden tener cero, uno o varios parámetros y devolver o no un resultado de cierto tipo. Los métodos son el análogo de las funciones o subrutinas de otros lenguajes. La declaración de un método tiene la siguiente estructura:

   acceso resultado nombre (lista de parámetros) {

   // Bloque del método

   ....

   return valor;  // si no es void

   }  

•   Acceso indica si el método se puede ejecutar desde otra clase distinta, y puede ser public, private, protected, o el tipo por defecto, si no se indica nada.

•   Resultado debe ser un tipo de dato primitivo, int, float, double, etc., o el nombre de una clase o void, si el método no devuelve ningún resultado.

•   Nombre es el nombre del método.

•   La lista de parámetros, indicando tipo y nombre, separados por comas.

En el siguiente ejemplo definimos un método para calcular el factorial de un número (n!). Este método lo incluimos como método de la clase EjemploJava1 después del método onCreate, en el que hemos estado programando hasta ahora. El método factorial es llamado repetidas veces en un bucle desde el método onCreate. Distintos métodos de una clase pueden llamarse entre sí. El resultado es una tabla con el factorial de los primeros 20 números, figura A.12.

Figura A.12. Uso de un método para calcular el factorial de un número.

  public class EjemploJava1 extends Activity {

     @Override

     public void onCreate(Bundle savedInstanceState) {

         super.onCreate(savedInstanceState);

         setContentView(R.layout.main);

         TextView tv=(TextView) findViewById(R.id.textView);

         tv.setText("Metodo factorial");

         for(int i=0;i<20;i++){

          tv.append("\n "+i+" ! = "+factorial(i));

         }

     }

     //  metodo para calcular el factorial de un numero

     double factorial(int n){

       double fac=1;

       if (n==0)return fac;

       for (int i=1;i<=n;i++)fac=fac*i;

       return fac;

     }

 }

En el siguiente ejemplo definimos un método void para imprimir un número, que no devuelve ningún resultado. Tiene dos argumentos: un número float y un objeto TextView, el campo de texto donde estamos escribiendo. El resultado de imprimir varios números en un bucle se ve en la figura A.13.

  public class EjemploJava1 extends Activity {

     @Override

     public void onCreate(Bundle savedInstanceState) {

         super.onCreate(savedInstanceState);

         setContentView(R.layout.main);

         TextView tv=(TextView) findViewById(R.id.textView);

         tv.setText("Metodo void para imprimir");

         for(int i=0;i<20;i++){

          float x=i*i;

          print(x,tv);

          }

     }

     // metodo para escribir un numero en un campo de texto

     void print(float x, TextView tv){

       tv.append("\n Metodo print "+x);

     }

 }

Figura A.13. Un método void para imprimir un número.

Un ejemplo de un método que no requiere ningún argumento es la función para generar números aleatorios Math.random().

A.11. Clases y objetos

Un objeto es un conjunto de datos de distintos tipos que se referencian con una única variable. Los objetos no sólo contienen datos sino que también realizan acciones. Cada objeto pertenece a una clase y debe declararse como tal precediendo el nombre de la variable por el nombre de la clase mediante la sentencia:

NombreDeLaClase variable;

Una clase es un bloque de código con toda la información sobre los tipos de datos que contienen sus objetos, cómo construirlos, y con métodos para operar sobre sus datos o para realizar acciones concretas. Una clase contiene variables de clase y métodos. Todos los métodos de una clase tienen acceso a las variables de clase y pueden modificarlas, a no ser que las variables se declaren final. La estructura de una clase es la siguiente:

   acceso class Nombre {

   // variables de la clase

   variable1;

   variable2;

   //otras variables

   ...

   //metodos de la clase

   metodo1 (parametros) {

   ....

   }

   metodo2 (parametros){

   ...

   }

   // otros metodos

   ...

   }

El identificador de acceso de una clase sólo puede ser public o ninguno. Todas las sentencias de un programa Java, excepto package e import, deben estar contenidas dentro de una clase. Las clases utilizadas en un programa Java pueden ser definidas por el programador, o ser de un paquete de las librerías de Java. Existe el convenio de que el nombre de una clase empiece siempre por mayúscula.

Un programa Java es una colección de clases en uno o varios ficheros. Un fichero puede contener varias clases, pero sólo una puede ser public. El nombre del fichero debe coincidir con el de la única clase public que contiene.

En el siguiente ejemplo definimos una clase Dato del tipo más simple, que contiene únicamente datos: un entero, un float y un double.  En la clase principal EjemploJava1 creamos un objeto de tipo Dato usando new Dato() y asignamos valores a sus variables o campos de clase. Para acceder a estas variables usamos el nombre del objeto, seguido de un punto y el nombre de la variable. La salida del programa se ve en la figura A.14. La clase Dato se ha incluido al final del fichero principal, pero podría igualmente incluirse sola en un archivo Dato.java en el mismo directorio, declarándola public.

Figura A.14. Uso de una clase para albergar datos.

  public class EjemploJava1 extends Activity {

     @Override

     public void onCreate(Bundle savedInstanceState) {

         super.onCreate(savedInstanceState);

         setContentView(R.layout.main);

         TextView tv=(TextView) findViewById(R.id.textView);

         tv.setText(

                  "Clase que contiene tres datos numéricos");

         tv.append("\n Se accede a las variables de clase " +

             "mediante el nombre del objeto, seguido de un " +

             "punto y el nombre de la variable");

         // declaracion de objeto Dato

         Dato miDato;

         // creación de objeto Dato;

         miDato=new Dato();

         // asignación de valores para el objeto Dato

         miDato.i=1;

         miDato.f=1.35f;

         miDato.d=2.3e2;

         tv.append("\n miDato.i= "+miDato.i);

         tv.append("\n miDato.f = "+miDato.f);

         tv.append("\n miDato.d = "+miDato.d);

     }

 }

   class Dato {

     int i;

     float f;

     double d;

   }

Entre los programadores de Java, se aconseja que las variables de clase se declaren privadas mediante private y que no puedan ser modificadas, ni siquiera visibles, fuera de la clase. Esto significa que el acceso a la variable de clase mediante objeto.variable no es posible y dará un error de compilación. Para extraer y modificar las variables se usan exclusivamente métodos, lo que permite controlar sus posibles valores. Para inicializar las variables se usa también un método constructor con el mismo nombre que la clase, que se ejecuta al crear un nuevo objeto. El constructor debe ser void. Puede haber varios constructores con distintos argumentos y se ejecutará el que corresponda.

Figura A.15. Uso de una clase para albergar datos, con variables de clase privadas.

A continuación, modificamos el ejemplo anterior ocultando los campos de clase y usando métodos. El constructor Dato() permite inicializar los objetos al crearlos (figura A.15).

  public class EjemploJava1 extends Activity {

     @Override

     public void onCreate(Bundle savedInstanceState) {

         super.onCreate(savedInstanceState);

         setContentView(R.layout.main);

         TextView tv=(TextView) findViewById(R.id.textView);

         tv.setText(

                  "Clase que contiene tres datos numéricos");

         tv.append("\n Se accede a las variables de clase " +

             "mediante el nombre del objeto, seguido de un " +

             "punto y uno de los métodos get()");

         // declaracion de objeto Dato

         Dato miDato;

         // creación de objeto Dato;

         miDato=new Dato(1,1.35f,2.3e2);

         tv.append("\n miDato.getI()= "+miDato.getI());

         tv.append("\n miDato.getF() = "+miDato.getF());

         tv.append("\n miDato.getD() = "+miDato.getD());

         miDato.setI(200);

         miDato.setF(1.23456f);

         miDato.setD(0.1111e-23);

         tv.append(

          "\n\n Después de modificar las variables con SET:");

         tv.append("\n miDato.getI()= "+miDato.getI());

         tv.append("\n miDato.getF() = "+miDato.getF());

         tv.append("\n miDato.getD() = "+miDato.getD());

     }

 }

   class Dato {

     private int i;

     private float f;

     private double d;

   // metodo constructor de la clase

   Dato(int ivar, float fvar, double dvar){

     i=ivar;

     f=fvar;

     d=dvar;

   }

   // metodos SET para modificar las variables

   void setI(int ivar){

     i=ivar;

   }

   void setF(float fvar){

     f=fvar;

   }

   void setD(double dvar){

     d=dvar;

   }

   // metodos GET para extraer las variables

   int getI(){

     return i;

   }

   float getF(){

     return f;

   }

   double getD(){

     return d;

   }

  }

En el siguiente ejemplo creamos una clase de números complejos llamada Complejo, que se ha añadido al final del fichero. Esta clase contiene dos variables a,b que almacenarán la parte real e imaginaria, respectivamente. La clase contiene cuatro métodos. Uno con el mismo nombre de la clase, Complejo, que se llama constructor de la clase, que se ejecuta al crear un objeto de la clase, donde se inicializan las variables. Los otros tres métodos extraen la parte real, imaginaria y el módulo del número complejo representado por un objeto. En este ejemplo creamos dos números complejos y escribimos sus partes real e imaginaria. El resultado se ve en la figura A.16.

  public class EjemploJava1 extends Activity {

     @Override

     public void onCreate(Bundle savedInstanceState) {

         super.onCreate(savedInstanceState);

         setContentView(R.layout.main);

         TextView tv=(TextView) findViewById(R.id.textView);

         tv.setText("Clase de números Complejos");

         Complejo c1,c2,c3;

         c1=new Complejo(1,1);

         c2=new Complejo(2,3);

         // partes real e imaginaria usando métodos

         tv.append("\n\n c1="+c1.real()+"+i"+c1.imag());

         tv.append("\n c2="+c2.real()+"+i"+c2.imag());

         // partes real e imaginaria usando variables de clase

         tv.append("\n\n c1="+c1.a+"+i"+c1.b);

         tv.append("\n c2="+c2.a+"+i"+c2.b);

         tv.append("\n\n modulo de c1 = "+c1.modulo());

         tv.append("\n modulo de c2 = "+c2.modulo());

     }

 }

   class Complejo {

     double a,b;

     Complejo(double x,double y){

        a=x;

        b=y;

     }

     double real(){

        return a;

     }

     double imag(){

        return b;

     }

     double modulo(){

        return Math.sqrt(a*a+b*b);

     }

   }

Figura A.16. Uso de la clase de números complejos.

La instrucción para crear el número complejo 2+3i usando esta clase es:

Complejo c = new Complejo(2,3);

En el ejemplo vemos que podemos acceder a las variables o a los métodos de un objeto utilizando el nombre del objeto seguido de un punto y el nombre de la variable, o el nombre del método. Por ejemplo, la parte real del número anterior se puede extraer de estas dos formas:

double r;

r=c.real();

r=c.a;

A.12. Sub-clases

En Java se puede definir una subclase, que hereda las variables y métodos de la clase original, llamada su superclase. La subclase puede contener variables y métodos nuevos, o puede redefinir o sobreescribir los métodos de su superclase. Para declarar una subclase se usa la estructura:

class Subclase extends Superclase{

}

Esta estructura de subclase es ya familiar para nosotros, puesto que la hemos encontrado en todos los ejemplos anteriores, al definir la clase EjemploJava1 como una subclase de la clase Activity. También hemos visto que en todos los ejemplos se define el método onCreate(), precedido por la etiqueta @Override.  Esto indica que estamos redefiniendo, sobreescribiéndolo, el método con el mismo nombre de la superclase Activity.

En el siguiente ejemplo definimos una subclase Complejo2 de la clase Complejo del ejemplo anterior. Esta subclase define nuevos métodos para sumar, multiplicar e invertir números complejos. Las variables y métodos de la superclase están definidos y se pueden invocar dentro de la nueva clase usando el prefijo this. La clase y la superclase están aquí en el mismo fichero, pero podrían haberse puesto en ficheros java distintos, con el mismo nombre que la clase correspondiente.

  public class EjemploJava1 extends Activity {

     @Override

     public void onCreate(Bundle savedInstanceState) {

         super.onCreate(savedInstanceState);

         setContentView(R.layout.main);

         TextView tv=(TextView) findViewById(R.id.textView);

         tv.setText("Ejemplo de una subclase");

         tv.append(

           "\n La clase Complejo2 extiende la clase Complejo"+

             " definiendo métodos para la suma y producto " +

             " de números complejos");

         Complejo2 c1,c2,c3,c1Inv,c2Inv;

         c1= new Complejo2(1,1);

         c2= new Complejo2(2,3);

         tv.append("\n c1="+c1.real()+" + i"+c1.imag());

         tv.append("\n c2="+c2.real()+" + i"+c2.imag());

         // suma c1+c2

         c3=c1.sum(c2);

         tv.append("\n suma ="+c3.real()+" + i"+c3.imag());

         // producto c1*c2

         c3=c1.prod(c2);

         tv.append(

               "\n producto ="+c3.real()+" + i"+c3.imag());

         // inverso 1/c1

         c1Inv=c1.inv();

         tv.append(

          "\n 1/c1 ="+c1Inv.real()+" + i("+c1Inv.imag()+")");

         // inverso 1/c2

         c2Inv=c2.inv();

         tv.append(

          "\n 1/c2 ="+c2Inv.real()+" + i("+c2Inv.imag()+")");

         // producto c1*1/c1

         c3=c1.prod(c1Inv);

         tv.append("\n c1/c1 ="+c3.real()+" + i"+c3.imag());

         // producto c2*1/c2

         c3=c2.prod(c2Inv);

         tv.append("\n c2/c2 ="+c3.real()+" + i"+c3.imag());

     }

 }

   class Complejo2 extends Complejo{

     Complejo2(double x,double y){

        super(x,y);

     }

     Complejo2 sum(Complejo2 c){

        double cReal=this.real()+c.real();

        double cImag=this.imag()+c.imag();

        Complejo2 result= new Complejo2(cReal,cImag);

        return result;

     }

     Complejo2 prod(Complejo2 c){

        double cReal=this.real()*c.real()-this.imag()*c.imag();

        double cImag=this.real()*c.imag()+this.imag()*c.real();

        Complejo2 result= new Complejo2(cReal,cImag);

        return result;

     }

     Complejo2 inv(){

        double modulo=this.modulo();

        double cReal=this.real()/(modulo*modulo);

        double cImag=-this.imag()/(modulo*modulo);

        Complejo2 result= new Complejo2(cReal,cImag);

        return result;

     }

    }

    class Complejo {

     double a,b;

     Complejo(double x,double y){

        a=x;

        b=y;

     }

     double real(){

        return a;

     }

     double imag(){

        return b;

     }

     double modulo(){

        return Math.sqrt(a*a+b*b);

     }

  }

El resultado se muestra en la figura A.17. En este ejemplo vemos que el constructor de la subclase consiste en la línea super(x,y), lo que indica que se ejecute el constructor de la superclase Complejo(x,y). La variable super hace siempre referencia a la superclase de la clase actual. La misma fórmula se emplea al definir el método onCreate(), cuya primera línea es super.onCreate(), para ejecutar el método onCreate() de la superclase Activity.

Figura A.17. Uso de una subclase de números complejos.

Obsérvese que en los tres métodos de Complejo2 se usa la variable especial this, para indicar el nombre del objeto asociado a la clase actual. Así, this.real() sería la parte real del presente objeto.

A.13. Variables y métodos estáticos y finales

Una clase puede contener variables estáticas, que deben ser declaradas como variables de clase mediante:

static variable;

No se pueden definir dentro de un método. Estas variables pertenecen a la clase y no requieren un objeto de la clase para usarlas, aunque un objeto puede modificarlas. Para acceder a una variable estática se precede su nombre por el nombre de la clase, como Clase.variable. Por ejemplo, la variable Math.PI de la clase de funciones matemáticas es estática.

Una clase puede contener también métodos estáticos, que no requieren un objeto de la clase para utilizarlos. Se emplean de la misma forma que las variables estáticas. Por ejemplo, los métodos de la clase de funciones matemáticas Math, como Math.log(), son estáticos.

Las variables finales son constantes que se inicializan cuando se declaran y no se pueden modificar. Se suelen escribir con mayúsculas. Por ejemplo:

final double PI=3.1416;

Una variable final también puede declararse estática.

   static final PI=3.1416;

La variable Math.PI es estática y final.

Un método también puede declararse final. Se prohibe entonces que el método pueda ser modificado por una subclase. En cierto modo el método es constante, como las variables finales.

En el siguiente ejemplo definimos una clase con tres variables y un método estáticos. Dos de las variables son final y no pueden modificarse, pero la variable aa es incrementada cada vez que se construye un objeto. Esta variable vale inicialmente cero (inicializada al compilar) y puede ser referenciada antes de que exista ningún objeto de la clase. Al crear un nuevo objeto, con new Aa(), la variable se incrementa en una unidad, y puede utilizarse para contar el número de objetos de la clase que se han creado.

  public class EjemploJava1 extends Activity {

     @Override

     public void onCreate(Bundle savedInstanceState) {

         super.onCreate(savedInstanceState);

         setContentView(R.layout.main);

         TextView tv=(TextView) findViewById(R.id.textView);

         tv.setText("Variables y métodos final y/o  static");

         tv.append("\n static aa="+Abc.aa);

         tv.append("\n static final BB="+Abc.BB);

         tv.append("\n static final CC="+Abc.CC);

         double x=1.5;

         tv.append("\n Funcion static f(x)="+Abc.f(x));

         for (int i=1;i<10;i++){

         Abc v1=new Abc();

         v1.write(tv);

         }

         tv.append("\n Fuera del bucle:");

         Abc v2=new Abc();

         v2.write(tv);

         Abc v3=v2;

         v3.write(tv);

     }

 }

   class Abc{

     static int aa=0;

     static final int BB=555;

     static final int CC=777;

     Abc(){

        aa++;

     }

     void write(TextView tv){

        tv.append("\n Variable static aa="+aa);

     }

     static double f(double x){

        return BB+CC*x;

     }

   }

La salida de este programa se ve en la figura A.18. Obsérvese que el valor de la variable estatica aa se incrementa cada vez que se crea un objeto nuevo en el bucle, pero no al asignar la última variable v3, puesto que no se crea ningún objeto nuevo, sólo se asigna una referencia a un objeto que ya existe.

Figura A.18. Uso de variables y métodos static.

A.14. Arrays

Los arrays consisten en grupos de variables que se referencian con uno o varios índices enteros. El tamaño del array, es decir, el número de objetos que contiene, debe especificarse al crearlo. Un array es a su vez un objeto de una clase especial y debe crearse con la orden new, seguida de la clase a la que pertenencen los objetos del array, especificando su longitud entre corchetes. Por ejemplo, para declarar un array conteniendo 3 números enteros usamos:

   int [] a;

   a = new int[3];

Equivalentemente, se puede declarar un array escribiendo los corchetes tras el nombre de la variable. Por ejemplo:

   int a[];

El array anterior contiene tres variables enteras denotadas a[0], a[1], a[2]. Los contenidos del array se denotan poniendo entre corchetes una variable entera, que cuenta el número de orden de cada elemento, a[i]. Pero hay que tener siempre en cuenta que se empieza a contar en cero. Es decir el primer elemento de un array es el número cero, y si el array tiene dimensión n, su último elemento es el n-1. Un array es un objeto y length es la variable de clase donde se almacena su longitud.  Por tanto, la longitud del array anterior se puede obtener mediante a.length.

Los contenidos de un array se inicializan automáticamente a cero si son numéricos. También podemos inicializar un array igualándolo a un bloque de valores separados por comas, como:

   int[] a = {1,2,3,4,5};

En el siguiente ejemplo ilustramos el uso de los arrays en un programa Java.  Definimos un array entero, un array double, y una función cuyo argumento es un array. El resultado se ve en la figura A.19..

  public class EjemploJava1 extends Activity {

     @Override

     public void onCreate(Bundle savedInstanceState) {

         super.onCreate(savedInstanceState);

         setContentView(R.layout.main);

         TextView tv= (TextView) findViewById(R.id.textView);

         tv.setText("Ejemplos de arrays");

         // definicion de un array de longitud 3

         int[] miArray;

         miArray=new int[3];

         // obtención de la longitud del array

         int longitud=miArray.length;

         tv.append("\n Longitud del array= "+longitud);

         // escribimos los valores iniciales del array (cero)

         for (int i=0;i<3;i++){

          tv.append("\n i="+i+", miArray[i]="+miArray[i]);

          miArray[i]=1+i*i;

          tv.append("\n Valor después ="+miArray[i]);

          }

         // inicializacion de un array

         double[] miArray2={0,1,2,3};

         tv.append("\n miArray2=");

         for (int i=0;i<miArray2.length;i++){

          tv.append(" "+i+" , ");

          }

          double total=suma(miArray2);

          tv.append("\n suma="+total);

     }

     // suma los elementos de un array

     double suma(double[] a){

        double s=0;

        int nsumandos=a.length;

        for(int i=0;i<nsumandos;i++){

          s= s+a[i];

        }

        return s;

     }

 }

Figura A.19. Uso de arrays.

A.15. Arrays 2D

Un array de dos dimensiones (2D) es un array de arrays. Se especifica con dos índices entre corchetes. El primero indica la fila y el segundo la columna. Por ejemplo un array de enteros con dos filas y tres columnas se declara de la siguiente forma:

   int[][] a;

   a= new int[2][3];

y sus elementos son variables enteras denotadas a[i][j], donde i=0,1 y j=0,1,2.

También se puede definir cada fila separadamente como un array de una dimensión. Por ejemplo, en las siguientes líneas primero declaramos un array 2D que tiene dos filas. A continuación, se declara que cada fila es a su vez un array con tres elementos:

   int[][] a = new int[2][];

   a[0]=new int[3];

   a[1]=new int[3];

Esto permite construir arrays con número de columnas variable. Por ejemplo, la primera fila podría contener dos elementos y la segunda cuatro, de la siguiente forma:

   int[][] a = new int[2][];

   a[0]=new int[2];

   a[1]=new int[4];

El siguiente programa Android es una demostración del uso de arrays 2D en Java, con número de columnas fijo y variable. El resultado se puede ver en la figura A.20..

Figura A.20. Uso de arrays 2D.

  public class EjemploJava1 extends Activity {

     @Override

     public void onCreate(Bundle savedInstanceState) {

         super.onCreate(savedInstanceState);

         setContentView(R.layout.main);

         TextView tv= (TextView) findViewById(R.id.textView);

         tv.setText("Ejemplos de arrays");

         // definicion de un array bidimensional

         int[][] miArray;

         miArray=new int[3][2];

         // obtención de la longitud del array

         int filas=miArray.length;

         int columnas=miArray[0].length;

         tv.append("\n miArray \n filas = "+filas);

         tv.append(", Columnas= "+columnas);

         // inicializamos el array

         for (int i=0;i<filas;i++){

          for (int j=0;j<columnas;j++){

             miArray[i][j]=10*i+j;

          }

         }

         // escribe el contenido del array

         for (int i=0;i<filas;i++){

          tv.append("\n fila: ");

          for (int j=0;j<columnas;j++){

             tv.append(" "+miArray[i][j]+",");

          }

         }

         // definimos e incializamos un array

         double miArray2[][]={ {1,2,3}, {4,5,6}};

         filas=miArray2.length;

         columnas=miArray2[0].length;

         tv.append("\n\n miArray2:");

         tv.append("\n Filas= "+filas);

         tv.append(" , Columnas = "+columnas);

         // escribe el contenido del array

         for (int i=0;i<filas;i++){

          tv.append("\n fila: ");

          for (int j=0;j<columnas;j++){

             tv.append(" "+miArray2[i][j]+",");

          }

         }

         // array con columnas variables

         double miArray3[][]=new double[3][];

         miArray3[0]=new double[1];

         miArray3[1]=new double[2];

         miArray3[2]=new double[3];

         miArray3[0][0]=0;

Ir a la siguiente página

Report Page