Wednesday, August 01, 2007

3.3-Alguns erros a evitar.[repost6]

Veja a seguinte classe:

public class Confusao{ //classe com muitos erros propositais!!! ;)
    
     private static String s;
     
     public static void mudaValor(int a[]){
         for(int i=0;i"menor"a.length;i++)
           a[i]+=17;   
        }
     
     public static int mudaValor(int a){ 
        a*=10;
       return a;                       
                                       } 
     public static String mudaValor(String s){ 
        s=s.concat(" O Maior Forum De Usuarios Java Do Brasil");
            
          return s;                          }       
     public static void mudaValor(int[] ref,int x,int y){ //troca os    //elementos em um array
        int temp;
              temp=ref[x];
              ref[x]=ref[y];
              ref[y]=temp;
                                                       }
     public static void bolha(int []a){
          for(int i=0;i"menor"a.length;i++) //controla o número de passagens
           for(int j=0;j"menor"a.length-1;j++) //controla as comparações e      //trocas
              if(a[j]"maior"a[j+1]) //compara o elemento com o seguinte,se for //maior
                mudaValor(a,j,j+1); //haverá a troca.                
                                      }                                                      
     public static void main(String []GUJ){
        int a[]={123,6111,52,13,2};
     
             s=new String("GUJ");
             //super exemplo de Overloading-sobrecarga de métodos
             mudaValor(a); //muda o valor do array
             System.out.println(a); //array eh um objeto sera exibido seu                //endereço Heap
        
             mudaValor(a[2]); //muda o valor da variavel
             System.out.println(a[2]);
        
             mudaValor(s); //tenta mudar o valor da String
             System.out.println(s);
        
             bolha(a);
             System.out.println(a);
        
        }   
 }


Compile (javac Confusao.java )e rode (java Confusao).Uma classe perfeita não?
Ela é perfeita para se jogar no lixo!Os piores erros são o que passam na compilação e na
execução, pois estes são difíceis de serem depurados!Nesse exemplo será fácil de ver os
erros, mas nem sempre será assim!
Temos 5 métodos de classe além do main(), sendo
que 4 deles com mesmo nome(mudaValor), mas assinaturas distintas(a assinatura de um
método é composta de nome+lista de parâmetros).
A essa possibilidade de métodos possuírem mesmo nome, mas lista de argumentos
diferente é chamada de overloading (sobrecarga), cabendo ao Interpretador selecionar
qual método deve ser executado combinando a lista de argumentos com o parâmetro
passado a chamada do método.
A essa associação de atributos feita em tempo de compilação, é chamada de early binding (ligação prematura)
ou static binding (ligação estática); que é executada pelo Carregador de Classe
(ClassLoader), procurando os membros estáticos na sua classe. Se existirem, eles serão
carregados!

NOTA
:Quando executamos métodos não estáticos, ou algum método sofre overriding
(é subscrito) numa subclasse, o compilador não sabe qual método será chamado e isso
só é resolvido em tempo de execução, processo chamado de late binding (ligação tardia),
dinamic binding(ligação dinâmica) ou a melhor definição, virtual method invocation (invocação de método virtual)
pois os métodos "existem" no momento da execução(nenhum código extra é gerado).

Em teoria essa classe deveria adicionar 17 á todos os membros do array a, através da
chamada a primeira função mudaValor() e mostrá-lo na tela. Deveria através da chamada
a mudaValor(a[2]); mudar o valor da variável (o que não ocorre). A terceira chamada
era para retornar a String modificada "GUJ O Maior Forum De Usuarios Java Do Brasil",
mas só GUJ é retornado. E a chamada ao método bolha, era para permitir exibir no
método println() o array a ordenado do menor para o maior. Nota-se que é exibido uns
caracteres estranhos (do tipo [I@10b62c9) assim como na primeira chamada a println().
Porque isso ocorre?Porque é passado uma referência a um array em ambos os casos!
Todos os objetos tem associados a eles uma referência a própria classe, quando uma
referência a um array é passada ao método println() há uma chamada ao método ToString
que retornará o nome da classe a qual esse objeto é uma instância(no caso [I-de Inteiro),
um separador "@", e uma representação hexadecimal representando o código hash desse
objeto.
Veja o formato:
getClass().getName() + '@' + Integer.toHexString(hashCode())
Nota-se que nas duas chamadas a println(a) serão retornadas a mesma String!Isso se
deve porque o objeto está num único local na tabela
hash (esse endereço de memória de
mentirinha que é @numero_hexadecimal).Não devemos passar um objeto a println() a
menos que se queira mostrá-lo dessa forma, senão poderá ser necessário subscrever o
método println()(para retornar um objeto).
Prosseguindo com a análise do código, a chamada ao primeiro mudaValor(a) e ao
método bolha(a) tem êxito, o problema foi passar uma referência ao método println()
para exibir na tela! Deve-se usar um laço for para poder exibir os valores corretos na tela:
for(int i=0;i"menor"a.length;i++)
System.out.println(a[i]);


Dessa forma, todos os índices serão percorridos, pois ocorre uma passagem por valor
(índice após índice) a cada interação do laço.(Nota: a.length retorna o tamanho total do
vetor).

Prosseguindo, temos a segunda chamada a mudaValor() na qual é passado a[2].Exibirá
69 na tela, logo a operação teve êxito, certo?ERRADO!Deveria exibir 690, correspondente
ao mudaValor() que recebe um tipo inteiro e multiplica por 10, mas o valor da posição 3
do array (assim como o array todo) foi modificado pela chamada ao primeiro
mudaValor()na qual foi passado o array a.Ele não pode ser exibido(o array a modificado
com os novos valores) porque foi passado erroneamente a println() também! Além do
mais, quando se passa um índice (um elemento) individual de um array de tipo de dados
primitivos essa passagem é feita por valor como uma simples variável! Elementos
individuais de um array de tipo referência(
Object, String...) são passados como uma
referência a esse objeto!O valor passado (69) não foi modificado, pois a cópia de a[2]
ficou limitada a execução no escopo do método!


A terceira chamada a mudaValor() é tudo o que você não pode fazer em Java! Não há
como mudar o valor de uma determinada String numa passagem para um método porque
Strings são imutáveis!E nesse caso, o gasto de memória foi um desperdício! (Em relação
ao que pode ser feito!). Jamais tente modificar Strings via método. Quando precisar de
Strings modificáveis, use java.lang.
StringBuffer(com sincronização) ou StringBuilder
(sem sincronização, portanto mais rápida!).

No comments: