Modificadores que no son de Acceso en Java

En anteriores entregas hemos visto los accesos a los miembros, el cual se refiere al código de una clase que puede invocar métodos o acceder a variables de instancia de otra clase. En esta entrada veremos otros modificadores para los miembros, pero que no tienen que ver con el acceso.


Hay otros modificadores que podemos usar en la declaración de los miembros. Dos de ellos ya nos son familiares, final y abstract, porque los hemos aplicado en toras entradas anteriores. Aún así, tendríamos que conocer por encima otros modificadores, como son transient, synchronized, native, strictfp y entonces el Big One, static.

Primero veremos como se aplican estos modificadores a los métodos, y luego cuando se aplican a las variables de instancia.

  • Metodos Final

    La palabra final previene a un método ser sustituido en una subclase, y es a veces usado para hacer cumplir la funcionalidad de un método de una API. Tal y como no podemos crear una subclase de la clase String, tampoco podemos sustituir muchos de los métodos en l núcleo de las librerías de clases. Esta restricción a no poder sustituirse provee seguridad, pero la tendríamos que usar con gran precaución. Prevenir a una subclase que no pueda sustituir un método sofoca muchos de los beneficios de la Orientación a Objetos incluyendo extensibilidad a través del polimorfismo. Una declaración típica de un método final es así:

    				class SuperClass{
    					public final void showSample(){
    						System.out.println("One thing.");
    					}
    				}
    				

    Es legal que alguna clase herede SuperClass, ya que la clase no está marcada como final, pero no podemos sustituir el método final showSample():

    				class SubClass extends SuperClass{
    					public void showSample(){ //Se intenta sustituir el método final
    						System.out.println("Another Thing");
    					}
    				}
    				

    Si intentamos compilar el código anterior, tendremos un error, ya que la subclase no puede sustituir el método declarado como final de la superclase.

  • Argumentos Final

    Los argumentos de un método son declaraciones de variables que aparecen dentro de los parentesis en la declaración de un método. Una declaración de un método típica sería la siguiente:

    				public Record getRecord (int fileNumber, int recNumber){}
    				

    En este ejemplo, las variables fileNumber y recNumber seguirán las reglas que se aplican a las variables locales. Esto significa que tambien pueden tener el modificador final:

    				public Record getRecord (int fileNumber, final int recNumber){}
    				

    La variable recNumber está declarada como final, lo cual quiere dar por supuesto que no puede ser modificada dentro del método. Diciendo “modificar” queremos decir que no se puede reasignar ningún nuevo valor a la variable.

  • Métodos Abstract

    Un método abstract es un método que ha sido declarado (como abstract) pero no ha sido implementado. En otras palabras, el método no contiene código funcional. Su código no contiene {}, sino que se cierran con (;), en otras palabras, NO EXISTE CUERPO EN EL MËTODO. Marcaremos un método como abstract cuando queramos forzar a las subclases que realicen la implementación. A continuación vemos un ejemplo de un método abstract:

    				public abstract void showSample();
    				

    Vemos que el método abstracto termina con (;) en vez de {}. Es ilegal tener un método abstract en una clase que no ha sido explícitamente declarada como abstract. Miremos el siguiente ejemplo, el cual es una clase ilegal:

    				public class IllegalClass{
    					public abstract void doIt();
    				}
    				

    El código nos dará error si intentamos compilarlo, diciendonos que la clase IllegalClass debería ser declarada como abstract.

    Sin embargo, lo que sí podemos hacer es tener una clase como abstract pero sin métodos declarados como abstract. En el siguiente ejemplo veremos que esto compilaría bien:

    				public abstract class LegalClass{
    					void goodMethod(){
    						//Aquí iría la implementación
    					}
    				}
    				

    En el anterior ejemplo, el método goodMethod() no es abstract. Hay 3 trucos que nos dicen que no es un método abstracto:

    • El método no está marcado como abstract.
    • La declaración del método introduce { }, en vez de terminar con (;).
    • El método provee código de implementación.

    La primera subclase concreta de una clase definida como abstract debe implementar TODOS los métodos abstractos de la superclase.

    Cuando decimos clase concreta, queremos decir que no es abstracta, así que si tenemos una clase abstract que herede de otra clase abstract, la subclase abstract no tiene porque proveer de implementación para los métodos heredados.

    				public abstract class Vehicle{
    					private String type;
    					public abstract void goUpHill(); //Método Abstracto
    					public String getType(){		//Método no abstracto
    						return type;
    					}
    				}
    				
    				public abstract class Car extends Vehicle{
    					public abstract void goUpHill(); //Sigue siendo abstracto
    					public void doCarThings(){
    						//Código especial del coche aqui
    					}
    				}
    				
    				public class Mini extends Car{
    					public void goUpHill(){
    						//Código de Especificaciones pra goUpHill
    					}
    				}
    				

    ¿Cuántos métodos tiene la clase Mini? 3. Hereda el método getType() y doCarThings, porque son public y concretos y goUpHill() es abstracto en la superclase Vehicle, y no ha sido implementado nunca en la clase Car.

    Vamos a echar un vistazo a una clase concreta que no provee de implementación del método para los métodos declarados como abstract de la superclase. El siguiente código no compilará:

    				public abstract class A{
    					abstract void foo();
    				}
    				
    				class B extends A{
    					void foo(int I){}
    				}
    				

    La clase B no compilará porque no implementa el método heredado declarado como abstract llamado foo(). A pesar de que aparece un método foo(int I) en la clase B y aunque parezca una implementación del método abstracto de la superclase, es un método sobrecargado (método que usa el mismo identificador, pero con diferentes argumentos), por lo que no cumplirá los requisitos para implementar el método declarado como abstract de la superclase.

    Un método nunca puede, nunca, nunca ser marcado como abstract y final, o ambos abstract y private. Pensemos en ello, los métodos abstract deben ser implementados mientras que final y private no pueden ser sustituidos en la subclase. Los modificadores abstract y final son virtualmente opuestos. Como los métodos privados no pueden ser nunca vistos por la subclase, tampoco pueden ser sustituidos, por lo que no pueden ser marcados como abstract.

    Finalmnente, necesitamos saber que el modificador abstract no puede ser combinado con el modificador static. Lo siguiente sería ilegal:

    				abstract static void doStuff();
    				
  • Métodos Synchronized

    La palabra synchronized indica que un método puede ser accedido por un solo hilo a la vez. Synchronized puede ser aplicado solo a métodos, ni a variables, ni a clases, solo a métodos. Un ejemplo típico de synchronized sería parecido a esto:

    				public synchronized Record retrieveUserInfo(int id){}
    				

    Deberíamos tambien saber que el modificador synchronized puede ser complementado con cualquiera d elos 4 niveles de control de acceso.

  • Métodos Native

    EL modificador native indica que un método es implementado en una plataforma dependiente, como a veces ocurre en C. Native es un modificador y solo puede ser aplicado a métodos, ni a clase, ni a variables, solo a métodos. Tomemos nota de que el cuerpo de los métodos marcados como native pueden terminar en (;) como en los métodos abstract, indicando que la implementadión está omitida.

  • Métodos Strictfp

    Vimos con anterioridad que strictfp es un modificador de clase, pero aunque no declaremos una clase como strictfp, podemos tambien declarar un método individual como strictfp. Strictfp fuerza a los floating points (y cualquier operación con cloating points) a adaptar el standard IEE 754. Con strictfp, podemos predecir como se comportarán los floating points sin tener encuenta la plataforma de JVM en la que se esté ejecutando. Debemos tener en cuenta que podemos modificar una clase o una declaración de un método, y una variable nunca puede ser declarada con strictfp.

  • Métodos con Lista de Variables como Argumento

    Java permite crear métodos que peudan tener un numero variable de argumentos. Podemos oir esta caracteristica como “variable-length argument lists”, “variable arguments”, “var-args”, “varargs” o “variable arity parameter”.

    • Argumentos – Las cosas que especificamos entre parentesis cuando invocamos un método
      							doStuff("a", 2); // A y 2 son argumentos
      							
    • Parámetros – Las cosas que pasamos al método que indica lo que el método debe recibir cuando es invocado:
      							void doStuff(String s, int a){} //Esperamos 2 parámetros, String y int
      							

    Aunque veremos el uso de los métodos con var-arg en otros capítulos, veremos las reglas que se aplican:

    • Tipo Var-arg – Cuando declaramos un parámetro var-arg, debemos especificar el tipo de argumentos que el parámetro de nuestro método puede recibir.
    • Sintaxis Básica – Para declarar un método usando parámetros var-arg, debemos seguir el tipo con (…), un espacio, y entonces el nombre del array que guardará los parámetros recibidos.
    • Otros parámetros – Es legal tener otros parámetros en un método que use var-arg.
    • Limites var-arg – No puede ser el último parámetro en el método, y solo podemos tener un var-arg en un método.

    Vamos a ver algúna declaración legal e ilegal:

    • Legal:
      							void doStuff(int... x){}
      							void doStuff2(char c, int... x){}
      							void doStuff3(Animal... animal){}
      							
    • Ilegal:
      							void doStuff4(int x...){}
      							void doStuff5(int... x, char... y){}
      							void doStuff6(String... s, byte b){}
      							

Hasta aquí un pequeño resumen de los modificadores que no son de acceso, y otros elementos más que nos podemos encontrar en los métodos, como son la lista de argumentos como parámetros.

Sin más, cualquier aporte o corrección es bienvenido.

Saludos!!!