viernes, 7 de diciembre de 2012

6.3 MÉTODOS DE INSTANCIA


Cuando una declaración de método incluye un modificador static, se dice que el método es un método estático. Si no existe un modificador static, se dice que el método es un método de instancia.
Un método estático no opera en una instancia específica, y se produce un error en tiempo de compilación al hacer referencia a this en un método estático.
Un método de instancia opera en una determinada instancia de una clase y es posible tener acceso a dicha instancia con this (Sección 7.5.7).
Cuando se hace referencia a un método en un acceso-a-miembro (Sección 7.5.4) de la forma E.M, si M es un método estático, E debe denotar un tipo que contenga M, y si M es un método de instancia, E debe denotar una instancia de un tipo que contenga M.
Las diferencias entre miembros estáticos y de instancia se tratan con más detalle en la Sección 10.2.5.

6.2 MÉTODOS DE UNA CLASE


  • Los métodos de una clase constituyen la lógica de la clase, es decir, contienen el código que manipula el estado del objeto. Además constituyen el mecanismo utilizado para implementar los mensajes entre objetos. Quiere decir, cuando un objeto se comunica con otro por un mensaje lo hace por medio de la invocación al método correspondiente del objeto. Y el mecanismo para invocar un método en java es por medio de las referencias usando el operador de la siguiente forma:
    referencia.metodo (parametros);

    Declaración de los Métodos

    Veamos la forma de declarar un método. La estructura general de una declaración tiene dos partes, la declaración y el cuerpo del método.
    Métodos de clase
    La Declaracion_del_metodo proporciona información sobre su nombre, la accesibilidad del método, el número de parámetros que recibe, etc. El Cuerpo_del_metodo contiene el conjunto de sentencias que manipula los datos de cada objeto.

    Sobrecarga de métodos

    Cada método tiene una "firma" por así decirlo, que son su nombre, el tipo y número de sus parámetros. Existe una característica para tener dos métodos (ó constructores) con el mismo nombre. Esta característica se denominasobrecarga de métodos.
    Hemos estudiado la construcción de distintos constructores para una clase y hemos puesto como ejemplo el caso de una clase Publicacion. Veamos lo implementado hasta el momento y cómo los constructores nos dan un ejemplo de sobrecarga de métodos:
    sobrecarga de métodos
    El compilador resolverá que constructor debe ejecutar en cada momento en función del número de parámetros y su tipo. Si se llama al constructor sin parámetros se ejecutará el primer constructor y en caso de hacerlo con dos parámetrosString se ejecutará el segundo.
    Nota: El concepto de sobrecarga de métodos se puede aplicar siempre que los parámetros sean diferentes, bien por su tipo, bien por que el número de parámetros de un método o otro es diferente. Hay que tener cuidado con los tipos: int, byte y short ya que aunque son tipos diferentes, si hacemos la llamada aún método con un número entero no sabría a cual de los métodos llamar, ya que un entero puede ser considerado de las tres formas. Con double y float no pasa, porque acordaros que hemos de forzar a que Java entienda un decimal como float, sino lo entiende como double.
    Los métodos de clase al igual que las variables de clase, se aplican a la clase como un todo y no a sus instancias.

    Se utiliza de igual manera la palabra clave static para indicar que un método es un método de clase: 
    static valorRetorno nombreMetodo( <lista argumentos opcionales> )
    {
         /* cuerpo del método */
    }
    
Para acceder a las variables o métodos de clase se utiliza el mismo operador punto ( . ).

Aunque se puede acceder a las variables y métodos de clase a través de un objeto, está permitido y se recomienda utilizar mejor el nombre de la clase,
   /* Utilizar esto */
   nombreClase.nombreVarClase;
   nombreClase.nombreMetodoClase();

   /* en lugar de esto */
   nombreObjeto.nombreVarClase;
   nombreObjeto.nombreMetodoClase();
Ejemplo

/* Usuario3.java */

class Usuario3
{
     static char MAS = 'm';
     static char FEM = 'f';

     String nombre;
     int edad;
     String direccion;
     char sexo;

     Usuario3( )
     {
        nombre = null;
        edad = 0;
        direccion = null;
        sexo = '\0';
     }

     Usuario3(String nombre, int edad, String direccion,char sexo)
     {
        this.nombre = nombre;
        this.edad = edad;
        this.direccion = direccion;
        this.sexo = sexo;
     }

     Usuario3(Usuario3 usr)
     {
        nombre = usr.getNombre();
        edad = usr.getEdad();
        direccion = usr.getDireccion();
        sexo = usr.getSexo();
     }

     void setNombre(String n)
     {
        nombre = n;
     }

     String getNombre( )
     {
        return nombre;
     }

     void setEdad(int e)
     {
        edad = e;
     }

     int getEdad()
     {
        return edad;
     }

     void setDireccion(String d)
     {
        direccion = d;
     }

     String getDireccion( )
     {
        return direccion;
     }

     void setSexo(char s)
     {
        sexo = s;
     }

     char getSexo( )
     {
        return sexo;
     }

     public String toString()
     {
        return nombre;
     }
}
/* ProgUsuario3.java */

class ProgUsuario3
{
   static int NUM_USUARIOS = 0;
   static java.util.Vector usuarios = new java.util.Vector();

   String nombreObj = null;

   ProgUsuario3(String nombre)
   {
     this.nombreObj = nombre;
   }

   static int getNumUsuarios()
   {
     return NUM_USUARIOS;
   }

   static void imprimeUsuario(Usuario3 usr)
   {
      System.out.println("\nNombre: " + usr.nombre );
      System.out.println("Edad: " + usr.getEdad() );
      System.out.println("Sexo: " + usr.getSexo() );
      System.out.println("Direccion: " + usr.getDireccion() );
   }

   void addUsuario(Usuario3 usr)
   {
      usuarios.addElement(usr);
      System.out.print(usr.toString( )+ " agregado por el "+ this.toString() +",");
      NUM_USUARIOS ++;
   }

   void delUsuario(Usuario3 usr)
   {
      boolean b = usuarios.removeElement(usr);
      if( b == true )
      {
         NUM_USUARIOS--;
         System.out.print(usr.toString( )+ " eliminado por el "+ this.toString() +",");
      }
      else System.out.println("No se pudo eliminar al usuario.");
   }

   public String toString()
   {
      return nombreObj;
   }

   public static void main(String args[])
   {
      ProgUsuario3 obj1 = new ProgUsuario3("objeto1");
      ProgUsuario3 obj2 = new ProgUsuario3("objeto2");

      Usuario3 usr1,usr2,usr3,usr4;

      usr1 = new Usuario3( );
      usr2 = new Usuario3("Usuario B",24,"La direccion A",Usuario3.FEM);
      usr1 = new Usuario3(usr2);
      usr1.setNombre("Usuario A");
      usr3 = new Usuario3("Usuario C",35,"La direccion C",Usuario3.MAS);
      usr4 = new Usuario3("Usuario D",15,"La direccion D",Usuario3.MAS);

      obj1.addUsuario(usr1);
      System.out.println( "\t Total: " +ProgUsuario3.getNumUsuarios() );
      obj2.addUsuario(usr2);
      System.out.println( "\t Total: " +obj1.getNumUsuarios() );
      obj1.addUsuario(usr3);
      System.out.println( "\t Total: " +ProgUsuario3.NUM_USUARIOS );
      obj2.addUsuario(usr4);
      System.out.println( "\t Total: " +getNumUsuarios() +"\n");

      obj2.delUsuario(usr4);
      System.out.println( "\t Total: " +ProgUsuario3.getNumUsuarios() );
      obj1.delUsuario(usr3);
      System.out.println( "\t Total: " +obj1.getNumUsuarios() );
      obj2.delUsuario(usr2);
      System.out.println( "\t Total: " +ProgUsuario3.NUM_USUARIOS );
      obj1.delUsuario(usr1);
      System.out.println( "\t Total: " +getNumUsuarios() +"\n");
   }
}

6.1 DECLARACIÓN DE MÉTODOS


Cuando uno plantea una clase en lugar de especificar todo el algoritmo en un único método (lo que hicimos en los primeros pasos de este tutorial) es dividir todas las responsabilidades de las clase en un conjunto de métodos.
Un método hemos visto que tiene la siguiente sintaxis:
public void [nombre del método]() {
  [algoritmo]
}
Veremos que hay varios tipos de métodos:

Métodos con parámetros.

Un método puede tener parámetros:
public void [nombre del método]([parámetros]) {
  [algoritmo]
}
Los parámetros los podemos imaginar como variables locales al método, pero su valor se inicializa con datos que llegan cuando lo llamamos.

Problema 1:

Confeccionar una clase que permita ingresar valores enteros por teclado y nos muestre la tabla de multiplicar de dicho valor. Finalizar el programa al ingresar el -1.

Programa:

import java.util.Scanner;
public class TablaMultiplicar {
    public void cargarValor() {
        Scanner teclado=new Scanner(System.in);
        int valor;
        do {
            System.out.print("Ingrese valor:");
            valor=teclado.nextInt();
            if (valor!=-1) {
                calcular(valor);
            }
        } while (valor!=-1);
    }
    
    public void calcular(int v) {
        for(int f=v;f<=v*10;f=f+v) {
            System.out.print(f+"-");
        }
    }
    
    public static void main(String[] ar) {
        TablaMultiplicar tabla;
        tabla=new TablaMultiplicar();
        tabla.cargarValor();
    }
}
En esta clase no hemos definido ningún atributo, ya que el objeto de la clase Scanner lo requerimos en un solo método, por ello lo definimos como una variable local.
El método calcular recibe un parámetro de tipo entero, luego lo utilizamos dentro del método para mostrar la tabla de multiplicar de dicho valor, para esto inicializamos la variable f con el valor que llega en el parámetro. Luego de cada ejecución del for incrementamos el contador f con el valor de v.
    public void calcular(int v) {
        for(int f=v;f<=v*10;f=f+v) {
            System.out.print(f+"-");
        }
    }
Un método puede no tener parámetros como hemos visto en problemas anteriores o puede tener uno o más parámetros (en caso de tener más de un parámetro los mismos se separan por coma)
El método cargarValores no tiene parámetros y tiene por objetivo cargar un valor entero por teclado y llamar al método calcular para que muestre la tabla de multiplicar del valor que le pasamos por teclado:
    public void cargarValor() {
        Scanner teclado=new Scanner(System.in);
        int valor;
        do {
            System.out.print("Ingrese valor:");
            valor=teclado.nextInt();
            if (valor!=-1) {
                calcular(valor);
            }
        } while (valor!=-1);
    }
Como vemos al método calcular lo llamamos por su nombre y entre paréntesis le pasamos el dato a enviar (debe ser un valor o variable entera)
En este problema en la main solo llamamos al método cargarValor, ya que el método calcular luego es llamado por el método cargarValor:
    public static void main(String[] ar) {
        TablaMultiplicar tabla;
        tabla=new TablaMultiplicar();
        tabla.cargarValor();
    }

Métodos que retornan un dato.

Un método puede retornar un dato:
public [tipo de dato] [nombre del método]([parámetros]) {
  [algoritmo]
  return [tipo de dato]
}
Cuando un método retorna un dato en vez de indicar la palabra clave void previo al nombre del método indicamos el tipo de dato que retorna. Luego dentro del algoritmo en el momento que queremos que finalice el mismo y retorne el dato empleamos la palabra clave return con el valor respectivo.

Problema 2:

Confeccionar una clase que permita ingresar tres valores por teclado. Luego mostrar el mayor y el menor.

Programa:

import java.util.Scanner;
public class MayorMenor {
    public void cargarValores() {
     Scanner teclado=new Scanner(System.in);
        System.out.print("Ingrese primer valor:");
        int valor1=teclado.nextInt();
        System.out.print("Ingrese segundo valor:");
        int valor2=teclado.nextInt();
        System.out.print("Ingrese tercer valor:");
        int valor3=teclado.nextInt();
        int mayor,menor;
        mayor=calcularMayor(valor1,valor2,valor3);
        menor=calcularMenor(valor1,valor2,valor3);
        System.out.println("El valor mayor de los tres es:"+mayor);
        System.out.println("El valor menor de los tres es:"+menor);
    }
    
    public int calcularMayor(int v1,int v2,int v3) {
        int m;
        if(v1>>v2 && v1>v3) {
          m=v1;
        } else {
            if(v2>v3) {
                m=v2;
            } else {
             m=v3;
            }
        }
        return m;
    }
    
    public int calcularMenor(int v1,int v2,int v3) {
        int m;
        if(v1<v2 && v1<v3) {
          m=v1;
        } else {
            if(v2<v3) {
                m=v2;
            } else {
             m=v3;
            }
        }
        return m;
    }
    
    public static void main(String[] ar) {
        MayorMenor maymen=new MayorMenor();
        maymen.cargarValores();
    }
}
Si vemos la sintaxis que calcula el mayor de tres valores enteros es similar al algoritmo visto en conceptos anteriores:
    public int calcularMayor(int v1,int v2,int v3) {
        int m;
        if(v1>v2 && v1>v3) {
          m=v1;
        } else {
            if(v2>v3) {
                m=v2;
            } else {
             m=v3;
            }
        }
        return m;
    }
Lo primero que podemos observar que el método retorna un entero y recibe tres parámetros:
    public int calcularMayor(int v1,int v2,int v3) {
Dentro del método verificamos cual de los tres parámetros almacena un valor mayor, a este valor lo almacenamos en una variable local llamada "m", al valor almacenado en esta variable lo retornamos al final con un return.
La llamada al método calcularMayor lo hacemos desde dentro del método cargarCalores:
        mayor=calcularMayor(valor1,valor2,valor3);
Debemos asignar a una variable el valor devuelto por el método calcularMayor. Luego el contenido de la variable mayor lo mostramos:
        System.out.println("El valor mayor de los tres es:"+mayor);
La lógica es similar para el cálculo del menor.

VI: MODULARIDAD

La modularidad es la capacidad que tiene un sistema de ser estudiado, visto o entendido como la unión de varias partes que interactúan entre sí y que trabajan para alcanzar un objetivo común, realizando cada una de ellas una tarea necesaria para la consecución de dicho objetivo. Cada una de esas partes en que se encuentre dividido el sistema recibe el nombre de módulo. Idealmente un módulo debe poder cumplir las condiciones de caja negra, es decir, ser independiente del resto de los módulos y comunicarse con ellos (con todos o sólo con una parte) a través de unas entradas y salidas bien definidas.
Modularidad en Ciencias de la computación es la característica por la cual un programa de computador está compuesto de porciones que se conocen como módulos. El diseño estructurado es la técnica de diseño de algoritmos en que se basa la programación modularparadigma de programación que persigue desarrollar programas modulares.


Modularidad y orientación a objetos. Traducción a Java de
diseños modulares
En esta asignatura sólo aplicaremos la orientación a objetos a fin de aprovechar mejor los mecanismos que el lenguaje Java ofrece para codificar nuestros diseños modulares. Sin embargo, este
estilo de programación conlleva un modo particular de abordar la estructuración de programas.
Veamos en primer lugar algunos aspectos conceptuales del mismo para pasar, seguidamente, a
aplicarlos en nuestro contexto.

Considerado como unidad de estructuración de programas, el concepto de clase equivale esencialmente al de módulo. Por tanto, sus fases de diseño son las mismas, si bien la forma de
especificar, utilizar e implementar difiere ligeramente entre un estilo y el otro. Las clases y los
objetos representan una manera alternativa de modelizar los datos (la información) de un programa.
En el estilo modular clásico, un módulo de datos define un tipo con un dominio de valores y
un conjunto de operaciones que trabajan con diversos parámetros, de los que al menos uno es del
propio tipo. En programación orientada a objetos, una clase de datos define una estructura de
atributos y operaciones que se particulariza (también se suele decir que se “instancia”) en cada
objeto de la misma que se crea. En este aspecto, una clase también hace el papel de “tipo” de
dichos objetos.
En el diseño modular clásico, una variable posee un valor del tipo al que pertenece y sobre
ella se aplican las operaciones de dicho tipo. Podemos decir que una variable contiene la información. Sin embargo, cada vez que se crea un objeto de una clase de datos, éste se convierte
en un representante de la estructura definida en tal clase, de forma que recibe como componentes sus atributos y sus operaciones (también llamadas métodos). En este caso el objeto es la
información.
La mayoría de lenguajes orientados a objetos introducen maneras de trabajar que pueden resultar sorprendentes si previamente se ha estudiado diseño modular, pero que son perfectamente
consistentes con la mencionada diferencia conceptual entre ambos estilos.
Por ejemplo, las operaciones de una clase se conciben para ser aplicadas sobre un objeto
concreto de la clase, y por eso se parametrizan de una manera especial, de tal manera que el
objeto que es creado, modificado o consultado por una operación no aparece explícitamente
en la lista de paramétros de la misma. Se mencionará sólo en las llamadas a dicha operación,
mientras que en el código de la misma es referido de forma implícita.
Otra práctica habitual es que las clases no se tratan igual que los tipos simples a la hora de
parametrizar las operaciones o respecto a la operación de asignación. La primera situación se
estudia en detalle en la primera sesión de laboratorio de la asignatura. En cuanto a la segunda,
cuando se desea producir dos objetos distintos con la misma información, no se habla de asignar
un objeto a otro sino de copiar (o también, clonar) un objeto en otro. De hecho, en la mayoría
de lenguajes orientados a objetos se permite realizar asignaciones entre objetos, pero con una
1semántica muy distinta a la de la asignación clásica. Al realizarse tal asignación entre objetos,
el resultado es que la misma información pasa a tener dos nombres (situación habitualmente
denominada “aliasing”), lo que puede dar lugar a efectos laterales difícilmente controlables.
Por ello, en nuestro contexto limitaremos estas asignaciones a un reducido número de casos
particulares que describiremos en su momento, aunque en otros contextos puede resultar útil
explotar esta compartición de información.
En la práctica, esta filosofía de trabajo da lugar a una serie de aspectos metodológicos nuevos
que presentamos en los apartados siguientes, aplicados de forma particular al lenguaje Java.

sábado, 1 de diciembre de 2012

5.4 CREAR OBJETOS


Crear Objetos en Java

En Java, se crea un objeto mediante la creación de un objeto de una clase o, en otras palabras, ejemplarizando una clase. Aprenderás cómo crear una clase más adelante en Crear Clases.
Hasta entonces, los ejemplos contenidos aquí crean objetos a apartir de clases que ya existen en el entorno Java.
Frecuentemente, se verá la creación de un objeto Java con un sentencia como esta.
Date hoy = new Date();
Esta sentencia crea un objeto Date (Date es una clase del paquete java,util). Esta sentencia realmente realiza tres acciones: declaración, ejemplarización e inicialización.
Date hoy es una declaración de variable que sólo le dice al compilador que el nombre hoy se va a utilizar para referirse a un objeto cuyo tipo es Date, el operador new ejemplariza la clase Date (creando un nuevo objeto Date), y Date() inicializa el objeto.

. Declarar un Objeto

Ya que la declaración de un objeto es una parte innecesaria de la creación de un objeto, las declaraciones aparecen frecuentemente en la misma línea que la creación del objeto. Como cualquier otra declaración de variable, las declaraciones de objetos pueden aparecer solitarias como esta.
Date hoy;
De la misma forma, declarar una variable para contener un objeto es exactamente igual que declarar una variable que va a contener un tipo primitivo.
tipo nombre
donde tipo es el tipo de dato del objeto y nombre es el nombre que va a utilizar el objeto. En Java, las clases e interfaces son como tipos de datos. Entonces tipo puede ser el nombre de una clase o de un interface.
Las declaraciones notifican al compilador que se va a utilizar nombre para referirse a una variable cuyo tipo es tipo. Las declaraciones no crean nuevos objetos. Date hoy no crea un objeto Date, sólo crea un nombre de variable para contener un objeto Date. Para ejemplarizar la clase Date, o cualquier otra clase, se utiliza el operador new.

. Ejemplarizar una Clase

El operador new ejemplariza una clase mediante la asignación de memoria para el objeto nuevo de ese tipo. new necesita un sólo argumento: una llamada al método constructor. Los métodos constructores son métodos especiales proporcionados por cada clase Java que son reponsables de la inicialización de los nuevos objetos de ese tipo. El operador new crea el objeto, el constructor lo inicializa.
Aquí tienes un ejemplo del uso del operador new para crear un objeto Rectangle (Rectangle es una clase del paquete java.awt).
new Rectangle(0, 0, 100, 200);
En el ejemplo, Rectangle(0, 0, 100, 200) es una llamada al constructor de la clase Rectangle.
El operador new devuelve una referencia al objeto recien creado. Esta referencia puede ser asignada a una variable del tipo apropiado.
Rectangle rect = new Rectangle(0, 0, 100, 200);
(Recuerda que una clase esencialmente define un tipo de dato de referencia. Por eso, Rectangle puede utilizarse como un tipo de dato en los programas Java. El valor de cualquier variable cuyo tipo sea un tipo de referencia, es una referencia (un puntero) al valor real o conjunto de valores representado por la variable.

. Inicializar un Objeto

Como mencioné anteriormente, las clases porporcionan métodos constructores para incializar los nuevos objetos de ese tipo. Una clase podría proporcionar múltiples constructores para realizar diferentes tipos de inicialización en los nuevos objetos.
Cuando veas la implementación de una clase, reconocerás los constructores porque tienen el mismo nombre que la clase y no tienen tipo de retorno. Recuerda la creación del objeto Date en el sección inicial. El constructor utilizado no tenía ningún argumento.
Date()
Un constructor que no tiene ningún argumento, como el mostrado arriba, es conocido como constructor por defecto. Al igual que Date, la mayoría de las clases tienen al menos un constructor, el constructor por defecto.
Si una clase tiene varios constructores, todos ellos tienen el mismo nombre pero se deben diferenciar en el número o el tipo de sus argumentos. Cada constructor inicializa el nuevo objeto de una forma diferente. Junto al constructor por defecto, la clase Date proporciona otro constructor que inicializa el nuevo objeto con un nuevo año, mes y día.
Date cumpleaños = new Date(1963, 8, 30);
El compilador puede diferenciar los constructores a través del tipo y del número de sus argumentos.

5.3 CLASE PRINCIPAL


Clase principal.

Clase con el método main: clase principal, iniciadora o “programa principal”
Esta es la clase Principal, es la encargada de ejecutar los Plugins, las clases que contienen un filtro especial para cada buscador en particular. Los Plugins extienden la clase GusPlugin que contiene las rutinas necesarias para que cualquier plugin funcione, como conectarse al buscador y devolver la búsqueda. Es una clase abstracta así que se obliga a extenderla. En el caso de que unplugin no funcione, por razones de cambio en el buscador original, entonces se puede cambiar la extensión, por la de un plugin ya hecho y dar la sensación de que la funcionalidad no se perdió. Esta clase contiene un pequeño cargador de clases así que sólo es necesario copiar los nuevos plugins a la carpeta con los demás sin tener que modificar el resto del código, y por supuesto losplugins son Threads que a medida que van terminando se interpretan y devuelven los resultados, mientras los otros siguen buscando. En este caso se limitó la carga de Plugins a 2 [0-1] por la razón de que son demasiados resultados y los usuarios, pueden terminar cancelando la búsqueda.
Hasta ahora hemos visto código implementando clases y que las clases definen tipos, es decir, nos permiten crear objetos del tipo definido por la clase. Pero a todas estas, ¿dónde está el programa? Todavía no hemos visto ningún programa, y ya es hora de que abordemos este asunto.
http://images4.hiboox.com/images/4111/diapo0289e8e5b4f9fb2375c0e99b518a8807.png?24
Sabemos que los métodos en Java pueden tener cualquier nombre (excluido el de palabras clave). Existe un nombre de método que está reservado en Java y otros lenguajes: el método main. Este método es un método especial en tanto en cuanto es el que da lugar al inicio del programa. Si comparamos un programa con un partido de fútbol, el método main sería el responsable de poner el partido en juego.
metodo main java

Es importante tener claro que el método main no es el elemento principal en el desarrollo del programa. El programa, de acuerdo con el paradigma de programación orientada a objetos, se desarrolla mediante la interacción entre objetos, que en la figura hemos representado como jugadores en el campo de fútbol. Por tanto el cometido del método main normalmente es iniciar el programa (poner el balón en juego) y permanecer en un segundo plano mientras los objetos interactúan entre sí, controlando el desarrollo de la situación como si del árbitro se tratara. El método main normalmente no será muy extenso en cuanto a líneas de código respecto al resto del código (clases). Si esto ocurriera, posiblemente sería indicador de que este método tiene más protagonismo del que debe, y en nuestro símil el árbitro no debe ser protagonista del partido. En algunos ejemplos de código que desarrollemos quizás la clase con el método main contenga gran parte del código total, pero si esto es así será porque lo estamos utilizando con fines didácticos. En programas profesionales esto no debe ocurrir.
El método main es indudablemente importante. Por eso y por motivos históricos en el desarrollo de la programación muchas veces se alude a él (o a la clase donde se sitúa) como clase principal o “programa” principal. Pero hay que tener bien claro que su carácter principal se debe a que es quien inicia el desarrollo del programa, no a que sea quien debe asumir el protagonismo del mismo.
Un error que cometen frecuentemente las personas que están aprendiendo Java es suponer que el método main es la parte principal del programa, en el sentido de que debe concentrar los procesos importantes y la mayor parte del código. Esta concepción errónea se reflejaría en el siguiente esquema, donde las clases y objetos están al servicio del método main (o de la clase donde se encuentre) que es quien centraliza las operaciones. Este esquema es posible, pero no es el adecuado dentro del estilo de programación orientada a objetos y no aprovecha todo el potencial de esta forma de programación.
metodo main java

 

 La clase principal y el método main

Un programa puede construirse empleando varias clases. En el caso más simple se utilizará una única clase. Esta clase contiene el programa, rutina o método principal: main() y en éste se incluyen las sentencias del programa principal. Estas sentencias se separan entre sí por caracteres de punto y coma.
La estructura de un programa simple en Java es la siguiente:
public class ClasePrincipal {
public static void main(String[] args) {
sentencia_1;
sentencia_2;
// ...
sentencia_N;
}
}
Como primer ejemplo sencillo de programa escrito en Java se va a utilizar uno que muestra un mensaje por la pantalla del ordenador.
Por ejemplo, el programa Hola.java:
/**
* La clase hola construye un programa que
* muestra un mensaje en pantalla
*/
public class Hola {
public static void main(String[] args) {
System.out.println("Hola, ");
System.out.println("me llamo Angel");
System.out.println("Hasta luego");
}
}
Como se ha indicado anteriormente, en un programa de Java todo se organiza dentro de las clases. En el ejemplo anterior, Hola es el nombre de la clase principal y del archivo que contiene el código fuente. Todos los programas o aplicaciones independientes escritas en Java tienen un método main o principal que, a su vez, contiene un conjunto de sentencias. En Java los conjuntos o bloques de sentencias se indican entre llaves { }. En el caso anterior, el conjunto de sentencias se reduce a tres sentencias, que son llamadas a dos métodos predefinidos en Java (print y println) que permiten visualizar texto por el dispositivo de salida de datos por defecto (la pantalla).
Por el momento y hasta que se explique con detalle el concepto de clase, los ejemplos de programa que se utilizarán constarán de una sóla clase en la que se declara el método main. Este método es el punto de arranque de la ejecución de todo programa en Java.

5.2 ELEMENTOS DE UNA CLASE

Atributos o Propiedades
Tipo de características y propiedades que las entidades puedan obtener. Los atributos distinguen un objeto de los restantes (tamaño, posición, color, ... ). Cada propiedad tendrá un determinado valor. Las propiedades de un objetos pueden ser heredadas por sus descendientes.
SINTAXIS
(ACCESO)

  • Public
  • Private
  • protected 
(MODIFICADOR)
  • Static
  • Final
tipoDato
  • Tipos básicos
  1. byte, int, float, double
  2. char, boolean
  • Wrapper
  1. Integer, String, Double, Float
  2. Clase definidas por el programador
TIPOS DE ATRIBUTOS
De Instancia :
Estos atributos permiten almacenar los datos particulares de un objeto. Se denominan de instancia porque se estructuran con el objeto cuando este cerca. 
Ejemplo: 
public class Triangulo{
             private int base;
             private int altura;  
             private int area:
}
De Clase:
Estos atributos permiten almacenar datos que van a ser compartidos por muchos objetos. Estos atributos, no se instancia  con el objeto cuando este es cerrado.
Ejemplo:
public class Casa{
               private static String empresaEnergia;
               private static String empresaAgua;
}
Constantes:
Estos atributos representan valores constantes de los objetos.
Ejemplo: 
public class Circulo{
         private final double PI= 3.1416;
}
public class Circulo{
         private static final double PI= 3.1416;
}
OPERACIONES
Es una acción que el objeto puede realizar. para implementar este concepto en Lenguaje de Programación Java, debemos recurrir al concepto de función (subprograma que realiza una tarea concreta) conjunto de cosas que puede hacer un objeto (estudiar, caminar, trabajar, rotas, volar, etc.). Un método es un procedimiento o función que altera el estado de un objeto o hace que el objeto envíe un mensaje, es decir, que devuelva los valores.
SINTAXIS
[acceso] tipoDevuelto nombreDeLaOperación( [parámetros] ){
                         Definición de la operación (método)
}
TIPOS DE OPERACIONES
Constructoras:
Estas operaciones se encargan de inicializar los atributos de un objeto cuando este se está creando:
  • Tiene el mismo nombre de la clase
  • No retornan valor (no se le especifican tipoDevuelto)
  • Se llaman automáticamente cuando el objeto se crea (llamado implícito)
POR DEFECTO:
Son creados por el programador, se encargan de inicializar los atributos de un objeto con valores preestablecidos :
public class Casas{
        private int numeroCuartos;
        public Casas(){
             this.numeroCuartos=3;
    }
}
PARAMETRICAS
Son creadas por el programador, se encargan de inicializar los atributos de un objeto con valores recibidos en los parámetros de la función 
public class Casas{
     private int nroCuartos;
     public Casas(int nC){
               this.nroCuartos=nC;
    }
}
MODIFICADORAS
Reciben un objeto, el cual se utiliza para inicializar los atributos de el objeto que se está construyendo
public class Casas{
public Casas(Casas ob){
    this.Cuartos=ob.nCuartos;
   }
}

TIPOS DE OPERACIONES
Analizadoras:
Estas operaciones se encargan de tomar el valor o dato que se encuentra en un atributo particular de un objeto y regresarlo (return)



Sintaxis:
[acceso] tipoDevuelto  getAtributo(){
        return nombreAtributo:
}

Modificadoras:
Estas operaciones se encargan de asignar un valor a un atributo especifico de un objeto
Sintaxis:
[acceso] void     setAtributo([parámetro]){
     nombreAtributo= parametro:
}







5.1 - ESTRUCTURA DE UNA CLASE


Una clase consiste en:

algunas_palabras class nombre_de_la_clase [algo_más] {
[lista_de_atributos]
[lista_de_métodos]
}

Lo que está entre [ y ] es opcional

Ya veremos qué poner en "algunas_palabras" y "algo_más", por ahora sigamos un poco más.

La lista de atributos (nuestras viejas variables locales) sigue el mismo formato de C: se define primero el tipo y luego el nombre del atributo, y finalmente el ";".

public final static int MAX_VALUE

;

También tenemos "algunas_palabras" adelante, pero en seguida las analizaremos.

En cuanto a los métodos, también siguen la sintaxis del C; un ejemplo:

public int incContador() { // declaración y apertura de {
cnt++; // instrucciones, separadas por ";"
return(cnt);
} // cierre de }

Finalmente, se aceptan comentarios entre /* y */, como en C, o bien usando // al principio del comentario (el comentario termina al final de la línea).

Veamos un ejemplo:

// Implementación de un contador sencillo
// GRABAR EN UN ARCHIVO "Contador.java" (OJO CON LAS MAYUSCULAS!)
// COMPILAR CON: "javac Contador.java" (NO OLVIDAR EL .java!)
// ESTA CLASE NO ES UNA APLICACION, pero nos va a servir enseguida

public class Contador { // Se define la clase Contador

// Atributos
int cnt; // Un entero para guardar el valor actual

// Constructor // Un método constructor…
public Contador() { // …lleva el mismo nombre que la clase
cnt = 0; // Simplemente, inicializa (1)
}

// Métodos
public int incCuenta() { // Un método para incrementar el contador
cnt++; // incrementa cnt
return cnt; // y de paso devuelve el nuevo valor
}
public int getCuenta() { // Este sólo devuelve el valor actual
return cnt; // del contador

}

Cuando, desde una aplicación u otro objeto, se crea una instancia de la clase Contador, mediante la instrucción:

new Contador()

el compilador busca un método con el mismo nombre de la clase y que se corresponda con la llamada en cuanto al tipo y número de parámetros. Dicho método se llama Constructor, y una clase puede tener más de un constructor (no así un objeto o instancia, ya que una vez que fue creado no puede recrearse sobre sí mismo).

En tiempo de ejecución, al encontrar dicha instrucción, el intérprete reserva espacio para el objeto/instancia, crea su estructura y llama al constructor.

O sea que el efecto de new Contador() es, precisamente, reservar espacio para el contador e inicializarlo en cero.

En cuanto a los otros métodos, se pueden llamar desde otros objetos (lo que incluye a las aplicaciones) del mismo modo que se llama una función desde C.

Por ejemplo, usemos nuestro contador en un programa bien sencillo que nos muestre cómo evoluciona:

// Usemos nuestro contador en una mini-aplicación
// GRABAR EN UN ARCHIVO "Ejemplo1.java" (OJO CON LAS MAYUSCULAS!)
// COMPILAR CON: "javac Ejemplo.java" (NO OLVIDAR EL .java!)
// EJECUTAR CON: "java Ejemplo1" (SIN el .java)

import java.io.*; // Uso la biblioteca de entradas/salidas

public class Ejemplo1 { // IMPORTANTE: Nombre de la clase
// igual al nombre del archivo!
// entero para asignarle el valor del contador e imprimirlo
// aunque en realidad no me hace falta.
static int n;
// y una variable tipo Contador para instanciar el objeto…
static Contador laCuenta;

// ESTE METODO, MAIN, ES EL QUE HACE QUE ESTO SE COMPORTE
// COMO APLICACION. Es donde arranca el programa cuando ejecuto "java Ejemplo1"
// NOTA: main debe ser public & static.
public static void main ( String args[] ) {
System.out.println ("Cuenta… "); // Imprimo el título
laCuenta = new Contador(); // Creo una instancia del Contador
System.out.println (laCuenta.getCuenta()); // 0 - Imprimo el valor actual (cero!)
n = laCuenta.incCuenta(); // 1 - Asignación e incremento
System.out.println (n); // Ahora imprimo n
laCuenta.incCuenta(); // 2 - Lo incremento (no uso el valor…
System.out.println (laCuenta.getCuenta()); // …de retorno) y lo imprimo
System.out.println (laCuenta.incCuenta()); // 3 - Ahora todo en un paso!
}
}

En el capítulo III vamos a analizar este programa en detalle. Por ahora veamos la diferencia con un applet que haga lo mismo: 


// Applet de acción similar a la aplicación Ejemplo1
// GRABAR EN ARCHIVO: "Ejemplo2.java"
// COMPILAR CON: "javac Ejemplo2.java"
// PARA EJECUTAR: Crear una página HTML como se indica luego
import java.applet.*;
import java.awt.*;

public class Ejemplo2 extends Applet {
static int n;
static Contador laCuenta;

// Constructor…
public Ejemplo2 () {
laCuenta = new Contador();
}

// El método paint se ejecuta cada vez que hay que redibujar
// NOTAR EL EFECTO DE ESTO CUANDO SE CAMBIA DE TAMAÑO LA
// VENTANA DEL NAVEGADOR!
public void paint (Graphics g) {
g.drawString ("Cuenta...", 20, 20);
g.drawString (String.valueOf(laCuenta.getCuenta()), 20, 35 );
n = laCuenta.incCuenta();
g.drawString (String.valueOf(n), 20, 50 );
laCuenta.incCuenta();
g.drawString (String.valueOf(laCuenta.getCuenta()), 20, 65 );
g.drawString (String.valueOf(laCuenta.incCuenta()), 20, 80 );
}
}

Ahora es necesario crear una página HTML para poder visualizarlo. Para esto, crear y luego cargar el archivo ejemplo2.htm con un browser que soporte Java (o bien ejecutar en la ventana DOS: "appletviewer ejemplo2.htm"):

<HTML>
<HEAD>
<TITLE>Ejemplo 2 - Applet Contador</TITLE>
</HEAD>
<BODY>
<applet code="Ejemplo2.class" width=170 height=150>
</applet>
</BODY>
</HTML>

Para terminar este capítulo, observemos las diferencias entre la aplicación standalone y el applet:

~- La aplicación usa un método main, desde donde arranca
~- El applet, en cambio, se arranca desde un constructor (método con el mismo nombre que la clase)

Además:

~- En la aplicación utilizamos System.out.println para imprimir en la salida estándar
~- En el applet necesitamos "dibujar" el texto sobre un fondo gráfico, por lo que usamos el método g.drawString dentro del método paint (que es llamado cada vez que es necesario redibujar el applet)

Con poco trabajo se pueden combinar ambos casos en un solo objeto, de modo que la misma clase sirva para utilizarla de las dos maneras:


// Archivo: Ejemplo3.java
// Compilar con: javac Ejemplo3.java
import java.applet.*;
import java.awt.*;
import java.io.*;

public class Ejemplo3 extends Applet {
static int n;
static Contador laCuenta;

public Ejemplo3 () {
laCuenta = new Contador();
}

public static void main(String args[]) {
laCuenta = new Contador();
paint();
}

public static void paint () {
System.out.println ("Cuenta...");
System.out.println (laCuenta.getCuenta());
n = laCuenta.incCuenta();
System.out.println (n);
laCuenta.incCuenta();
System.out.println (laCuenta.getCuenta());
System.out.println (laCuenta.incCuenta());
}
public void paint (Graphics g) {
g.drawString ("Cuenta...", 20, 20);
g.drawString (String.valueOf(laCuenta.getCuenta()), 20, 35 );
n = laCuenta.incCuenta();
g.drawString (String.valueOf(n), 20, 50 );
laCuenta.incCuenta();
g.drawString (String.valueOf(laCuenta.getCuenta()), 20, 65 );
g.drawString (String.valueOf(laCuenta.incCuenta()), 20, 80 );
}
}

Esta clase puede ejecutarse tanto con "java Ejemplo3" en una ventana DOS, como cargarse desde una página HTML con:

<applet code="Ejemplo3.class" width=170 height=150>
</applet>

Notar que conviene probar el applet con el appletviewer ("appletviewer ejemplo3.htm"), ya que éste indica en la ventana DOS si hay algún error durante la ejecución. Los browsers dejan pasar muchos errores, simplemente suprimiendo la salida a pantalla del código erróneo.

Notar que en todo este desarrollo de las clases Ejemplo1, Ejemplo2 y Ejemplo3, en ningún momento volvimos a tocar la clase Contador! Aquí un ejemplo en video para que nos quede un poco mas claro la esctructura de una clase Estructura de una Clase