1.5 Declaración de miembros de clase - ajpaez/OCA GitHub Wiki

(OCA Objectives 2.1, 2.2, 2.3, 2.4, 2.5, 4.1, 4.2, 6.2, and 6.6)

Los métodos y variables de instancia (no locales) se conocen colectivamente como miembros. Dichos miembros pueden ser declarados con modificadores de acceso y no de acceso.

#Modificadores de acceso Los miembros de una clase pueden usar cuatro modificadores:

  • public
  • protected
  • default
  • private

El modificador por defecto es el que se tiene cuando no se escribe ningún modificador de acceso en la declaración del miembro.

Es necesario comprender dos accesos diferentes:

  • Cuando el código de un método en una clase puede acceder a miembros de otra clase
  • Cuando una subclase puede heredar miembros de su superclase.

El primer tipo de acceso se produce cuando un método de una clase intenta acceder a un método o una variable de otra clase, usando el operador punto (.) para invocar a un método o recuperar una variable. Por ejemplo:

class Zoo {
  public String coolMethod() {
    return "Wow  baby";
  }
}
class Moo {
  public void useAZoo() {
    Zoo z = new Zoo();
    // If the preceding line compiles Moo has access to the Zoo class
    // But... does it have access to the coolMethod()?
    System.out.println("A Zoo says, " + z.coolMethod());
    // The preceding line works because Moo can access the public method
  }
}

El segundo tipo de acceso gira entorno a los miembros de una superclase que son accedidos desde una subclase por herencia. Estamos viendo como una hereda un miembro exactamente como si la subclase lo hubiese implementado.

class Zoo {
  public String coolMethod() {
    return "Wow  baby";
 }
}
class Moo extends Zoo {
  public void useMyCoolMethod() {
    // Does an instance of Moo inherit the coolMethod()?
    System.out.println("Moo says, " + this.coolMethod());
    // The preceding line works because Moo can inherit the public method
    // Can an instance of Moo invoke coolMethod() on an instance of Zoo?
    Zoo z = new Zoo();
    System.out.println("Zoo says, " + z.coolMethod());
    // coolMethod() is public, so Moo can invoke it on a Zoo reference
  }
}

##Miembros públicos Cuando un miembro, bien una variable o un método, es declarado como publico, esto significa que todas las otras clases, independientemente del paquete al que pertenezcan, puede ser accedido (suponiendo que la clase es visible). Para una subclase, si un miembro de la superclase es declarado como publico, la subclase lo hereda aunque no se encuentre en el mismo paquete.

##Miembros protected Un miembro protected puede ser accedido por herencia por una subclase incluso si la subclase esta en un paquete diferente. La subclase puede acceder a el a través de this, por ejemplo, pero no a través del operador punto, ya que no puede instanciar un objeto de la superclase y esperar poder utilizar el miembro protected. A grandes rasgos protected=herencia. Las clases que hereden de la subclase que ya heredaba de la superclase que contiene el miembro protected no tienen acceso a los miembros protecteds.

##Miembros default Ambos modificadores de control de acceso son casi idénticos, pero con una diferencia. Un miembro default puede ser accecido solo si la clase que quiere acceder a el está en el mismo paquete.

##Miembros privados Los miembros declarados como privados solo pueden ser accedidos desde el miembro que lo declare. Si se intentan llamar desde otra clase, es como si no existiesen. ¿Qué ocurre con la herencia de métodos privados? Cuando se declara un miembro como privado este no puede heredarse. Por tanto una subclase no podrá ver ni utilizar un miembro privado de la superclase. Por todo lo anterior, puede existir en la subclase un método que se llame igual al privado de la superclase, esto no se considera overriding!!.

##Variables locales y modificadores de acceso. Los modificadores de acceso nunca aplican a variables locales.

Combinaciones de modificadores de acceso y su visibilidad:

Visibility Public Protected Default Private
From the same class Yes Yes Yes Yes
From any class in the same package Yes Yes Yes No
From a subclass in the same package Yes Yes Yes No
From a subclass outside the same package Yes Yes, through inheritance No No
From any nonsubclass class outside the package Yes No No No

Modificadores de no acceso

##Métodos Final La palabra reservada final previene que un método sea sobreescrito en una sublclase previniendo que se modifique su comportamiento. Evitar que una clase sobreescriba un método reprime muchos de los beneficios de OO incluyendo la extensibilidad a traves del polimorfismo. Si intentamos sobreescribir un método final, el compilador se queja. ##Argumento Final Los argumentos usados en un método, que son esencialmente como una variable local, también se pueden marcar como final, y conseguir con ello que no se puedan modificar dentro del método. En otras palabras, un argumento final debe mantener el mismo valor que el parámetro tenía cuando fue pasado al método. ##Métodos Abstract Un método abstracto es un método que ha sido declarado ( como abstracto) pero no implementado. El método no contiene código funcional. Con esto, estamos obligando a las subclases a crear una implementación para el.

RECUERDA: No pueden existir métodos abstractos en una clase no abstracta, pero si existir una clase abstracta sin métodos abstractos.

Los métodos abstractos no tiene cuerpo

public abstract void goFast();

Cualquier clase que extienda de una clase abstracta debe implementar todos los métodos abstractos de la superclase, a menos que la subclase sea también abstracta. Un método no puede ser marcado NUNCA como abstract y final, como abstract y private o como abstract y static.

##Métodos sincronizados Que un método sea sincronizado indica que puede ser accedido por un solo hilo al mismo tiempo. Este modificador solo aplica a métodos.

##Métodos nativos El modificador nativo indica que el método esta implementado en una plataforma independiente de código, a menudo en C. Solo se aplica a métodos.

##Métodos strictfp Indica que el método que se marca con este modificador respetara el IEEE 754 al trabajar con datos en punto flotante independientemente de la arquitectura subyacente a la JVM. Solo aplica a clases y métodos.

##Métodos con lista de argumentos variable (var-args) Desde Java 5, se permite a los métodos tomar un numero variable de argumentos.

  • Argumento: Lo que se especifica entre paréntesis cuando tu estas invocando a un método .

doStuff("a",1); // "a" y 2 son argumentos

  • Parámetro: Lo que se indica en la firma de un método que indica lo que el método debe recibir cuando sea invocado

void doStuff(String a, int i) {} // String e int son argumentos

Declaraciones de var-args:

  • Tipos de var-args: cuando se declara un parámetro var-agas se debe especificar el tipo de argumento, un primitivo o un objeto.
  • Sintaxis: Para declarar un parámetro var-args se debe indicar después del tipo una elipsis ( ... ), un espacio y a continuación el nombre de array que almacenará los datos recibidos.
  • Otros parametros: Se pueden indicar otros parámetros junto con var-args.
  • Limite de var-args: el parametro var-args debe ser el ultimo indicado en la firma del método y solo se puede declarar uno por metodo.ç
Declaracion legales con var-args:
+ void doStuff(int... x) { }              // expects from 0 to many ints as parameters
+ void doStuff2(char c, int... x)  { }    // expects first a char, then 0 to many ints
+ void doStuff3(Animal... animal) { }     // 0 to many Animals
Declaracion ilegales con var-args:
- void doStuff4(int x...) { }             // bad syntax
- void doStuff5(int... x, char... y) { }  // too many var-args
- void doStuff6(String... s, byte b) { }  // var-arg must be last

#Declaración de constructores Los objetos usados en Java necesitan ser construidos. Todas las clases tienen un constructor, aunque no se cree de forma explícita el compilador creará uno.

class Foo {
  protected Foo() { }        // this is Foo's constructor
  protected void Foo() { }   // this is a badly named, but legal, method
}
  • Tiene que tener el mismo nombre que la clase.
  • Un constructor no puede tener nunca un valor de retorno.
  • Pueden tener todos los modificadores de acceso normales.
  • Pueden declarar argumentos y var-args.
  • No pueden ser final o abstract.
class Foo2 {
  // legal constructors
  Foo2() { }
  private Foo2(byte b) { }
  Foo2(int x) { }
  Foo2(int x, int... y) { }
  // illegal constructors
  void Foo2() { }            // it's a method, not a constructor
  Foo() { }                  // not a method or a constructor
  Foo2(short s);             // looks like an abstract method
  static Foo2(float f) { }   // can't be static
  final Foo2(long x) { }     // can't be final
  abstract Foo2(char c) { }  // can't be abstract
  Foo2(int... x, int t) { }  // bad var-arg syntax
 }

#Declaración de variables

Existen dos tipos de variables en Java:

  • Primitivas: puede ser de una de los 8 tipos existentes [char, boolean, byte, short, int, log, double o float], cuando una variable primitiva se declara su tipo no puede cambiar nunca, aunque su valor cambie.
  • Variables de referencia: las variables de referencia son usadas para referirse o acceder a los objetos. Son declaradas de un tipo especifico y nunca puede cambiar, aunque si pueden almacenar subtipos del tipo declarado.

##Declaración de primitivas y sus rangos Pueden ser declaradas como variables de clase (static), variables de instancia, parámetros de métodos o variables locales. Se permite declarar varias en la misma linea. Las variables de tipo numérico, tanto los enteros como los de punto flotante tienen signo. Se representa por el bit mas significativo. Así, si un byte tiene 8 bits, el primero representa el signo ( 0, positivo 1 negativo) y los siete restantes el valor del dato.

Tipo Bits Valor Mínimo Valor Máximo
byte 8 -2^7 -2^7 - 1
short 16 -2^15 -2^15 - 1
int 32 -2^32 -2^32 - 1
long 64 -2^64 -2^64 - 1
float 32 n/a n/a
double 64 n/a n/a

Los bit que necesita un boolean depende de la maquina virtual. Los de tipo char solo contiene un caracter, representado por 16 bit Unicode.

##Declaración de variables de referencia Las variables de referencia pueden ser usadas como variables estáticas, variables de estancia, parámetros de métodos o variables locales. Se permite declarar varias en la misma linea.

##Variables de instancia Una variable de instancia esta definida dentro de una clase, pero fuera de cualquier método y se inicializa cuando la clase se instancia. Son los campos que pertenecen a cada objeto único.

class Employee {
  //  define fields (instance variables) for employee instances
  private String name;
  private String title,
  private String manager;
  // other code goes here including access methods for private
  // fields
}
  • Pueden usar cualquiera de los cuatro modificadores de acceso
  • Pueden ser final, y transient
  • NO pueden ser abstract, synchronized, strictfp, native o static

Comparación de modificadores de variables y métodos:

Variables locales Variables (non-local) Métodos
final final final
public public
protected protected
private private
static static
transient
volatile
abstract
synchronized
strictfp
native

Variables locales

Una variable local es una variable declarada dentro de un método. Su scope es el método. Las variables locales se almacenan siempre en el stack, no en el heap. Si la variable local está en el stack y esta referencia a un objeto, el objeto todavía estará en el heap. No existen los objetos de stack, solo las variables de stack. Solo permiten el modificar final. Las variables locales no tiene valor por defecto. Es posible declarar variales locales con el mismo nombre que las variables de instancia, esto se conoce como shadowing. (para esto tenemos la ayuda de this)

##Declaración de array Son objetos que almacenan variables del mismo tipo o de sublcases con la misma superclase. Pueden contener datos primitivos o referencias de objetos. El objeto del array se almacena en el heap.

Primitivos Objetos
int[] key; String [] strings;
int key []; String strings [];

Declaración de array multidimensional:

String[][][] occupantName; String[] managerName [];

Nunca se debe indica el tamaño del array en su declaración:

ILEGAL: int [2] arr; El código nunca compilará. La JVM no asigna el espacio hasta que en realidad no se instancia el objeto.

##Variables Final Declarar una variable como final, significa que no se va a poder reasignar una vez inicializada con un valor explicito ( que no es lo mismo que por defecto). Para primitivas significa que una vez asignado un valor este no puede ser alterado. Para las de referencia significa que no se podrá reasignar a un objeto diferente, el estado del objeto se pueden cambiar, pero la variable de referencia no puede ser cambiada para que se refiera a otro objeto diferente. Cuando se declara una variable como final, esta debe de ser inicializada cuando la instancia que la contiene sea construida, sino el codigo no compilará. Por tanto, una variable final se debe inicialiar cuando se declara, en un codigo statico o en cada costructor que tenga la clase.

No existen objetos finales, solo referencias finales

##Variables transient Cuando se indica una variable como transient se le está indicando a la JVM que no tenga en cuenta dicha variable a la hora de serializar el objeto que la contiene.

##Variables volatile El modificador volatile indica al compilador que es posible que dicho atributo vaya a ser modificado por varios threads de forma simultanea y asíncrona, y que no queremos guardar una copia local del valor para cada thread a modo de caché, sino que queremos que los valores de todos los threads estén sincronizados en todo momento, asegurando así la visibilidad del valor actualizado a costa de un pequeño impacto en el rendimiento.