Olá

Esse post é só uma dica para você que usa o SimpleDateFormat para converter String em Date.
Não sei por que razão (para falar a verdade também não pesquisei) mas o SimpleDateFormat não lança uma exceção quando passamos um data que não existe no calendário. Por exemplo 31 de setembro e 32 de setembro. Ele simplesmente converte para um dia do próximo mês.

Veja os exemplos abaixos:

    SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
    System.out.println(sdf.parse("30/09/2011"));
    System.out.println(sdf.parse("31/09/2011"));
    System.out.println(sdf.parse("32/09/2011"));

    // Saídas
    // Fri Sep 30 00:00:00 BRT 2011
    // Sat Oct 01 00:00:00 BRT 2011
    // Sun Oct 02 00:00:00 BRT 2011

Dica do Tadashi:
Para validar a data use o método setLenient(false)

Dessa forma um ParseException será lançada!

Até mais,
Roberto

Olá

Programinha para identificar valores RGB e gerar imagens pixel a pixel pelo valor RGB.

import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.image.WritableRaster;
import java.io.File;
import java.io.IOException;
import java.util.*;
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.event.*;  

public class IdentificadorRGB extends JFrame implements MouseMotionListener {  

   private JLabel l_imagem, l_red, l_green, l_blue, l_r, l_g, l_b;
   private BufferedImage imagem,
   img_red, img_blue, img_green;
   Container c;  

   IdentificadorRGB() {
      super("Identificador de valores RGB pixel a pixel");
      try {
         //Leitura da imagem do disco
         imagem = ImageIO.read(new File("imagem.png"));
         img_blue = ImageIO.read(new File("imagem.png"));
         img_red = ImageIO.read(new File("imagem.png"));
         img_green = ImageIO.read(new File("imagem.png"));
      } catch (IOException e) {
         e.printStackTrace();
      }
      getContentPane().setLayout(null);
      c = getContentPane();  

      l_r = new JLabel();
      l_r.setBounds(300, 0, 270, 185);
      c.add(l_r);  

      l_g = new JLabel();
      l_g.setBounds(300, 190, 270, 185);
      c.add(l_g);  

      l_b = new JLabel();
      l_b.setBounds(5, 245, 270, 185);
      c.add(l_b);  

      l_imagem = new JLabel();
      l_imagem.setIcon(new ImageIcon(imagem));
      l_imagem.setBounds(0, 0, 270, 185);
      c.add(l_imagem);  

      l_red = new JLabel();
      l_red.setText("R:");
      l_red.setBounds(5, 190, 100, 15);
      c.add(l_red);  

      l_green = new JLabel();
      l_green.setText("G:");
      l_green.setBounds(5, 210, 100, 15);
      c.add(l_green);  

      l_blue = new JLabel();
      l_blue.setText("B:");
      l_blue.setBounds(5, 225, 100, 15);
      c.add(l_blue);  

      WritableRaster raster = imagem.getRaster();
      int pixels[] = new int[4];
      for (int i = 0; i < imagem.getWidth(); i++)
         for (int j = 0; j < imagem.getHeight(); j++) {
            raster.getPixel(i, j, pixels);
            img_red.setRGB(i, j, setR(pixels[0] ));
            img_green.setRGB(i, j, setG(pixels[1] ));
            img_blue.setRGB(i, j, setB(pixels[2] ));  

         }  

      c.validate();
      l_r.setIcon(new ImageIcon(img_red));
      l_g.setIcon(new ImageIcon(img_green));
      l_b.setIcon(new ImageIcon(img_blue));
      addMouseMotionListener(this);
      setSize(600, 500);
      setResizable(false);
      show();
      setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  

   }
   /* métodos que transforma valores inteiros do RGB para um numero hexadecimal
    *
    * Por exemplo 255,000,255  fica em hexadecimal 0x00FF00FF
    *
    * O dois primeiros 00 são valores do ALPHA que é responsavel pela
    * transparencia
    *     *
    */
   private int setR(int r) {
      return 0
         << 24
            | ((r << 16) & 0x00FF0000)
            | ((0 << 8 ) & 0x0000FF00)
            | (0 & 0x000000FF);
   }
   private int setG(int g) {
      return 0
         << 24
            | ((0 << 16) & 0x00FF0000)
            | ((g << 8 ) & 0x0000FF00)
            | (0 & 0x000000FF);
   }
   private int setB(int b) {
      return 0
         << 24
            | ((0 << 16) & 0x00FF0000)
            | ((0 << 8 ) & 0x0000FF00)
            | (b & 0x000000FF);
   }  

   public static void main(String[] args) {
      new IdentificadorRGB();
   }  

   public void mouseDragged(MouseEvent arg0) {
   }  

   public void mouseMoved(MouseEvent arg0) {  

      WritableRaster raster = imagem.getRaster();
      int pixels[] = new int[4];
      if (arg0.getX() < imagem.getWidth()
         && arg0.getY() < imagem.getHeight()) {
         raster.getPixel(arg0.getX() - 3, arg0.getY() - 23, pixels);
         //Mostras os valores na tela
         l_red.setText("R: " + pixels[0] );
         l_green.setText("G: " + pixels[1] );
         l_blue.setText("B: " + pixels[2] );
      }
   }  

}

Boas Práticas – Dica nº 4

19/outubro/2010 - Geral

Olá

Nunca altere o estado dos objetos passados por parâmetro de um método, utilize uma variável temporária quando alterar o valor de algum atributo do objeto.

Essa prática é para evitar erros diante de uma confusão causada pelo tipo de passagem de valores que o Java adota. Java sempre faz a passagem por valor.

Abaixo um exemplo de erro que levamos a cometer quando alteremos o estado de um objeto.

Nós temos um objeto do tipo ItemPedido que possui os atributos quantidade e preço. Passamos esse objeto para o método totalizarPedido(), que para seu calculo interno subtrai um caso o parâmetro promoLeveUmGratis for true.

if(promoLeveUmGratis){

item.setQuantidade(item.getQuantidade().subtract(BigDecimal.ONE));

}

Observe que estamos atribuindo o resultado da subtração no mesmo objeto que recebemos por parâmetro para o cálculo na linha abaixo.

return item.getQuantidade().multiply(item.getPreco());

Em seguida os métodos calcularFrete() e darBaixaNoEstoque() são invocados.

ex.totalizarPedido(ip, true);
ex.calcularFrete(ip);
ex.darBaixaNoEstoque(ip);

Coloquei alguns sysout´s para ilustrar o problema.

Quantidade de itens no pedido:   10

Quantidade de itens no frete:    9

Quantidade de itens a dar baixa: 9

Note que para os dois métodos seguintes a quantidade que chegou foi alterada, não era essa a intenção. Isso traria sérios problemas para nós.

Downloads: Exemplo.java ItemPedido.java

Até mais,

Boas Práticas – Dica nº 3

19/outubro/2010 - Geral

Olá

Acrescentando e removendo parâmetros, todo desenvolvedor já precisou algum dia fazer essa alteração no código-fonte, esse é o tipo de refatoração mais comum na nossa vida.

Pode parecer simples quando o projeto é pequeno e pouco reaproveitado, mas precisamos ter muito cuidado ao fazer isso em grandes projetos cujo método é altamente reusado para não correr o risco de tomar um NoSuchMethodException em produção.

O procedimento é parecido para os dois tipos de refatoração.

1.       Crie um novo método com o novo parâmetro (ou sem o parâmetro se estiver removendo). Geralmente é um Ctrl+C e Ctrl+V do método existente apenas alterando a lista de parâmetros.

2.       Agora você deve copiar o corpo do método existente para o método novo.

3.       No método que já existia efetue a chamada do método novo. No caso de acréscimo de parâmetro você terá que passar um valor padrão para o parâmetro novo, eu geralmente uso null.

4.       Altere os demais códigos para que chame o método novo. Tente procurar pelo máximo de referencias.

5.       Execute o aplicativo e teste.

6.       Você pode apagar o método antigo, mas se isso não for possível por que o método faz parte de uma facade (interface) mantenha-o e coloque um @deprecated no javadoc dele.

Se precisar alterar o método com mais de um parâmetro, o ideal é fazer tudo de uma vez só para evitar retrabalho depois.

Muitos não têm o costume de retirar parâmetros, mesmo que não sejam mais usados. Eles mantêm o parâmetro boiando (inclusive eu :-D ) com a premissa de que não vai dar problema no comportamento do método, nisso temos razão, mas com certeza dará problema no seu entendimento ou no do pobre coitado alguns dias depois quando for dar manutenção.

Até mais,

Boas Práticas – Dica nº 2

10/setembro/2010 - Geral

Olá,

A dica de hoje é mover números mágicos do código para constantes com nomes sugestivos para facilitar a leitura por quem for dar manutenção futuramente.
No exemplo abaixo, o valor utilizado para converter km/h em m/s e vice-versa é 3.6, ao invés de repetir esse número várias vezes, colocamos em uma constante e usamos ela em todos os lugares que precisamos.

public double converterKMH2MS(double velocidade){
	return velocidade / 3.6;
}

public double converterMS2KMS(double velocidade){
	return velocidade * 3.6;
}

O código melhorado ficaria assim:


//
public static final double FATOR_CONVERSAO_KMH_MS = 3.6;

public double converterKMH2MS(double velocidade){
	return velocidade / FATOR_CONVERSAO_KMH_MS;
}

public double converterMS2KMS(double velocidade){
	return velocidade * FATOR_CONVERSAO_KMH_MS;
}

Dependendo da quantidade de constantes que você tem no seu sistema é bom agrupá-las em uma interface.

Até mais,
Roberto