Chamar um método Java sem nome


101

Estou olhando o código abaixo e encontrei algo um pouco estranho:

public class Sequence {
    Sequence() {
        System.out.print("c ");
    }

    {
        System.out.print("y ");
    }

    public static void main(String[] args) {
        new Sequence().go();
    }

    void go() {
        System.out.print("g ");
    }

    static {
        System.out.print("x ");
    }
}

Eu esperava que isso gerasse um erro de compilação, já que System.outcom "y" não pertence a uma declaração de método, apenas a { }. Por que isso é válido? Não vejo como esse código seria ou deveria ser chamado.

Ao executar isso, ele x y c gtambém produz , por que o static { }get é chamado antes do construtor de sequência?

Respostas:


149

Este:

static {
        System.out.print("x ");
    }

é um bloco de inicialização estático e é chamado quando a classe é carregada. Você pode ter quantos deles quiser em sua classe e eles serão executados na ordem em que aparecem (de cima para baixo).

Este:

    {
        System.out.print("y ");
    }

é um bloco de inicialização e o código é copiado no início de cada construtor da classe. Portanto, se você tiver muitos construtores de sua classe e todos eles precisarem fazer algo comum no início, você só precisa escrever o código uma vez e colocá-lo em um bloco de inicialização como este.

Portanto, sua saída faz todo o sentido.

Como Stanley comentou abaixo, consulte a seção no tutorial do Oracle que descreve os blocos de inicialização para obter mais informações.


12
Ótima resposta. Saiba mais sobre o bloco de inicialização em http://docs.oracle.com/javase/tutorial/java/javaOO/initial.html
Stanley

6
the code is copied into the beginning of each constructor of the class- isso está incorreto. Digamos que o construtor comece com super("x ");, o superconstrutor será executado antes de qualquer bloco de inicialização.
RokL

3
sim, as chamadas implícitas e explícitas para o superconstrutor serão executadas primeiro, o bloco de inicialização a seguir e depois o resto do código do construtor.
jlordo

25

Não é um método, mas um bloco de inicialização .

 {
    System.out.print("y ");
 }

Ele será executado antes da chamada do construtor. Enquanto

static {
        System.out.print("x ");
       }

é um bloco de inicialização estática que é executado quando a classe é carregada pelo carregador de classes.

Portanto, quando você executa seu código
1. A classe é carregada pelo carregador de classes para que o bloco de inicialização estático seja executado
Saída: x é impresso
2. O objeto é criado para que o bloco de inicialização seja executado e o construtor é chamado de
Saída: y é impresso seguido por c
3. O método principal é invocado, o que por sua vez invoca o método go
Saída: g é impresso

Resultado final: xycg
Isso pode ajudar http://blog.sanaulla.info/2008/06/30/initialization-blocks-in-java/


@Cthulhu: Obrigado. Era válido até a semana passada eu atualizei com novo link.
xyz

16

Esse é um bloco de inicialização de instância seguido por um bloco de inicialização estático .

{
    System.out.print("y ");
}

é chamado quando você cria uma instância da classe.

static {
    System.out.print("x ");
}

é chamado quando a classe é carregada pelo carregador de classes. Então, quando você faz

new Sequence().go();

a classe é carregada, então ela executa static {}, então ela executa o bloco de inicialização da instância {}, depois o corpo do construtor é chamado e então o método na instância recém-criada. Portanto, a saída x y c g.


15
static {
        System.out.print("x ");
    }

É um bloco estático e é chamado durante o carregamento da classe

{
    System.out.print("y ");
}

É um bloco de inicialização

Você pode ter vários blocos de inicialização em uma classe, caso em que eles são executados na sequência em que aparecem na classe.

Observe que qualquer bloco de inicialização presente na classe é executado antes do construtor.


10
static {
      System.out.print("x ");
}

é um bloco de inicialização compartilhado pela classe (conforme indicado por static), que é executado primeiro.

{
        System.out.print("y ");

}

é um bloco de inicialização compartilhado por todos os objetos (construtores) da classe, que vem a seguir.

Sequence() {
        System.out.print("c ");
}

é um construtor específico para a classe, que é executado em terceiro lugar. O bloco de inicialização da instância é invocado primeiro sempre que o construtor é executado. É por isso que "y" vem logo antes de "c".

void go() {
        System.out.print("g ");
}

é apenas um método de instância associado a objetos construídos usando o construtor acima, que vem por último.


9
{
    System.out.print("y ");
}

Esses tipos de blocos são chamados initializer block. Ele é executado sempre que você cria uma instância de a class. Em tempo de compilação, esse código é movido para cada construtor de sua classe.

Onde, como no caso de static initializerbloco: -

static {
    System.out.println("x ");
}

ele é executado uma vez quando a classe é carregada. Geralmente usamos o staticbloco inicializador quando a inicialização de um staticcampo requer várias etapas.


6

É usado como um bloco de inicialização e é executado após qualquer declaração estática . Ele pode ser usado para garantir que ninguém mais possa criar uma instância da classe (da mesma forma que você usaria um construtor privado) como com o padrão de design Singleton .


3
static {
    System.out.print("x ");
}

Static blockssão executados apenas uma vez quando a classe é carregada e inicializada pelo JRE.

E o non-staticbloco será chamado toda vez que você estiver criando uma nova instância e será chamado antes do Construtor.

Como aqui, você criou apenas 1 instância de Sequenceassim construída foi chamada após os non-staticblocos e, em seguida, o método que realmente é seu objetivo.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.