Arquivo de setembro, 2011

Apanhado de assuntos sortidos

Posted in Idiotices on 19/09/2011 by Allan Taborda

O post de hoje será um miscelânea de vários assuntos.

Num comentário sobre o primeiro post que fiz sobre o Robowebert Player, me pediram para enviar por e-mail o código-fonte do pequeno player que fiz antes do que estou fazendo agora, que só toca MP3 e possui poucas linhas de código. Enviei o e-mail com os fontes, mas o mesmo voltou. Neste caso, e também para o caso de mais alguém quiser ver os fontes do primeiro player que fiz, aí estão os dois arquivos de código-fonte, sendo o primeiro a classe principal, que contém o método Main, e o segundo sendo a parte gráfica.

http://pastebin.com/i4iYFPfL

http://pastebin.com/1t9u52Vt

Este player funciona em conjunto com a biblioteca JLayer, que implementa o suporte ao formato MP3. Esta biblioteca pode ser baixada em:

http://www.javazoom.net/javalayer/sources.html

Por falar no Robowebert Player, este continua a ser desenvolvido no meu tempo livre e já possui muitos recursos novos implementados, como o suporte a múltiplas bibliotecas de músicas, o salvamento e o carregamento de playlists compactadas com GZIP e a possibilidade de arrastar músicas e/ou playlists do desktop diretamente para a lista de reprodução. Mas ainda não há uma previsão de quando ele será disponibilizado ao público geral, visto que ainda faltam recursos básicos. Mas eu posso enviar o código-fonte dele para quem quiser, basta me contatar por meio de um comentário neste ou em outro post sobre o player.

Depois de alguns anos com o mesmo celular, no qual eu o tenho desde 2005 e que foi o primeiro que eu tive (um Nokia 2112, fabricado em 2004), eu comprei um celular novo, um Galaxy 5, da Samsung, que vem com o sistema operacional Android. Estou gostando bastante desse meu novo celular. Ele tem muitas funções legais que o outro não tinha, como rádio FM, acesso à Internet, câmera digital embutida, ouvir músicas em MP3, configurar um toque de celular em MP3, instalar aplicativos, dentre outras funções. Só a função de despertador que deixou a desejar, uma vez que esta só funciona com o celular ligado. Como despertador, permanecerei usando meu celular antigo, que agora só serve para isso e como lanterna, já que ele tem uma lanterna na parte de cima.

Ainda falando do meu novo celular, apesar de ter visto na Internet que a bateria do modelo que eu comprei dura pouco, até que a bateria do meu está durando bastante. Vai ver porque eu não fico a toda hora mexendo no celular como fazem algumas pessoas. Eu mais fico com ele em stand-by ou escutando música com o fone de ouvido.

No painel de controle do WordPress, há a exibição de estatísticas, que incluem os termos pesquisados pelos motores de busca que fazem os usuários chegarem ao meu blog. O pessoal que chega no meu blog usando vários termos diferentes, muitos deles pesquisando sobre o golpe 419 (no qual foi tema de um post meu recentemente), sobre tocar áudio em Java, sobre obter ou atualizar o Debian GNU/Linux, sobre como ganhar moedas no Come2Play, sobre software para identificar números primos, sobre proteção de tela que gera falsas telas azuis, e mais uma infinidade de coisas. Tem até termos nos quais eu não me lembro de ter postado nada a respeito, como Miley Cyrus deletando conta no Twitter, comprar projetor que não seja caro e algoritmo em C# para traduzir do português para o inglês (e eu nem programo em C#).

Mas um termo de busca recorrente está me deixando intrigado: muitas pessoas chegam ao meu blog perguntando ao buscador para que serve banana com aveia. É espantoso o povo usar o Google para perguntar algo tão óbvio, algo que, teoricamente, todo mundo já sabe a resposta. Mas caso alguém não saiba pra que serve banana com aveia, eu respondo para que serve banana com aveia: serve para comer.

Este blog está cada vez tendo uma maior audiência, com cada vez mais pessoas acessando a cada dia. A média de acessos é de cerca de 25 acessos diários, chegando a 38 em alguns dias (pouco comparado a grandes sites, mas bastante para os meus padrões). Meu outro blog, o dos Sonhos do Allan, tem bem menos acessos, cerca de 3 por dia, 50 por mês, em média. Mas teve um dia, o dia 6 de setembro, que houve 53 acessos a este blog, bem mais que costuma ocorrer neste meu blog principal em um dia. Acho que alguém deve ter gostado do blog e deve ter tuitado o link.

Por falar em Twitter, continuo não tendo Twitter, e nunca terei. E acredito que o Twitter será eclipsado pelo Facebook, que também possui um serviço de microblogging interno, que no qual possui recursos mais interessantes e não é limitados aos claustrofóbicos 140 caracteres. E o usuário ainda pode fazer com que as atualizações em seu Twitter apareçam em seu Facebook.

Com certeza, irá acontecer com o Twitter o mesmo que aconteceu com o ICQ e que está acontecendo com o Orkut. Há alguns anos atrás, todo mundo tinha Orkut. Hoje em dia, o que vejo é que um monte de conhecidos meus não têm mais Orkut ou não abrem mais seus perfis, além de comunidades do Orkut outrora badaladas passarem a ficar às moscas. E o ICQ então? Muita gente usava, era o “mensageiro padrão” do povo. Hoje, quem usa ICQ, tirando alguns russos? A mesma coisa irá ocorrer com o Twitter, que possui um único serviço apenas, que é o de microblogging, ao contrário do Facebook, que possui alguns serviços vinculados, além dos famigerados aplicativos. E até o próprio Facebook acabará deixado de lado um dia, embora isso demorará mais para ocorrer.

Por hoje é só, até o próximo post, no qual abordará, provavelmente, mais erros irritantes cometidos por programadores Java.

Erros irritantes cometidos por programadores Java, parte 1

Posted in Atividades profissionais on 03/09/2011 by Allan Taborda

No post de hoje, eu irei falar sobre alguns erros muito comuns cometidos por programadores Java ao codificarem seus programas. São erros estúpidos que costumam me irritar bastante quando vejo um no meio do código. São erros que podem provocar desde o desperdício de recursos (memória, principalmente) até comportamentos inesperados que podem resultar em erros nos aplicativos.

A intenção era de colocar outros erros além desses seis, mas o post acabou ficando muito comprido e os outros erros ficarão para futuros posts. Então, acabei por colocar neste post apenas erros relacionados a comparações de igualdade.

Este post (e os próximos com a mesma temática deste) tem por finalidade alertar programadores (tantos os iniciantes como os experientes, que, como todo ser humano, também cometem erros) para que estes deixem de cometer esses erros. Seguem os erros abaixo:

1) Comparar Strings com dois sinais de igual (==): Esse é um dos erros muito comuns cometidos pelos programadores Java. Comparar Strings com == presumindo que comparações de Strings iguais (com a mesma sequencia de caracteres) feitas dessa maneira sempre retornará true (ou seja, que a condição é verdadeira) pode provocar erros de lógica, pois a comparação pode muito bem retornar false (ou seja, que a condição é falsa). Isto porque comparar Strings com dois sinais de igual (ou melhor, comparar qualquer objeto com dois sinais de igual) significa que você está verificando se as duas referências aos objetos apontam para o mesmo objeto, ou seja, você está verificando se os dois objetos (as duas Strings, neste caso) são, na verdade, o mesmo objeto. Como novas instâncias da classe String podem ser criadas com o comando new (assim como qualquer instâncias de qualquer classe), e o comando new sempre resulta na criação de um novo objeto, e como não dá para garantir que uma String vinda vai saber de onde é uma String declarada com um literal de String (uma String que é declarada com seu valor entre aspas) ou resultante de um comando new, então não é garantido que uma comparação com dois sinais de igual irá retornar true caso as Strings sejam iguais.

Ao invés de comparar Strings com dois sinais de igual, o correto é comparar as Strings com o método equals. Basicamente, pega-se uma das Strings e chama-se o método equals nessa String, passando como parâmetro a outra String, que vai ser comparada com a primeira a fim de verificar se ela é igual à outra. Caso as Strings sejam iguais, ainda que sejam objetos diferentes, o método equals retornará true.

Objetos String até podem ser comparados com dois sinais de igual, desde que tanto a String da esquerda do == quanto a String da direita, ou devem ser literais de String, ou devem ser String resultantes de uma chamada do método intern de outra String, ou então deve ser uma referência cujo valor foi sabidamente atribuído (e sem ter jeito de não ser) ou a um literal de String, ou a uma String resultante de uma chamada do método intern de outra String. O método intern sempre retorna uma String do pool de Strings da máquina virtual igual à String de onde o método foi chamado, ou a mesma String, caso ela seja uma String do pool de Strings.

2) Comparar números encapsulados por objetos numéricos wrappers com dois sinais de igual (==): É o mesmo problema de comparar Strings com dois sinais de igual, já que os objetos podem ser diferentes. Com números inteiros até o 128 não há problema, pois números até o 128 são armazenados num pool de inteiros pela máquina virtual (poucos programadores sabem disso), entretanto, como não é garantido que um objeto de uma classe wrapper de um tipo numérico representa um número menor ou igual a 128, é melhor não arriscar e fazer a comparação com o método equals. Ou então pegar os valores resultantes de chamadas aos métodos da própria classe wrapper que retornam o número propriamente dito (armazenado em um tipo primitivo, não em um objeto), como o método intValue, que retorna um número inteiro de 32 bits (o popular int), e fazer a comparação com dois sinais de igual, pois daí você estará comparando os valores numéricos em si, que não são objetos. Utilizar os métodos que retornam números em tipos primitivos permite que sejam feitas comparações entre objetos wrappers de tipos diferentes, como Integer e Long, por exemplo.

3) Comparar dois objetos de uma classe implementada pelo programador com o método equals, mas sem sobrescrever o mesmo: O método equals pode ser chamado a partir de qualquer objeto e tem por finalidade verificar se o conteúdo do objeto em questão é igual ao conteúdo do objeto passado como parâmetro. Em classes escritas pelo programador que estão sujeitas a terem seus objetos comparados entre si a fim de verificar se são iguais, o programador deve sempre sobrescrever o método equals, implementando um algoritmo que efetue a comparação dos atributos da classe em questão, verificando se o conteúdo dos atributos é igual ao conteúdo dos atributos do objeto a comparar.

Caso o programador não sobrescreva o método equals padrão que é herdado da classe Object (a classe mãe de todas as outras classes Java, que possui métodos comuns a todas elas), a comparação é feita com a implementação padrão provida pela classe Object, que… Adivinhem! Compara os objetos com dois sinais de igual! Ou seja, compara se os dois objetos são, na verdade, o mesmo objeto. Aí, caso os objetos tenham os mesmos valores em seus atributos, a comparação poderá retornar false, caso os objetos sejam diferentes.

4) Sobrescrever o método equals, mas não sobrescrever o método hashCode: caso desses métodos seja sobrescrito, o outro também deve ser, pois o contrato de ambos os métodos (não irei explicar aqui o que é um contrato de um método, caso não saiba, acho que o Google pode lhe ajudar, assim como me ajuda quando eu não sei algumas coisas) diz que, caso a comparação entre dois objetos pelo método equals retorne true, o retorno do método hashCode de ambos deve ser igual. Atenção: isto não significa que objetos com valores diferentes não devem ter o mesmo hashCode. sobrescrever o método equals e não sobrescrever o método hashCode pode resultar em resultados imprevisíveis caso o objeto em questão seja utilizado em alguma classe que chame ambos os métodos internamente, como as classes do Java Collections Framework, que são as populares coleções do Java (classes ArrayList, LinkedList, HashSet, HashMap, etc).

5) Armazenar um objeto de uma classe implementada pelo programador em uma coleção ou um Map sem implementar os métodos equals e hashCode dessa classe: as classes do Java Collections Framework fazem uso massivo desses dois métodos a fim de saber se um objeto possui os mesmos valores de outro, principalmente as classes que implementam a interface Map (HashMap, TreeMap, LinkedHashMap, ConcurrentHashMap, etc), que usam o valor retornado pelo método hashCode para posicionar o objeto dentro do mapa de objetos que foram postos dentro do Map. Caso um dos dois métodos deixe de ser implementado, um objeto da classe em questão pode se perder dentro do Map (entrar e não sair mais), já que, na hora de recuperar o objeto, é verificado o retorno do método hashCode a fim de saber onde o objeto está em relação ao mapa, além de eventualmente (dependendo das implementações dos Maps e de quais métodos forem chamados) haver comparações com o método equals a fim de saber se um determinado objeto é igual a outro. Isso vale para todas as classes do Java Collections Framework, mesmo para Lists (ArrayList, LinkedList, Vector, etc), uma vez que alguns métodos fazem uso do equals e do hashCode em seus objetos armazenados, como o método contains, que verifica se um objeto está contido na lista comparando cada um com o método equals.

6) Comparar String ou números encapsulados por objetos numéricos wrappers ou qualquer objeto usando um ponto de exclamação e um sinal de igual (!=): um ponto de exclamação e um sinal de igual é o contrário de dois sinais de igual, ou seja, verifica se dois objetos (ou dois tipos primitivos) são diferentes. Do mesmo modo que comparações com == presumindo que isto faz comparar se o valor dos objetos é igual podem zicar com o funcionamento de um programa, comparações com != presumindo que isto faz comparar se o valor dos objetos é diferente também não é uma boa ideia, apesar de que objetos cujas comparações entre si com o método equals retornem false são sempre objetos diferentes. Isto porque, do mesmo modo, presume-se que comparações com != entre objetos iguais retornem false, quando podem acabar retornando true na hipótese dos objetos serem diferentes. Neste caso, usa-se o método equals com um ponto de exclamação à esquerda do objeto cujo método equals está sendo chamado. Isto faz com que o retorno do método equals seja “invertido”, ou seja, faz retornar false quando o método retorna true e vice-versa. Aliás, o ponto de exclamação à esquerda de qualquer método que retorne um valor boolean (true ou false) sempre “inverte” o retorno desse método.

Bom, por hoje é só, mas futuramente, escreverei melo menos mais um post acerca de erros cometidos por programadores Java, que será a continuação deste aqui.