Diario de un Aprendiz de Java

Tuesday, May 31, 2005

Otro ejercicio de seguimiento de flujo

Los ejercicios que encontré ayer en el libro de Java del que tanto he hablado en las últimas entradas del blog me encantaron. Así que hoy, mientras la profesora de física impartía nociones de dinámica durante su soporífera hora, he escrito algo por el estilo. Es un poco más complicado que los anteriores, pero sigue en la misma linea. Consiste en predecir el resultado que imprimiria en pantalla su ejecución.

class Lio {

  public static void changed(int uno, int dos) {
   if((uno + dos) <= 3 && (uno + dos) >= 0) {
    System.out.print(uno + dos);
    geo("kirai",12);
   } else if(uno > 3) {
    System.out.println("Buuuzz!!");
   }
  }

  public static void geo(String paco, int llamada) {
   changed(llamada, llamada);
   System.out.println(paco);
  }

  public static int topstar(int capo) {
   int staedler = 15;
   staedler += capo;
   if(capo > staedler) {
    System.out.println("Tas k si ... ");
    return 5;
   } else {
    System.out.println("Pac||");
    changed(capo,staedler);
    return 10;
   }
  }

  public static void main(String[] args) {
   int tipo = topstar(4);
   System.out.print("Hola " + tipo);
  changed(tipo,-8);
  }

}


Por ahora, no salimos de la clase, pero me han rondado por la cabeza muchas ideas ... que si usar el operador if-else (si, ese tan extraño del que hablé), usar condicionales tipo switch para meter mucha paja y despistar, usar otras clases generando métodos, un poco de herencia, etc ... Solo hay que ser un poco cruel xD

Monday, May 30, 2005

Ejercicios y bajadas de intensidad

Estos últimos días no he posteado tan activamente como de costumbre (si es que una costumbre puede establecerse en un periodo tan corto de tiempo), pero tengo excusa por dos motivos. Primero, estoy hasta el cuello de exámenes de evaluación, y, aunque poco, me quitan algo de tiempo. El otro motivo es el libro que comentava ayer, con el que estoy intentando asimilar conceptos básicos, a la par que repaso mi pobre inglés técnico.
Del citado libro os paso unos ejercicios la mar de interesantes. La cosa consiste en predecir el resultado de la ejecución del codigo, es decir, averiguar lo que imprimiría el codigo en pantalla. Estos son bastante sencillos :

public class Buzz {

  public static void baffle (String blimp) {
   System.out.println(blimp);
   zippo ("ping", -5);
  }

  public static void zippo (String quince, int flag) {
   if (flag < 0) {
    System.out.println(quince + " zoop");
   } else {
    System.out.println("ik");
    baffle(quince);
    System.out.println("boo-wa-ha-ha");
   }
  }

  public static void main(String[] args) {
   zippo("rattle",13);
  }
}


public class Narf {

  public static void zoop(String fred, int bob) {
   System.out.println(fred);
   if (bob == 5) {
    ping("not ");
   } else {
    System.out.println("!");
   }
  }

  public static void main(String[] args) {
   int bizz = 5;
   int buzz = 2;
   zoop("just for", bizz);
   clink(2*buzz);
  }

  public static void clink(int fork) {
   System.out.print("It's ");
   zoop("breakfast ", fork);
  }

  public static void ping(String strangStrung) {
   System.out.println("any" + strangStrung + "more ");
  }
}


Son unos ejercicios muy sencillos, pero muy entretenidos. Además son muy útiles, porque muchas veces nos encontraremos con que la salida del programa que acabamos de escribir no será exactamente lo que teníamos en mente, así que tendremos que recorrer el codigo en busca del error de planteamiento, y ejercicios tipo este, en el que tienes que seguir el flujo del codigo, sirven para entrenar esta faceta del programador.

Sunday, May 29, 2005

Leyendo sobre Java

He encontrado un libro muy interesante sobre Java, titulado How to think like a Computer Scientist, Java Version. Su autor, Allen B. Downey, lo escribió por el mismo motivo que muchos escriben libros básicos sobre temas técnicos; daba clases y no encontró ningún texto que se adaptara a sus necesidades. Además esta licenciado bajo GNU Free Documentation License.
Con el estoy aprendiendo, aparte de Java, a empezar a pensar como un programador y a llamar a las cosas por su nombre, y es que al autor pone mucho énfasis en la nomenclatura.
También estoy reaprendiendo (en extensión y en calidad) muchas cosas básicas sobre Java y sus métodos más típicos. Por ejemplo, no sabía que println fuera la unión de print line, ni que existiera el print, que no escribe un salto de linea al final del texto, al estilo del printf de C. Y es que, como dice un amigo ...

Creerse sabio es caer en lo más profundo de la ignorancia.

Saturday, May 28, 2005

El modificador STATIC

Una de los posibles usos de el modificador static es compartir el valor de una variable miembro entre objetos de una misma clase. Si declaramos una variable miembro de una clase, todos los objetos que declaremos basandonos en esa clase compartiran el valor de aquellas variables a las que se les haya aplicado el modificador static, y se podrá modificar el valor de este desde todas.
Un caso en el que nos podría ser muy util este modificador, es en una clase que nos diga la cantidad de objetos que se han creado basandose en ella. Podemos meter una linea de codigo en el constructor que incremente la variable contador con el modificador static, y asi cada vez que se declare un objeto el contador se incrementará. Desde cualquier objeto podremos consultar el valor del contador. El codigo sería algo asi
class Clase {
  static int contador;

  Clase() {
   contador++;
  }

  int getContador() {
   return contador;
  }
}


class Codigo {
  public static void main(String[] args) {
   Clase uno = new Clase();
   Clase dos = new Clase();
   Clase tres = new Clase();
   Clase cuatro = new Clase();
   System.out.println("Hemos declarado " + uno.getContador() + " objetos.");
  }
}

Esto tiene varias ventajas, porque además de ahorrarnos algunas posiciones de memoria (porque todos objetos comparten la misma) podemos crear variables compartidas, cosa que abre la puerta a suculentas posibilidades.

Las palabras reservadas THIS y SUPER

Después de un tiempo sin postear (y sin dedicarle demasiado a Java) por culpa de determinadas obligaciones académicas, vuelvo a la carga para explicar una cosa muy sencilla.
Java nos da estas herramientas para poder hacer nuestro codigo más entendible. La palabra reservada this permite especificar que la variable que señala (y la señala haciendo this.nombreVariable) es de la misma clase en la que se usa.
Os podeis preguntar .. ¿para que me sirve esto, si ya se sobreentiende? ¡Yo nunca voy a usar dos variables con el mismo nombre!
Pues yo os voy a comentar un caso en el que this nos permite crear codigo mucho más facil de entender para aquel que lo lee (y por tanto, más sencillo para nosotros cuando lo tengamos que releer/modificar/mejorar). Mirad el siguiente codigo :
class RGB {
  int red, green, blue;

  RGB(int red, int green, int blue) {
   this.red = red;
   this.green = green;
   this.blue = blue;
  }
}

Como veis, el nombre de los argumentos que se pasan en el constructor son los mismos que las variables de la clase, así que para asignar los valores sin hacer tonterias (tipo red = red, :D) debemos usar this. En este caso, el poder usar los nombres red/green/blue en los argumentos nos permite evitar comentar el codigo para indicar que eso es el constructor principal y tal (como nos pasaría si hicieramos algo como RGB(int x, int y, int z)), ya que solo dandole un vistazo al codigo se entiende perfectamente su función.

No me cansaré de decirlo. Para lograr un buen source es importante no repetir fragmentos de codigo, usar tipos de variables acorde a la necesidad (si vas a hacer un bucle que solo se repita 50 veces, ¿porque usar un int como contador, cuando puedes usar un byte y ahorrar memoria?), establecer nombres de variables que expresen con claridad lo que van a contener, y comentar solo cuando haga falta. Estas son las claves más sencillas, pero también las más fundamentales.

La palabra reservada super sirve para indicar que una variable o un método es de la superclase (espero que os acordeis de nuestra querida heréncia :D). Os pongo un codigo para que entendais su uso
class SuperClase {
  boolean variableBool;

  void setVariableBool() {
   variableBool = true;
  }
}

class SubClase extends SuperClase {
  boolean variableBool;

  void setVariableBool() {
   variableBool = false;
   super.setVariableBool();

   System.out.println("La variable de aqui es " + variableBool);
   System.out.println("La de la superclase es " + super.variableBool);
  }
}

class Codigo {
  public static void main(String[] args) {
   SubClase objetoPrueba = new SubClase();
   objetoPrueba.setVariableBool();
  }
}

Como veis, en este codigo la superclase y la subclase tienen una variable y un método que tienen el mismo nombre, pero que hacen funciones diferentes, y los distingimos usando super.
Aún asi, el poner el mismo nombre a dos variables diferentes no es una buena manera de hacer las cosas, porque puede llevar a confusiones, e incluso el JavaCompiler nos indica warning cuando compilamos el codigo

servomac@ubuntu:~/coding/java $ javac Codigo.java

Issued 1 semantic warning compiling "Codigo.java":

10. boolean variableBool;
^----------^
*** Semantic Warning: Field "variableBool" shadows a field of the same name in "SuperClase".

De nuevo me limpio las manos, y dejo a elección del programador el uso de distintos métodos/variables con el mismo nombre.
Espero que tanto this como super os ayuden a entender un poco mejor a Java. ¡Saludos!

Tuesday, May 24, 2005

Sobrecarga, de métodos y de constructores

Los constructores son métodos, con el mismo nombre de la clase, que sirven para definir el valor de las variables de la clase cuando creas el objeto.
Un ejemplo sería este
class UnaClase {
  byte unaVariable, otraVariable;

/*Ahora crearemos el constructor. Como veis, tiene el mismo nombre que la clase.*/
  UnaClase(byte x, byte y) {
   unaVariable = x; otraVariable = y;
  }
}

Con este constructor ya definido, podremos asignar valores a las variables de la clase justo en el momento en que creamos el objeto.
UnaClase objeto1 = new UnaClase(10,12)
Como podeis ver, en este caso la variable unaVariable del objeto objeto1 tendría el valor 10, y objeto1.otraVariable valdría 12.

Por otro lado, es muy posible que diferentes objetos que se basan en la misma clase no necesiten usar el mismo constructor. Imaginemos una clase Clientes, con su nombre, su edad y el nombre de la empresa como variables. De algunos de los objetos que creemos basandonos en esta base conoceremos todos los datos, pero siempre habrá alguno del que desconozcamos la edad, o incluso su nombre. Aqui entra en juego la sobrecarga de constructores, que consiste en crear un constructor para cada posibilidad (real[*]) que tengamos.

[*]Como estoy cansado de decir, se tiene que conseguir un equilibrio entre usabilidad (muchos constructores) y codigo entendible (pocos constructores). El programador eficiente debe ser capaz de declarar solo aquellos constructores que realmente se van a usar, sin caer en la tentació de crear constructores para todos los posibles casos, por muy incoherentes que parezcan.

class Cliente {
  String nombre, nombreEmpresa;
  int edad;

/*El constructor que viene a continuación se usará en el caso de que se conozcan todas las variables*/
  Cliente(String nombre, String nombreEmpresa, int edad) {
   this.nombre = nombre;
   this.nombreEmpresa = nombreEmpresa;
   this.edad = edad;
  }

/*También es provable que conozcamos el nombre del cliente, y el nombre de su empresa, pero desconozcamos su edad. Por esto vamos a declarar un constructor asi. */
  Cliente(String nombre, String nombreEmpresa) {
   this.nombre = nombre;
   this.nombreEmpresa = nombreEmpresa;
  }
}

class Sobrecarga {
  public static void main(String [] args) {
   String nombre, empresa;
   int edad;

/*Ahora creamos un objeto basandonos en la clase cliente, imaginando que conocemos todos los valores*/
   Cliente paco = new Cliente("Paco","EmpresaFalsa",55);
/*Aqui un objeto de la clase Cliente del que desconocemos la edad*/
   Cliente julian = new Cliente("Julian","EmpresaFalsa");

   nombre = paco.nombre;
   empresa = paco.nombreEmpresa;
   edad = paco.edad;

   System.out.println(nombre + ", de " + empresa + ", tiene " + edad);

   nombre = julian.nombre;
   empresa = julian.nombreEmpresa;
   edad = julian.edad;

   System.out.println(nombre + " trabaja en " + empresa + ".");
  }
}


La sobrecarga de métodos es justo lo mismo; creamos varios métodos con el mismo nombre que actuen diferente segun el tipo de los parámetros de entrada. Por ejemplo, queremos hacer un método que devuelva el resultado de la suma de los dos parametros de entrada, pero no sabemos si será un entero o si tendrá decimales, así que tendremos que hacer un método para el caso de los decimales, y otro con el mismo nombre para el caso de los enteros.

class Calculadora {
  int suma(int x, int y) {
   return (x + y);
  }

  float suma(float x, float y) {
   return (x + y);
  }
}

class Servo {
  public static void main(String[] args) {
   int operacion1;
   float operacion2;

   Calculadora sumador = new Calculadora();
   operacion1 = sumador.suma(2,3);
   operacion2 = sumador.suma(0.23F, 12.53F);

   System.out.println("La suma de los enteros 2 y 3 es " + operacion1);
   System.out.println("Sumando 0.23 y 12.53, se consigue " + operacion2);
  }
}

Monday, May 23, 2005

Ejercicios básicos

Buscando por la red he encontrado unos ejercicios propuestos de clases y objetos, y he empezado a hacerlos. Son parte de la asignatura de Programación Orientada a Objetos de la Universidad de Murcia. Podeis encontrar su página web en este enlace. En la parte teórica de la asignatura se trabaja con los lenguajes orientados a objetos Eiffel, C++ y Java, pero las prácticas se entregan solo en este último, Java.

El enunciado de lo primero que he hecho dice asi :

1.- Implementar la clase Posicion que represente un punto (x,y) en el eje de las coordenadas. Cada posición viene definida por dos valores enteros x e y. Las operaciones disponibles son:

    · Constructor por defecto, se corresponde con la posición (0,0).
    · Constructor al que se le pasa como parámetro los valores inciales de las coordenadas X e Y.
    · Constructor de copia.
    · Métodos para modificación y consulta (set/get) de los atributos de la clase.
    · Métodos para incrementar y decrementar los valores de cada una de las coordenadas de la posición (incX, incY, decX, decY).
    · Un método para establecer los valores de las coordenadas (setXY).


Y siguiendo este enunciado, he escrito este codigo

class Posicion {
  int x, y;

/*Constructor por defecto*/
  Posicion() {
   this.x = 0;
   this.y = 0;
  }

/*Constructor al que se le pasa como parámetro los valores
iniciales de las coordenadas X e Y.*/
  Posicion(int x, int y) {
   this.x = x;
   this.y = y;
  }

/*Métodos para modificación y consulta*/
  void setX(int x) {
   this.x = x;
  }

  void setY(int y) {
   this.y = y;
  }

  int getX() {
  return x;
  }

  int getY() {
   return y;
  }

/* Métodos para incrementar y decrementar los atributos*/
  void incX() {
   x++;
  }

  void incY() {
   y++;
  }

  void decX() {
   x--;
  }

  void decY() {
   y--;
  }

/*Método para establecer los valores de las coordenadas*/
  void setXY(int x, int y) {
   this.x = x;
   this.y = y;
  }
}


Como veis, lo único que me falta es el constructor de copia, pero es algo que no he hecho nunca y aún desconozco. Queda en la lista de cosas TO-LEARN (pero en la lista que realmente se va siguiendo, no el otra en la que dejas los temas imposibles .. xD).
¡Aprovecho para pedir rectificaciones y/o ayudas en el codigo, se agradece mucho si alguien lo revisa! ¡Saludos!

Sunday, May 22, 2005

Operador if-else

Java tiene un operador que nos sirve para asignar un valor a una varible, dependiendo de una condición determinada. Tiene esta estructura :
[variable] = [condicion]?[valorSiVerdadero]:[valorSiFalso];

He aqui algun ejemplo :
byte numero;    //Declaramos la variable numero
numero = 10;    //Le asignamos el entero 10
boolean variBoleana;    //Declaramos la variable variBoleana
variBoleana = numero < 50 ? true : false;    /*como 10 es menor que 50, a variBoleana le es asignado el valor true*/


Esto puede suponer un ahorro de lineas de codigo, y es una ventaja si se conoce bien este operador, pero tiene sus repercusiones negativas; si se desconoce el codigo puede parecer un poco críptico en aquellos casos en que el programador abuse de este asignador. Así que la elección de su uso o desuso se deja en manos del programador experimentado, que debe elegir dependiendo de la situación.
Personalmente creo que lo ideal es que los que lean codigo fuente conozcan el lenguaje que estan manteniendo, así que lo importante es conocer realmente bien el funcionamiento de este operador y no hacerse lios. Si tu realmente dominas el lenguaje Java (y esto incluye este tipo de operadores) no hace falta sacrificar más tiempo codeando en pos del codigo entendible. Hay que saber encontrar un equilibrio entre codigo facil de mantener en un futuro, cómodo a la hora de escribir, y potente y adequado a la hora de ejecutarse.

Sentencia condicional IF en Java

La sentencia condicional if/else tiene esta forma
if(condicion)
{
  //Codigo a ejecutar si se cumple la condición
}
else
{
  //Codigo a ejecutar si la condición es falsa
}

La condición debe ser un enunciado boleano (verdadero o falso), i se pueden usar varios operadores. Los más importantes son los de igualdad (variable1 == variable2, devuelve true si ambas variables contienen lo mismo), diferencia (variable1 != variable2, devuelve true si son diferentes), mayor que (variable1 > variable2, con el resultado verdadero si la primera variable es mayor a la segunda), menor que (variable1 < variable2, con el resultado verdadero si la primera variable es menor a la segunda), mayor o igual que (variable1 >= variable2, que devuelve true cuando la variable1 es mayor o igual que la variable 2), menor o igual que (variable1 <= variable2, también devuelve true cuando la segunda variable es mayor o igual que la primera).

Como condición también podemos tener a un booleano. He aqui un ejemplo
boolean verdadero = true;
if(verdadero) {
  System.out.println("Esto se ejecutará, porque la condición resulta verdadera.");
}
else {
  System.out.println("Esto no se ejecutará.");
}


También podemos usar operadores lógicos para crear sentencias condicionales algo más complejas, como && (AND), || (OR) o ! (NOT). Por ejemplo, imaginad que tenemos un numero entero, i queremos que se imprima en pantalla cuando este comprendido entre 10 y 20. Para esto tenemos que comprovar que el numero sea mayor o igual que 10, pero también debe ser menor o igual que 20, así que usaremos el && (AND).
if (numero >= 10 && numero <= 20)
{
  System.out.println(numero);
}

Ahora imaginad que queremos imprimir un numero que este comprendido entre 10 y 20 o entre 30 y 40. Si el numero es 15, se imprimirá en pantalla, si es 25 no, pero si es 35 también se imprimirá. Para esto tenemos que mezclar los operadores AND (&&) y OR (||).

if ( (numero >= 10 && numero <= 20) || (numero >= 30 && numero <= 40) )
{
  System.out.println("El numero " + numero + " esta comprendido entre 10 y 20 o entre 30 y 40");
}


Hasta aqui (y más en extensión, porque yo solo he comentado los mecanismos que más conozco) el IF que se implementa en Java es igual al de PHP, C, y otros lenguajes, usando incluso los mismos operadores.

Saturday, May 21, 2005

¿Qué es esto de la herencia?

Una de las características de los lenguajes de programación orientada a objetos (POO) es la herencia. La herencia es un mecanismo que nos permite crear nuevas clases basandonos en clases ya creadas, y nos ayuda a evitar la repetición de codigo.
Imaginemad que necesitamos crear una aplicación que nos ayude a catalogar los animales que nos encontremos cuando paseemos por el bosque. Todos tendran elementos en común (todos tendrán patas, así como todos tendrán un nombre científico, etc ...), que podremos establecer como variables en la clase principal, que llamaremos Animal. Pero también tendrán peculiaridades dependiendo de si són mamiferos u otros, así que tendremos que hacer subclases que contengan las peculiaridades de los insectos y demás, además de las própias de todos los animales. Aqui es cuando entra en juego la herencia, ya que gracias a ella podemos crear subclases que heredaran las variables y los métodos de su clase "madre", además de poder añadir nuevos métodos y nuevas variables a la nueva subclase.
En Java especificamos cual es la clase de la que debe heredar variables y métodos mediante inclusión de la palabra reservada extends seguida del nombre de la clase madre, justo después de el nombre de la subclase.
class nombreSubclase extends claseMadre {
  /*Variables y métodos própias de la subclase*/
}

En este caso la clase nombreSubclase heredaría las variables y los métodos de la clase claseMadre.

Añado un pequeño codigo que ejemplifica el uso de la herencia de manera muy básica. Ya sabeis que para compilar el codigo le debeis dar el nombre de la clase en la que este el método main seguido de la extensión .java (en este caso seria Herencia.java).

class Animal {   //La clase madre
  String nombre;
  byte numeroPatas;
}

class Mamifero extends Animal {    /*Toma Animal como clase madre*/
  byte mesesGestacion;

  void nombreAnimal() {
   System.out.println(nombre);
  }
}

class Herencia {
  public static void main(String[] args) {
   Mamifero humano = new Mamifero();    //Creamos el objeto humano
   humano.nombre = "Homo Sapiens";
   humano.numeroPatas = 2;
   humano.mesesGestacion = 9;
   humano.nombreAnimal();
  }
}

Friday, May 20, 2005

Fe de erratas

Ya he encontrado dos errores en mis anteriores posts, y estoy muy orgulloso de ello :D. No, no soy como el gilipollas de Buenafuente, pero es que mi intención con este blog era ir corrigiendome y a la vez transmitiendo algo, para quien quisiera leer a alguien en apuros xD.
Lo que he visto que estava mal, es que cuando hablé de los tipos de variables me dejé a un tipo muy importante, las variables tipo String. Como debeis saber los que conozcais algun lenguaje de programación, los strings són cadenas de caracteres. Un ejemplo práctico :
String cadenaCaracteres;
cadenaCaracteres = "hola, soy una variable tipo string";
System.out.println(cadenaCaracteres);

Debeis fijaros en que esta va a contracorriente, ya que todos los tipos de variables se indican en minúscula (int, char, boolean), y en canvio esta va en mayúscula. Cuando me entere realmente porque lo publicaré :P.

El otro error es que, en el codigo en el que explicava (o intentava explicar) lo que eran los métodos, creé métodos que servian para definir el valor de las variables que formavan la clase. Esto puede dar lugar a confusiones, ya que parece que las variables de una clase no se pueden definir/establecer desde otro método, y no es asi, simplemente pones el nombre del objeto y el nombre de la variable a definir separados por un punto, como si fuera un método. De nuevo me respaldo en el código para intentar explicarme, porque tampoco me doy demasiado a entender :P
class Zapato {
  String marca;
  byte numeroPie;
  byte precioEuros;
}

class Principal {
  public static void main(String[] args)      //Método principal
   Zapato allStar = new Zapato();      /*Creamos el objeto allStar, con la clase Zapato como plantilla*/
   allStar.marca = "Converse";      /*A la variable marca del objeto allStar de asignamos el string Converse*/
   allStar.numeroPie = "40";
   allStar.precioEuros = "50";
  }
}

¡¡Espero que lo entendais, almenos yo me quedo más tranquilo y digo un par de chorradas menos en el blog :D!!

Thursday, May 19, 2005

Clases, métodos y objetos

Para todos aquellos que nos iniciamos en el mundo de la programación orientada a objetos y en especial en el mundo de Java, hay tres vocablos técnicos que oimos hasta la saciedad en los manuales, tutoriales y cursos, pero que tanto para quien empiezan en el mundo de la programación como para aquellos que vienen del paradigma de la programación estructurada son un tanto dificiles de entender; las clases, objetos y métodos. Por esto intentaré explicar por encima "quien es quien" en el mundo de la POO, y como podemos implementarlo en Java, ya que son la espina dorsal de este lenguaje de programación.
Una clase es un conjunto de primitivos y métodos relacionados entre si. Ya expliqué lo que eran los primitivos,
ahora le toca a los métodos. Un método es parecido a lo que, en programación estructurada se llama función. Es decir, un fragmento de codigo al que se llama, acompañado de unos datos de entrada, y produce una determinada salida. Para esto tenemos que indicar el tipo de los primitivos de entrada, el tipo de los de salida, el nombre del método y el trabajo que realizara.
[tipoPrimitivoSalida] [nombreMétodo] ([tipoPrimitivoEntrada] [nombrePrimitivoEntrada]) {
 //Codigo del método
  return primitivoSalida;
}

Para ser más explicitos, vamos a poner un ejemplo porque no creo que me haya explicado demasiado bien. Imagina que queremos hacer un método al que le pasamos un parametro determinado (un primitivo tipo int) y devuelva el resultado del primitivo de entrada más 5. Primero definimos el tipo del primitivo de entrada y el de salida (en nuestro caso ambos seran tipo int). Seguidamente, le damos un nombre (en este caso lo he bautizado como sumaCinco) y lo escribimos :
int sumaCinco(int entrada) {
  return entrada + 5;
}

Para usar este método, podemos hacer lo siguiente
int numero;
numero = sumaCinco(10);
System.out.println("El resultado es " + numero + ".");

Como podeis imaginar, el resultado es, efectivamente, 5.
Un detalle importante que me he olvidado comentar es el tema de los modificadores. No entraré demasiado en detalle con esto, pero debemos saber que para usar un método desde otro método tipo static (como el método main, que se declara como public static void main(String[] args)). Otro tipo de modificador es el public, que permite que el método sea usado desde otro paquete. Pero como en nuestros pequeños programas aún no usamos paquetes, lo dejaremos para otro dia. Para terminar con esto, una cosa muy importante, debo decir que los modificadores se especifican justo antes de poner el tipo del primitivo de salida. Completando el esquema de un método estandar que había empezado antes, nos queda esto
[modificadores] [tipoPrimitivoSalida] [nombreMétodo] ([tipoPrimitivoEntrada] [nombrePrimitivoEntrada]) {
  //Codigo del método
  return primitivoSalida;
}


Ahora que ya sabemos lo que son los primitivos y los métodos, podemos crear una clase. Como he dicho al principio, una clase es un conjunto de primitivos y métodos, así que también podemos hacer un esquemilla de como sería una clase estandar
class NombreClase {
  //Primitivos

  //Métodos
}

Así como los nombres de los primitivos empiezan con una minúscula por convención, los nombres de clases empiezan con una mayúscula por el mismo motivo.
Para dejarlo claro, hagamos un ejemplo. Queremos crear una clase que nos permita "simular" un disco de música. Los parametros que definen un disco son su título, el nombre del grupo que lo edita, el estilo de música de sus canciones, el número de canciones, el nombre de la productora, y demás. Estos serían los primitivos de la clase. ¿Y que pasa con los métodos? Pues en nuestra clase DiscoMusica podrían ser métodos que especificaran estos valores (los primitivos) para cada cd de nuestra coleccion. Un método llamado definirEstilo, al que le pasasemos un string con el nombre del estilo de música, y un método para definir cada primitivo. Para ponernos lo sencillo y no complicarnos con el uso de strings o arrays, solo trabajaremos con enteros, y simplificaremos mucho la clase. También pondré un método que nos devuelva el número de componentes del grupo, mediante un returnEl codigo sería asi
class DiscoMusica {
  int numeroCanciones;
  int numeroComponentesGrupo;
  int añoPublicacion;

  void definirNumeroCanciones(int numero) {
   numeroCanciones = numero;
  }

  void definirNumeroComponentes(int num) {
   numeroComponentesGrupo = num;
  }

  void definirAño(int año) {
   añoPublicacion = año;
  }

  int devolverNumeroComponentes() {
   return numeroComponentesGrupo;
  }
}

¡Hecho, una clase que pseudo define un disco! Tenemos primero los tres primitivos, y luego sus métodos que los definen. Muy bien, pero esto define un disco genérico. Imaginemos que queremos hacer una clasificacion de 3 discos, ¿tengo que hacer una clase diferente para cada uno de ellos? ¡Pues claro que no, porque aqui entran en juego los famosos objetos! Un objeto no es más que una personalificación de una clase, el conjunto de primitivos y métodos definidos en la clase, que ahora definen un objeto determinado (por ejemplo, disco1, disco2, disco3 ...). Para definir un objeto, debemos especificar en que clase se basará, con la siguiente sintaxis
[nombreClase] [nombreObjeto] = new [nombreClase]();
Por ejemplo, para crear un objeto llamado disco1 basado en la clase que creamos anteriormente, hacemos
DiscoMusica disco1 = new DiscoMusica();
Ahora que ya tenemos el objeto disco1, podemos asignar un valor a sus primitivos. Podemos usar los métodos del objeto disco1 que hemos creado usando la clase DiscoMusica (como veis, en esta frase se resumen los 3 conceptos que quiero dejar claros) usando el nombre del objeto junto con el nombre del método a usar, separados por un punto entre ellos
[nombreObjeto].[nombreMétodo]([primitivosEntrada]);
En nuestro caso, vamos a especificar el número de componentes, canciones y el año publicación del disco1
disco1.definirNumeroCanciones(14);
disco1.definirNumeroComponentes(3);
disco1.definirAño(2005);

También podemos usar el método que nos devuelve el numero de componentes del objeto disco1
System.out.println("Hay " + disco1.devolverNumeroComponentes() + " músicos.");
Con esto imprimimos por pantalla la cadena "Hay ", concatenada (el operador + suma numeros, pero también sirve para unir dos o más cadenas) con el resultado de disco1.devolverNumeroComponentes(), y también lo concatena con la cadena " músicos.". El resultado es Hay 3 músicos., que es imprimido por pantalla.

Si has llegado aqui, espero que te haya quedado claro todo lo explicado aqui. Ahora mismo publico el codigo fuente de la explicación, totalmente funcional, en otra entrada. ¡Saludos!

Wednesday, May 18, 2005

Variables (Codigo de respaldo)

class Ejemplo {
  public static void main(String[] args) {
   boolean verdaderoFalso; //Declaramos una variable de cada tipo
   byte enteroBits8;
   short enteroBits16;
   int enteroBits32;
   long enteroBits64;
   float comaFlotanteSimple;
   double comaFlotanteDoble;

   verdaderoFalso = true; //Asignamos valores a las variables
   enteroBits8 = 15;
   enteroBits16 = -30500;
   enteroBits32 = 9878677;
   enteroBits64 = 99999999999L; //Recordad que se pone una L al final
             // del numero para especificar que se trata de un long
   comaFlotanteSimple = 222.22F; //Para indicar que es un float, una F
   comaFlotanteDoble = 6545.123243D; //Para double ponemos una D al final
  }
}

Variables

Uno de los pilares principales de la programación es el uso de variables. En Java encontramos muchos tipos de variables, capaces de almacenar todos los tipos de datos que necesitemos. Pero al estar hablando de programación Orientada a Objetos tenemos que diferenciar variables de objetos. Las variables, en Java, son llamados primitivos. Simplemente almacenan un valor. En canvio, un objeto es un conjunto de variables y métodos. Como aún no hemos tratado los conceptos de clase y objeto, tan importantes en Java, la explicación anterior puede parecer difusa. No os preocupeis, que cuando tenga realmente claros los mecanismos de declaración y uso de clases escribiré un pequeño apunte aclaratorio sobre ellas. Hasta el momento, los que ya sabeis algo de programación podeis tratar a los primitivos como variables de toda la vida.
Tenemos distintos tipos de primitivos :

· boolean. Este tipo de variable solo puede tomar dos valores, o true o false. Por defecto, si no se le asigna ningún valor, le corresponde el valor false.
· char. Las variables de caracteres pueden contener cualquier caracter, tanto numeros, como letras, como signos. El valor por defecto es NULL.
· byte. Esta variable puede comprender valores numéricos enteros entre -128 y +127. Se caracteriza por su ligereza, ya que solo ocupa 8 bits (un byte), pero su utilidad es reducida.
· short. Igual que byte, pero ocupando el doble de memoria (dos bytes) y permitiendo asignar valores mucho más grande (exactamente desde -32768 hasta 32767). También debe ser un valor entero.
· int. Ocupa 32 bits (4 bytes), pero permite asignar valores en un rango especialmente grande; desde -2147483648 hasta 2147483647. Como en los tipos byte y short, el valor por defecto es 0.
· long. Las variables tipo long ocupan 64 bits (8 bytes), ya que sus valores pueden jugar dentro de un rango amplisimo (de -9223372036854775808 a 9223372036854775807 :D). Al igual que sus hermanos pequeños (byte, short e int), su valor por defecto es 0. Una cosa muy importante es que a la hora de asignar un valor a este tipo de variables, teneis que indicar que se trata de un long añadiendo una L (mayuscula) al final del numero. Luego publicaré un ejemplo práctico.
· float. Hasta ahora hemos hablado de variables para almacenar enteros, pero muchas veces necesitaremos representar numeros reales con decimales y demás. Para esto sirve float (y su hermana mayor, double). Ocupa 32 bits. Su precision es muy pobre, y se pueden obtener resultados extraños trabajando con numeros grandes. Trataremos este tema en más profundidad en próximos comentarios, apoyado de codigo fuente.
· double. Igual que float, pero mayor, ocupando 64 bits. Intenta arreglar los problemas de la coma flotante simple (float).

Ahora que ya sabemos los tipos de primitivos con los que contamos, y que la declaración de variables es simplemente tipoPrimitivo nombreVariable;, debemos saber que hay algunas convenciones a la hora de dar nombre a las variables, para hacer codigo más entendible. Los variables deben hablar de los datos que contienen, cosa que permite una mejor identificación. No podemos dar el nombre haceCalor a un primitivo tipo string que contiene el nombre del usuario de la aplicación, solo provocario lios a la hora de mejorar/ampliar/estudiar el codigo. Un nombre adecuado para la variable sería nombreUsuario. Como habreis notado, la primera letra del nombre de variable siempre debe estar en minúscula, y si usamos más de una palabra la primera letra de la segunda palabra la ponemos en mayuscula. Así, si queremos dar nombre a una variable que contenga el numero de dias del més de febrero, podríamos poner numeroDiasFebrero. Otra cosa importante es que no se pueden usar palabras reservadas de Java, como class o main.

Cuando tenemos una variable declarada (para seguir el lenguaje estricto de Java deberíamos decir "un primitivo referenciado"), toca asignarle un valor. Esto se hace mediante el operador =. Ahy van algunos ejemplos :

byte contador;
contador = 100;
short dieciseisBits;
DieciseisBits = 30500;
boolean verdaderoFalso;
verdaderoFalso = true;


Continuará ...

Tuesday, May 17, 2005

Hello, world!

Me parecía una verguenza tener un blog sobre mis inicios en Java y no publicar un Hola mundo, asi que ahi va ;)

public class Holas {
  public static void main(String[] args) {
   System.out.println("Buenas, soy un aprendiz de Java!");
  }
}


Como veis, creamos una clase llamada Holas, dentro de la cual definimos el método principal (main), que siempre se ejecuta. La función System.out.println imprime en pantalla la string que le pases como parámetro, en este caso Buenas, soy un aprendiz de Java! (viva la originalidad xD).

Debeis saber que en java, el fichero que contenga el codigo fuente debe llevar como nombre el de una de las clases que en el se usen (normalmente la principal) seguido de la extensión ".java". Como en este caso solo usamos una clase, llamada Holas, al fichero del source code (codigo fuente) lo llamamos "Holas.java". Con el JavaCompiler, creamos el bytecode a partir del codigo fuente que acabamos de escribir con el siguiente comando

$ javac Holas.java

Si no el compilador no encuentra ningún error, ya tendremos nuestro ByteCode con el nombre del archivo de codigo fuente, pero sin la terminación .java. Asi que en el fichero Holas tendremos un ByteCode preparado para pasar por nuestra JVM de la siguiente manera

$ java Holas

Y en la consola se nos imprimira el resultado. ¡¡Ya hemos creado nuestro primer programa en Java!!

Historia de Java

El título de este post es lo que he buscado en Google, y después de leerme un par de textos sobre su historia, he escrito este pequeño resumen.

El diseño de Java se inició a finales de la década de los 80, cuando Sun Microsystem montó un equipo, formado por James Gosling y otros, con el objetivo de crear un lenguaje de programación multiplataforma. El requisito de que fuera multiplataforma era crucial, ya que las aplicaciones inmediatas de este iban a ser su uso en dispositivos eléctronicos, que funcionavan con chips de todos los tipos, y no era viable canviar el codigo para cada plataforma (como hubiera sido necesario usando lenguajes como C o C++).
En 1991 James Gosling escribió el primer compilador para un lenguaje bastante primitivo, al que bautizaron como Oak, que significa Roble en inglés. Sobre este nombre circulan varias "leyendas urbanas" que intentan explicarlo, pero la que más se lee por la red es que cerca del lugar donde se reunía el grupo encargado del desarrollo de el nuevo lenguaje había un gran roble.
El primer proyecto importante basado en Java (aún conocido como Oak) fué el conocido Proyecto Green, un sistema de control completo de los aparatos electrónicos de una casa. Otro fué el desarrollo de una televisión interactiva. Pero ninguno de los dos tuvo el reconocimiento suficiente como para ser un producto de masas, y podríamos decir que Java se relegó a un segundo plano.
Aprovechando el boom de internet, Sun, de manera muy astuta, decidió apostar por una unión entre Java y la nueva red de redes. Si se incorpora una Java Virtual Machine en un navegador, cualquier ordenador conectado a la red sería capaz de ejecutar el Java Aplet, con independencia de su arquitectura y el sistema operativo que ejecutase. Asi que en 1995 lanzaron HotJava, el primer navegador con una JVM. El canvio de nombre se produjo aqui, ya que el nombre comercial Oak ya estava registrado por otra empresa. Una de las leyendas que rodean a Java explica que se llama así porque el grupo de trabajo de Sun que trabajava en él se reunía en una cafetería para hablar sobre el desarrollo del lenguaje, y Java es el nombre con el que se designa de manera coloquial el café en Estados Unidos.
No pasaría mucho tiempo hasta que subieran al carro de navegadores con soporte para aplets de java, como Netscape con su Netscape Navigator 2.0, todo sumado a las licencias que se otorgaron a empresas como IBM, Microsoft, y Novell para que escribieran sus propios JVM para otros sistemas operativos.
Java ha seguido creciendo hasta el dia de hoy, y está consolidado como un lenguaje sério y adecuado, llegnado a ser uno de los más utilizados.

Monday, May 16, 2005

Un par de links

Para empezar, voy siguiendo dos cursos bastante diferentes.
El primero está escrito por Sun (imagino que es el manual oficial de los developers :P) y está traducido al español por gente de programacion.com. Empieza de zero y es muy completo y detallado. Lo podeis encontrar en este enlace.
El otro está un poco mal estructurado, pero los ejemplos de codigo que añade vienen muy bien para aprender un poco leyendo. Es este.
Ala, ya sabeis, ¡a estudiar Java! :D

Declaracion de intenciones

¡Bienvenidos, navegantes! Me voy a presentar, soy un aprendiz de programador, y acabo de empezar a filtrear con Java. Mi intención es hacer de este blog un lugar enfocado a Java y a la programación orientada a objectos en general, aunque estoy empezando. Se algo de C, algo de PHP, algo de perl ... pero nunca he trabajado con POO. Conceptos como la herencia, las clases, el Garbage Colector y demás me son totalmente desconocidos, pero poco a poco espero ir aprendiendo, a la par que intentaré hacer crecer esta pequeña ventana dónde hacerme oir, con mis aventuras en el mundo del codigo.