Esta é pra ver se você é bom mesmo

10 respostas
Luca

Olá

Pegadinha: quem acertar vai ganhar um servidor de aplicação e uma IDE.

[color=green]Todo mundo aqui ([/color][color=red]no Java avançado[/color][color=green]) sabe que [/color][color=red]é possível[/color][color=green] mudar um campo [/color][color=red]private[/color][color=green] ou [/color][color=red]private final[/color][color=green], certo?[/color]

Vamos ver um exemplinho simples:

public class Tiozinho {

    private String nome;
    private final int idade = 60;

    public String getNome() {
        return nome;
    }

    public int getIdade() {
        return idade;
    }
}

Agora a classe que pretende alterar os campos private e private final:

import java.lang.reflect.Field;

public class FonteJuventude {

  public static void main(String[] args) throws NoSuchFieldException {

    Tiozinho tio = new Tiozinho();

    // notar que getField(...) throws NoSuchFieldException
    Field campoNome = Tiozinho.class.getDeclaredField("nome");

    // Vamos alterar um campo private
    campoNome.setAccessible(true);
    try {
      campoNome.set(tio, "Jenubaldo Canopilha");
    } catch (IllegalAccessException e) {
      System.out.println("Não foi possível trocar o nome");
    }

    Field campoIdade = Tiozinho.class.getDeclaredField("idade");
    // Agora vamos alterar um campo private final
    campoIdade.setAccessible(true);
    try {
      campoIdade.setInt(tio, tio.getIdade() - 30);
    } catch (IllegalAccessException e) {
      System.out.println("Não foi possível diminuir a idade");
    }
 
    // Vamos provar que funciona
    try {
       System.out.println("Nova idade = " + campoIdade.getInt(tio));
    } catch (IllegalAccessException e) {
      System.out.println("Não foi possível pegar a idade");
    }

    // Assim podemos escrever
    System.out.println("Idade agora de " + tio.getNome() + " = " + tio.getIdade());
  }

}

Vamos executar:

linha de comando do meu computador:

C:>javac Tiozinho.java

C:>javac FonteJuventude.java

C:>java FonteJuventude
Nova idade = 30
Idade agora de Jenubaldo Canopilha = 60

C:>

Ops!

[color=red]Mudou o nome, mudou a idade mas depois imprimiu a idade antiga[/color]

E agora, alguém tem alguma explicação? Paulo? Louds? Sami? Maurício?

Com certeza a explicação existe e faz sentido.

[color=yellow] Uma dica: se mudar a inicialização do valor da idade de lugar, a fonte da juventude funcionará corretamente.[/color]

[]s
Luca [color=yellow](que copiou esta idéia do Eric Burke)[/color]

10 Respostas

samuelhenriquerj

vc colocou o final na idade, mas não no nome
qd vc imprime:

System.out.println("Nova idade = " + campoIdade.getInt(tio));

é uma variável local, da classe Main
qd vc imprime

System.out.println("Idade agora de " + tio.getNome() + " = " + tio.getIdade());

é da clase tiozinho, mas vc só conseguiu mudar o nome q não está com final, mas a idade é estática e não mudou
falei alguma besteira?rrsrs

Luca

Olá

Valeu a tentativa Samuel

Mas repare que o programa imprime a idade alterada. Então é claro que é possível com o uso de reflection alterar campos private e também campos private final.

A explicação que eu quero é outra.

[]s
Luca

samuelhenriquerj

rsrs, desculpe mas ñ entendi, pois ele imprime o valor alterado pq vc usou:

campoIdade.setInt(tio, tio.getIdade() - 30);

aí imprime 30 certo?
:roll:

Luca

Olá

Ainda não. O motivo porque imprime 30 da primeira vez e 60 na segunda é outro.

[]s
Luca

davidbuzatto

Quando o campo da idade é obtido via reflection, é obtida uma cópia do valor do inteiro, muda-se o valor dessa cópia e sim, o valor 30 é mostrado (um int não é uma referência). Já para o campo nome, que é uma String, é obtida a referência que é associada a uma nova String.

Se o valor da constante inteira for iniciada dentro do construtor de Tiozinho, a fonte de juventude funcionará, pois o campo foi iniciado após a criação do objeto (super do Object). Parece que a inicialização da constante dentro do construtor faz ela ter um comportamento diferente, sendo associada ao objeto da classe Tiozinho e não a classe em sí.

Hehehe acho que fui meio confuso, mas me parece que é isso que acontece.

Abraços!

Luca

Ola

Caraca, é isto mesmo!

Da forma em que está, o compilador otimiza o código. Quando a gente inicializa no construtor, isto não acontece.

Pô, meu teste super 3XYKP4 não durou nem uma horinha…

[]s
Luca

davidbuzatto

Êba! Acertei!

Qual IDE vou ganhar :smiley:

Legal saber esse detalhe! Bem interessante! Valeu Luca!

Abraço!

CintiaDR

Algumas das coisas que eu achei bizarra quando comecei em Java (eu vim de C++) foi esse esquema de reflection e todos os objetos virem de ‘Object’. Hoje já paguei a língua bem paga e uso e abuso disso :smiley:

rogeriop80

davidbuzatto:
Qual IDE vou ganhar :smiley:

Eclipse ou Netbeans =), pode escolher.

Abraços.

davidbuzatto

rogeriop80:
davidbuzatto:
Qual IDE vou ganhar :smiley:

Eclipse ou Netbeans =), pode escolher.

Abraços.

Pensei qua ia ser a IntelliJ :smiley: :smiley: :smiley: :smiley:

Criado 14 de outubro de 2007
Ultima resposta 14 de out. de 2007
Respostas 10
Participantes 5