Blocos de inicialização

4 respostas
Java_Player

O que imprime? Por que?

class A {
  { System.out.print("a1 "); }
  public A() { System.out.print("a2 "); }
  static { System.out.print("a3 "); }
}
class B extends A {
  static { System.out.print("b1 "); }
  public B() { System.out.print("b2 "); }
  { System.out.print("b3 "); }
  static { System.out.print("b4 "); }
}
public class C {
	static { System.out.print("c1 "); }
	public static void main(String[] args) {
		System.out.print("c2 ");
		B b;
		System.out.print("c3 ");
		b = new B();
		C c = new C();
		System.out.print("c4 ");
		
	{ System.out.print("c5 "); }
}
	static { System.out.print("c6 "); }
	{ System.out.print("c7 "); }
	public C() { System.out.print("c8 "); }
}

4 Respostas

Omeganosferatu

Pequeno erro … lol

Eu tinha feito tudo isso mas com C extendendo B :frowning: … dai errei …hehehe

Mas é bem legal esse exercicio eu fiz aqui mas nem vou postar, eu ja errei eheheh entao deixa pro próximo… mas essa questão ta muito boa mesmo

R

O programa inicia no método main da classe C. Assim sendo, a primeira coisa que o JVM faz é carregar a classe C. Quando vai fazer isso, ela já roda seus blocos inicializadores estáticos e, com isso, exibe c1 e c6.

Em seguida, o programa começa a rodar o método main. Então exibe c2 e c3. Quando vai rodar b = new B(); ele chama o construtor de B e a JVM precisa carregar a classe B, só que como B herda de A, então primeiro a JVM deve carregar a classe A, rodando seu bloco inicializador estático e exibindo a3. Em seguida, a JVM carrega a classe B exibindo b1 e b4.

Agora ele vai chamar o construtor da superclasse, A, mas como tem um bloco inicializador, esse roda antes do código do construtor e o programa exibe a1. Em seguida roda o código do construtor, exibindo a2.

Agora que vai rodar o construtor de B, primeiro precisa rodar o bloco inicializador, então exibe b3 e, em seguida, roda o construtor, exibindo b2.

Depois, o programa tenta instanciar C e primeiro tem que rodar o bloco inicializador, exibindo c7 e depois roda o construtor, exibindo c8.

Finalmente, o programa exibe c4 e depois o bloco de instruções (válido e que não tem nada de especial), que exibe c5.

Ufa!

Resumindo:

  1. Carrega a classe C e exibe: c1 e c6
  2. Continuando o main exibe c2 e c3
  3. Carrega a classe A e seu bloco inicializador estático exibe a3
  4. Carrega a classe B e seus blocos inicializadores estáticos exibem b1 e b4 (a ordem que estão na classe)
  5. Bloco inicializador em A exibe a1
  6. Construtor de A exibe a2
  7. Bloco inicializador em B exibe b3
  8. Construtor de B exibe b2
  9. Continuando com o main, instancia C e então o bloco inicializador em C exibe c7.
  10. Construtor de C exibe c8
  11. Contunando o main, exibe c4 e depois c5

Questão muito boa, como fiz uma questão parecida com essa no livro da kathy recentemente eu já tinha pensado em alguma variações para tornar a questão do livro da kathy mais difícil e já tinha pensado nas soluções não demorei muito tempo pra resolver.

A questão ficaria ainda mais interessante se ele tentasse instanciar novamente uma classe que tem bloco inicializador estático, pois o mesmo não rodaria novamente e seria uma armadilha a mais pra o pessoal cair.

Java_Player

Podemos garantir que “a3” será impresso antes de “b4”? Ou seja, podemos garantir que a JVM vai carregar as superclasses antes das subclasses?

R

Na verdade, enquanto eu estava fazendo, tive uma duvida maior que essa, embora acho que a resposta seja a mesma para a sua pergunta:

Não apenas entre superclasses e subclasses, podemos garantir que a JVM irá carregar as classes “sob demanda”, ou seja, à medida que há necessidade de utiliza-las? Ou pode haver implementações de JVM que carreguem todas ou algum conjunto de classes ao mesmo tempo em algum momento inicial antes de rodar qualquer código? Nesse caso, não podemos nem mesmo garantir se vai ser impresso primeiro “a3” ou “b1 e b4” ou “c1 e c6”, que são os blocos inicializadores estáticos das classes em questão.

Mas de qualquer forma, se a forma de carregar é “sob demanda”, então em caso de a primeira utilização de uma classe for a chamada a um construtor da subclasse, como o construtor da superclasse vai rodar primeiro, é natural que a superclasse tenha que ser carregada primeiro.

Criado 4 de julho de 2007
Ultima resposta 4 de jul. de 2007
Respostas 4
Participantes 3