Casting de Variáveis de Referência


Quando uma variável de referência do tipo de uma classe está instanciada por um tipo de uma subclasse, só poderão ser executados métodos da classe do tipo de referência; porém, quando se faz necessário utilizar o método presente na subclasse, esse método só poderá ser executado se for feito casting da variável.
Por exemplo: B extends A; A a = new B(); para executar um método de B sem gerar erro de compilação é necessário fazer casting:   B b = new B(); b = (B)a;
Nesse caso, é chamado de downcast, porque o casting está sendo feito da árvore de herança pra uma classe específica; ou seja, uma classe específica recebe uma mais genérica. Entretanto, é necessário ter certeza que o tipo do objeto trata-se mesmo do tipo que se deseja fazer casting, pois pode gerar uma exceção. Por exemplo: A a = new A();         B b = (B) a; gera uma exceção em tempo de execução, pois a instância é da classe A, mesmo sendo da mesma árvore de herança.

public class Livro {

      public void abrir() {
            System.out.println("Livro");
      }
     
}


public class Java extends Livro {

      public void abrir() {
            System.out.println("Java");
      }
     
      public void fechar() {
            System.out.println("Java");
      }
     
}


public class AppLivro {

      public static void main(String[] args) {
            Livro livro = new Java();
            livro.abrir();
            /* erro de compilação, pois, apesar de a
             * instância ser do tipo Java (que possui
             * o método fechar()), o compilador irá
             * tentar executa-lo em Livro, que é o 
             * tipo da referência e que não o possui,
             * ou seja, é necessário fazer downcast*/
            livro.fechar();
            Java java = (Java)livro;
            java.abrir(); //imprime Java
            //depois do casting é possível executar
            java.fechar();
           
            Livro livro2 = new Livro();
            /* não gera erro de compilação porque as
             * duas classes estão na mesma árvore de
             * herança, mas uma exceção é lançada, 
             * pois o JVM espera uma instância de Java
             * e recebe uma instância de Livro; o cast
             * não irá funcionar */
            Java java2 = (Java)livro2;
           
            Livro livro3 = new Livro();
            /* esse caso gera erro de compilação
             * porque a classe String não está na  
             * mesma árvore de herança que Livro */
            String s = (String) livro3;
      }
     
}


Ao contrário do downcast, o upcast (feito da árvore de herança para uma classe mais genérica) não precisa ser explícito, porque no upcasting há uma restrição do número de métodos que podem ser invocados. Por exemplo: B b = new B(); A a1 = b; A a2 = (B)b; as duas opções funcionam no upcast. Nesse caso, poderão ser executados os métodos de A.

public class Livro {

      public void abrir() {
            System.out.println("Livro");
      }
     
}


public class Java extends Livro {

      public void abrir() {
            System.out.println("Java");
      }
     
      public void fechar() {
            System.out.println("Java");
      }
     
}


public class AppLivro2 {
     
      public static void main(String[] args) {
            Java java = new Java();
            /* casting implicito, pois Livro há uma
             * restrição dos métodos que podem ser
             * executados (os de Livro) */
            Livro livro = java;
            //também pode ser explícito
            Livro livro2 = (Livro) java;
      }

}

Fonte: SCJP Sun Certifi ed Programmer for Java 6 Study Guide

0 comentários:

Postar um comentário