Skip to content

3 Convenciones

JavaBean

Los JavaBeans son un modelo de componentes para la construcción de aplicaciones en Java. Se usan para encapsular varios objetos en un único objeto (la vaina o Bean en inglés), para hacer uso de un solo objeto en lugar de varios más simples. La especificación de JavaBeans los define como "componentes de software reutilizables que se puedan manipular visualmente en una herramienta de construcción".

Para funcionar como una clase JavaBean, una clase debe obedecer ciertas convenciones sobre nomenclatura de métodos, construcción y comportamiento. Estas convenciones permiten tener herramientas que puedan utilizar, reutilizar, sustituir y conectar JavaBeans.

Las convenciones requeridas son:

  • Debe tener un constructor sin argumentos.
  • Sus atributos de clase deben ser privados.
  • Sus propiedades deben ser accesibles mediante métodos get y set que siguen una convención de nomenclatura estándar.
  • Debe ser serializable.

Dentro de un JavaBean podemos distinguir tres partes:

  • Propiedades: Los atributos que contiene.
  • Métodos: Se establecen los métodos get y set para acceder y modificar los atributos.
  • Eventos: Permiten comunicar con otros JavaBeans

Métodos get y set

Los métodos get y set son métodos de las clases para mostrar o modificar el valor de un atributo. Para mostrar se utiliza el método get y para modificar el método set.

Según las convenciones JavaBean, la nomenclatura de ambos debe ser la siguiente:

  • get: - Debe ser declarado con el modificador de acceso public. - El nombre del método comienza con get y le sigue el nombre del atributo en UpperCamelCase. En el caso de los booleanos, el nombre del método comienza con is. - El tipo de retorno del método debe ser el mismo que el tipo del atributo.
  • set: - Debe ser declarado con el modificador de acceso public. - El nombre del método comienza con set y le sigue el nombre del atributo en UpperCamelCase. - El tipo de retorno del método debe ser void. - El tipo del parámetro del método debe ser el mismo que el tipo del atributo.

Hacer uso de este convenio nos facilitará trabajar con el resto del mundo y nos permitirá ampliar las capacidades de nuestro código utilizando frameworks existentes que hacen uso del convenio y que si no seguimos no podremos utilizar.

En los IDEs, se pueden generar de forma automática.

Vamos a incluir en la clase Vehicle los getters y setters. Para ello, nos tenemos que plantear qué atributos vamos a permitir consultar y modificar. En cuanto a la consulta, vamos a permitir consultar todos los atributos por lo que tendremos que realizar 3 getters. En cuanto a las modificaciones, el número de ruedas de un vehículo no cambia a lo largo del tiempo por lo que no hace falta ponerle un método set. La velocidad se va modificando con los métodos de acelerar y frenar por lo que tampoco le vamos a poner un método set. En cuanto al color, vamos a permitir que un vehículo pueda cambiar de color por lo que sí vamos a hacerle un método set al color.

public class Vehicle {
    private int wheelCount; // Nº ruedas
    private double speed; // Velocidad
    private String color; // Color del vehículo

    public int getWheelCount() {
        return wheelCount;
    }

    public void setWheelCount(int wheelCount) {
        this.wheelCount = wheelCount;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public double getSpeed() {
        return speed;
    }

    public void accelerate(double amount){ // acelerar
        speed += amount;
    }
    public void brake(double amount){ // frenar
        speed -= amount;
    }
}

Fijémonos en el método setColor:

public void setColor(String color) {
    this.color = color;
}

Tenemos dos variables que se llaman igual: color. Una es un parámetro y otra es un atributo. Para diferenciarlas, el atributo se utiliza con la palabra this. El uso de this se explica con detenimiento más adelante.

En el caso de los booleanos, el getter comienza por is. Si la clase Vehicle tuviera un atributo booleano llamado empty para detectar cuándo está vacío el depósito de gasolina, el getter se llamaría isEmpty():

private boolean empty;
public boolean isEmpty(){
    return empty;
}
Ejercicio 2

Cree un paquete llamado exercise02 y copie la clase Persona del ejercicio anterior. Luego, realice las modificaciones necesarias para poder modificar y acceder a los atributos sin necesidad de usar directamente el atributo. Crea un método Main donde le solicite al usuario todos los atributos y muéstrelos por pantalla haciendo uso de dichos métodos.

Constructores

Un constructor es un método que se invoca cuando se crea un objeto y que sirve para inicializar los atributos del objeto y para realizar las acciones pertinentes que requiera el mismo para ser creado. El constructor tiene el mismo nombre que la clase y para invocarlo se utiliza el operador new.

Vehicle car = new Vehicle(); //(1)!
  1. Vehicle() es un constructor de la clase Vehicle

En los constructores no se especifica tipo de retorno:

public class Vehicle {
    private int wheelCount; // Nº ruedas
    private double speed; // Velocidad
    private String color; // Color del vehículo

    public Vehicle(){
        wheelCount = 4;
        speed = 0;
        color = "blanco";
    }
    public int getWheelCount() {
        return wheelCount;
    }

    public void setWheelCount(int wheelCount) {
        this.wheelCount = wheelCount;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public double getSpeed() {
        return speed;
    }

    public void accelerate(double amount){ // acelerar
        speed += amount;
    }
    public void brake(double amount){ // frenar
        speed -= amount;
    }
}
public class Main {
    public void showDefaultConstructor(){
        Vehicle car1, car2;
        car1 = new Vehicle();
        car2 = new Vehicle();

        System.out.printf("Coche1: %d ruedas y de color %s\n", car1.getWheelCount(), car1.getColor());
        System.out.printf("Coche2: %d ruedas y de color %s\n", car2.getWheelCount(), car2.getColor());

        System.out.printf("Velocidad del coche1: %.2f km/h\n", car1.getSpeed());
        System.out.printf("Velocidad del coche2: %.2f km/h\n", car2.getSpeed());

        System.out.println("Aceleramos el coche1 a 90,50km/h");
        car1.accelerate(90.50);
        System.out.printf("Velocidad del coche1: %.2f km/h\n", car1.getSpeed());

        System.out.println("Aceleramos el coche2 a 20,30km/h");
        car2.accelerate(20.30);
        System.out.printf("Velocidad del coche2: %.2f km/h\n", car2.getSpeed());
    }

    public static void main(String[] args) {
        new Main().showDefaultConstructor();
    }
}
Coche1: 4 ruedas y de color blanco
Coche2: 4 ruedas y de color blanco
Velocidad del coche1: 0,00 km/h
Velocidad del coche2: 0,00 km/h
Aceleramos el coche1 a 90,50km/h
Velocidad del coche1: 90,50 km/h
Aceleramos el coche2 a 20,30km/h
Velocidad del coche2: 20,30 km/h

El constructor que no tiene parámetros se llama constructor por defecto, como por ejemplo Vehicle(). Si nos fijamos en la salida por consola, los dos coches tienen los mismos datos ya que el constructor por defecto crea todos los objetos de la misma manera. Para poder crear objetos diferentes, tendremos que usar un constructor con parámetros:

public class Vehicle {
    private int wheelCount; // Nº ruedas
    private double speed; // Velocidad
    private String color; // Color del vehículo

    public Vehicle(){
        wheelCount = 4;
        speed = 0;
        color = "blanco";
    }

    public Vehicle(int wheelCount, String color) {
        this.wheelCount = wheelCount;
        this.color = color;
        speed = 0;
    }

    public int getWheelCount() {
        return wheelCount;
    }

    public void setWheelCount(int wheelCount) {
        this.wheelCount = wheelCount;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public double getSpeed() {
        return speed;
    }

    public void accelerate(double amount){ // acelerar
        speed += amount;
    }
    public void brake(double amount){ // frenar
        speed -= amount;
    }
}
public class ConstructorParameterized {
    public void show(){
        Vehicle car, moto;
        car = new Vehicle(4, "azul");
        moto = new Vehicle(2, "rojo");

        System.out.printf("Coche: %d ruedas y de color %s\n", car.getWheelCount(), car.getColor());
        System.out.printf("Moto: %d ruedas y de color %s\n", moto.getWheelCount(), moto.getColor());
    }

    public static void main(String[] args) {
        new ConstructorParameterized().show();
    }
}
Coche: 4 ruedas y de color azul
Moto: 2 ruedas y de color rojo

Al tener parámetros el constructor, esto nos permite poder crear objetos diferentes.

En los IDEs, se puede generar el constructor con parámetros de forma automática.

Los constructores se pueden sobrecargar, por lo tanto una clase puede tener varios constructores, en el ejemplo anterior la clase Vehicle mantiene el constructor por defecto, además del constructor con parámetros.

public class ShowConstructors {
    public void show(){
        Vehicle car, moto;
        car = new Vehicle();
        moto = new Vehicle(2, "rojo");

        System.out.printf("Coche: %d ruedas y de color %s\n", car.getWheelCount(), car.getColor());
        System.out.printf("Moto: %d ruedas y de color %s\n", moto.getWheelCount(), moto.getColor());
    }
}

Si una clase no tiene constructor, Java crea uno por defecto. Los atributos se inicializan a su valor por defecto en función del tipo que posean:

  • Tipos numéricos enteros: 0
  • Tipos numéricos decimales: 0
  • Caracteres: Carácter nulo (Código Unicode 0)
  • Booleanos: false
  • Referencias a objetos: null

Solo se inicializan los atributos, las variables locales de los métodos no son inicializados por defecto.

¡OJO!

Java solamente crea un constructor cuando la clase no tiene ninguno, pero si la clase tiene un constructor, aunque sea con parámetros, Java ya no crea ninguno por defecto.

Si la clase posee algún constructor con parámetros pero se usa Class() el compilador nos da un mensaje de error de que el constructor no está definido.

Ejercicio 3

Crea un paquete llamado exercise03 y copia la clase persona del ejercicio anterior. Crea un método constructor para dicha clase que asigne los siguientes valores a sus atributos:

nombre = "Sin nombre" edad = 0 altura = 0.0f ocupacion = "sin ocupación"

Crea un Main que declare un objeto de tipo persona utilizando el constructor, para posteriormente mostrar el contenido de sus atributos por pantalla.

Ejercicio 4

Crea un paquete llamado exercise04 y copie la clase persona del ejercicio anterior. Crea un método constructor con parámetros sin anular el ya creado. Realiza un Main que declare un objeto tipo persona utilizando dicho constructor y muestre el contenido posteriormente por pantalla.

Visibilidad

La visibilidad de los atributos y métodos de una clase se establece utilizando los modificadores de acceso.

Los modificadores de acceso permiten dar un nivel de seguridad mayor a nuestras aplicaciones restringiendo el acceso a diferentes atributos y métodos asegurándonos que el cliente no va a consultar el valor de un atributo que no debe, no va a modificar incorrectamente el valor de un atributo o que no va a utilizar un método que no le esté permitido. Cuando nos referimos al término cliente es cualquier programador que utilice nuestras clases.

Tal y como vimos en el apartado 2. Modificadores de acceso, se resume su funcionamiento en la siguiente tabla:

Private Friendly Public
Misma clase x x x
Mismo paquete x x
Otro paquete x

Veamos un ejemplo de la clase Vehicle que está en el mismo paquete que una clase cliente Main.

Vamos a comprobar la visibilidad que tiene la clase Main sobre la clase Vehicle en función de los modificadores de acceso. Tal y como podemos observar en la tabla anterior, tendrá acceso a public y a friendly pero no a private

public class Vehicle {
    private int wheelCount; // Nº ruedas
    private double speed; // Velocidad
    private String color; // Color del vehículo
    public Vehicle(int wheelCount, String color) {
        this.wheelCount = wheelCount;
        this.color = color;
        speed = 0;
    }
    int getWheelCount() {
        return wheelCount;
    }
    public void setWheelCount(int wheelCount) {
        this.wheelCount = wheelCount;
    }
    public String getColor() {
        return color;
    }
    public void setColor(String color) {
        this.color = color;
    }

    public double getSpeed() {
        return speed;
    }

    public void accelerate(double amount){ // acelerar
        speed += amount;
    }
    public void brake(double amount){ // frenar
        speed -= amount;
    }
}
public class Main {
    public void showVisibility(){
        Vehicle car = new Vehicle(4, "azul");

        System.out.printf("El coche tiene %d ruedas\n", car.getWheelCount()); //(1)!

        car.accelerate(100); //(2)!

        System.out.printf("El coche va a %.2f km/h\n", car.speed); //(3)!
    }
}
  1. getWheelCount es visible porque es friendly y la clase Main está en el mismo paquete que la clase Vehicle.
  2. accelerate es visible porque es public.
  3. Error de compilación: speed no es visible porque es private
Ejercicio 5

Cree un paquete exercise05 copiando la clase Persona del exercise04 y modifica al acceso a algunos de sus métodos, haciéndolos public, private o friendly y realiza las siguientes operaciones y observa si da o no error, justificando sus respuesta con comentarios:

  • Crea un método main dentro de la clase Persona y crea un objeto persona, intente acceder a todos sus métodos.
  • Crea una clase Main dentro del paquete exercise_05 y realice la misma operación anterior
  • Crea un paquete llamado exercise05_bis y una clase Main realizando la misma operación anterior

instanceof

El operador instanceof permite comprobar si un determinado objeto pertenece a una clase concreta. Se utiliza de esta forma:

object instanceof class

Devuelve true si el objeto pertenece a dicha clase.

public class InstanceOf {
    public void show(){
        Vehicle vehicle = new Vehicle();
        System.out.println(vehicle instanceof  Vehicle);
    }

    public static void main(String[] args) {
        new InstanceOf().show();
    }
}