(→"super") |
(→Exemplo 1) |
||
Line 76: | Line 76: | ||
Neste exemplo a classe Numero não é carregada (o método "main" de Order1 não a usa). Assim, não há produção de caracteres para a saída. | Neste exemplo a classe Numero não é carregada (o método "main" de Order1 não a usa). Assim, não há produção de caracteres para a saída. | ||
− | < | + | <source lang="java"> |
class Numero { | class Numero { | ||
int x; | int x; | ||
Line 93: | Line 93: | ||
} | } | ||
} | } | ||
− | </ | + | </source> |
− | < | + | <source lang="java"> |
public class Order1 { | public class Order1 { | ||
public static void main(String[] args) {} | public static void main(String[] args) {} | ||
} | } | ||
− | </ | + | </source> |
//output: | //output: |
A construção de objectos em Java segue a modalidade genérica da iniciação de objectos, i.e., primeiro iniciam-se os sub-objectos correspondentes a definições da superclasse e só depois os próprios. Este processo é recursivo, o que significa que a superclasse mais antiga na hierarquia é a que inicia primeiro, sendo seguida pela classe logo abaixo, etc., até chegar à classe cuja instância está a ser criada.
Como já se referiu, a linguagem Java procura esconder do programador pormenores como as especificadades de reserva de memória. No entanto, o programador ainda fica com algumas responsabilidades, nomeadamente na definição e chamadas dos construtores. Esta secção apresenta então os seguintes aspectos relacionados com a construção e iniciação de objectos em Java:
As palavras chave this e super, além das utilizações como auto-referência, permitem a chamada explÃcita a construtores.
Num construtor, esta palavra reservada pode ser utilizada para chamar explicitamente outro construtor da mesma classe. Quando é utilizado desta forma, this pode ocorrer apenas uma vez e deve aparecer como a primeira instrução do construtor.
class A {
A(int i) { /* qualquer coisa */ }
A(float f, int i) {
this(i); // chamada ao outro construtor
/* resto do segundo construtor */
}
}
Num construtor, esta palavra reservada pode ser utilizada para chamar explicitamente outro construtor de uma superclasse. Quando é utilizado desta forma, super pode ocorrer apenas uma vez e deve aparecer como a primeira instrução do construtor.
Definição de uma classe A:
class A {
A(int i) { /* qualquer coisa */ }
A(String etiqueta, int i) {
this(i); // chamada ao outro construtor
/* resto do segundo construtor */
}
}
Definição de uma classe B (subclasse de A):
class B extends A {
B() {
this("etiqueta arbitrária", 123); // chama outro construtor de B
/* uma iniciação qualquer */
}
B(String etiqueta, int quantidade) {
super(etiqueta, quantidade); // chama um construtor de A
/* resto do construtor */
}
}
Quando um objecto é criado, várias acções são realizadas em sequência, algumas das quais apenas uma vez durante a vida de uma aplicação.
As seguintes acções são executadas apenas uma vez:
As seguintes acções são executadas cada vez que um objecto é criado:
Os seguintes exemplos ilustram a ordem de iniciação.
Neste exemplo a classe Numero não é carregada (o método "main" de Order1 não a usa). Assim, não há produção de caracteres para a saída.
class Numero {
int x;
static int a = 7;
{
int b = 1;
System.out.println("non-static block: a = " + a + " b = " + b);
}
static {
int b = 4;
System.out.println("static block: a = " + a + " b = " + b);
}
{
int b = 3;
System.out.println("non-static block: a = " + a + " b = " + b + " x = " + x);
}
}
public class Order1 {
public static void main(String[] args) {}
}
//output:
Neste exemplo, a classe Order2 utiliza um atributo "static" da class Numero, provocando o carregamento da classe e a iniciação e execução de componentes "static".
class Numero {
int x;
static int a = 7;
{
int b = 1;
System.out.println("non-static block: a = " + a + " b = " + b);
}
static {
int b = 4;
System.out.println("static block: a = " + a + " b = " + b);
}
{
int b = 3;
System.out.println("non-static block: a = " + a + " b = " + b + " x = " + x);
}
}
public class Order2 {
public static void main(String[] args) {
Numero.a = 2;
}
}
//output: //static block: a = 7 b = 4
Semelhante ao exemplo 2, mas utilizando o valor alterado.
<java5> class Numero {
int x; static int a = 7; { int b = 1; System.out.println("non-static block: a = " + a + " b = " + b); } static { int b = 4; System.out.println("static block: a = " + a + " b = " + b); } { int b = 3; System.out.println("non-static block: a = " + a + " b = " + b + " x = " + x); }
} </java5>
<java5> public class Order3 {
public static void main(String[] args) { Numero.a = 2; System.out.println("Numero.a = " + Numero.a); }
} </java5>
//output: //static block: a = 7 b = 4 //Numero.a = 2
É criada uma instância da classe Numero. Todas as fases descritas nos exemplos anteriores são executadas. Depois, são executados os blocos anónimos e o contrutor.
class Numero {
int x = 93;
Numero() { System.out.println("Numero.Numero"); }
static int a = 7;
{
int b = 1;
System.out.println("non-static block: a = " + a + " b = " + b);
}
static {
int b = 4;
System.out.println("static block: a = " + a + " b = " + b);
}
{
int b = 3;
System.out.println("non-static block: a = " + a + " b = " + b + " x = " + x);
}
}
public class Order4 {
public static void main(String[] args) {
Numero n = new Numero();
System.out.println("Numero.a = " + Numero.a + " n.x = " + n.x);
}
}
//static block: a = 7 b = 4
//non-static block: a = 7 b = 1
//non-static block: a = 7 b = 3 x = 93
//Numero.Numero
//Numero.a = 7 n.x = 93