Como criar um array de JComboBox?

Bom eu declaro

JComboBox<String> combo[];

e no corpo do programa digito o sequinte código:

combo = new JComboBox<String>[10];

Fiz isso porque para cada elemento do array quero um JComboBox diferente, até o java 4 era só fazer o seguinte:

JComboBox combo[] = new JComboBox[10];

que tava tudo certo, depois no corpo do programa era só preencher um a um

for (int i =0; i<=10; i++) combo[i] = new MinhaLista();

agora quando eu digito:

combo = new JComboBox<String>[10];

da o seguinte erro:

javac Great.java -Xlint:unchecked
Great.java:1425: error: generic array creation
combo = new JComboBox[10];

Já procurei na internet livros e não achei literatura que ensine a criar array de JComboBox.
Alguém já passou por isso?

1 curtida

Boa pergunta. Não sabia que não era possível fazer dessa forma. Fui tentar aqui, e soh funciona dessa forma:

JComboBox<String>[] combobox = new JComboBox[1];
combobox[0] = new JComboBox<String>();

Vou dá uma pesquisada para ver se acho alguma referência disso. Se achar algo, posto aqui.

Achei isso: https://docs.oracle.com/javase/tutorial/java/generics/restrictions.html#createArrays

A partir do Java 5 a classe JComboBox é genérica e não é possível instanciar arrays informando um tipo genérico.

Entretanto, você pode muito bem instanciar o seu array de JComboBox da seguinte maneira:

@SuppressWarnings("unchecked")
JComboBox<String>[] combo = new JComboBox[10]; // perceba que não usa o <String> na instanciação, só na declaração
1 curtida

Olá.
Pessoal desculpa a demora em responder.
Notei que fazendo dessa forma que o staroski deu a dica até funciona. O problema que eu encontrei é que quando (pelo menos aqui rodou desse jeito) eu declaro a variável lá em cima

JComboBox<String>[] combo;

e no corpo do programa eu instancio o array

@SuppressWarnings("unchecked")
combo = new JComboBox[10];

ele da erro. Bom entretanto eu encontrei uma maneira de mascarar o problema, que é criando uma classe que encapsula um JComboBox e dessa maneira eu crio um array dessa classe. Exemplo

//importo tudo pra garantir
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.util.*;
import java.sql.*;
import java.lang.reflect.*;
import java.lang.*;
import java.io.*;
import cedruslibani.cad.*;

public class ComboBox {
	
	private JComboBox<String> combo;
	
	public ComboBox() {
		super();
	}
	
	public void preencheCombo(String[] valor) {
		combo = new JComboBox<String>(valor);
	}
	
	public JComboBox<String> getCombo() {
		return combo;
	}
}

Eu to achando mais seguro. Se alguém tiver uma sugestão ou idéia melhor agradeço.
grato.
Fábio.

1 curtida

É que você está declarando sem informar o tipo genérico.

Você deveria declarar assim:

JComboBox<Tipo de dado que vai inserir no combo>[] combo;

Você pode anotar sua classe com @SuppressWarnings("rawtypes")

Como assim mais seguro?
Que risco você está vendo?
Você sabe que os tipos genéricos só existem em tempo de compilação, né?
Depois de compilado o tipo genérico é substituído por Object.

Foi desnecessário você encapsular um JComboBox em outra classe.
Acho que só falta você aprender/entender a utilizar tipos genéricos.

Todavia, você poderia muito ver ter estendido o JComboBox ao invés de encapsular ele.

1 curtida

O erro é o seguinte:
error: expected
combo = new JComboBox[10];

Agora tem outro jeito de fazer. Declaro o combo lá em cima e no corpo do programa faço o seguinte:
@SuppressWarnings(“unchecked”)
JComboBox[] combos = new JComboBox[tamanhoTabela];
combo = combos;

Assim funciona.
A propósito. Consigo fazer JComboBox<tipoGenérico> combo?
É que eu estava trabalhando com uma versão do java mais antigo o 4 e estou migrando pro 8 e essa sintaxe não existia <?>. Realmente preciso aprender/entender isso mesmo.
Mas todavia do jeito que eu mostrei funcionou bem. Agradeço a ajuda.
Fábio.

Não coloquei o erro completo:
error: expected
combo = new JComboBox[10];
Mas como eu disse funciona fazendo aquele “truque”.

Deve, pois os seus erros são justamente pelo fato de você não estar fazendo isso.

Mas você pode muito bem continuar utilizando uma classe genérica como se fosse uma classe não genérica, é só anotar sua classe com @SuppressWarnings("rawtypes")

Exemplo:

import javax.swing.JComboBox;

@SuppressWarnings("rawtypes")
public class Exemplo {

    private JComboBox[] combo;

    public Exemplo() {
        int qtd = 10;
        combo = new JComboBox[qtd];
        for (int i = 0; i < qtd; i++) {
            combo[i] = new JComboBox();
            combo[i].addItem("Bla bla bla " + i);
            combo[i].addItem("Ble ble ble " + i);
            combo[i].addItem("Bli bli bli " + i);
            combo[i].addItem("Blo blo blo " + i);
            combo[i].addItem("Blu blu blu " + i);
        }
    }
}

Essa classe ComboBox que você criou é completamente desnecessária e só agrega uma complexidade que não precisa existir, além do mais, você fez uma serie de import que não utiliza e ainda pôs um comentário “importo tudo pra garantir”, pra garantir o quê?

Assim, se não quer utilizar a sintaxe de tipo genérico, OK, anota sua classe com @SuppressWarnings("rawtypes") e segue a vida, mas eu recomendo utilizar, torna o código mais legível.

E, em último dos últimos dos casos, se você realmente quer usar uma outra classe não genérica no lugar do JComboBox, reescreva sua classe ComboBox da seguinte forma:

import javax.swing.JComboBox;

public class ComboBox extends JComboBox<String> {

    private static final long serialVersionUID = 1;

    public ComboBox() {}

    public ComboBox(String[] itens) {
        super(itens);
    }
}

Po, legal cara. Valeu! entendi. É que eu estava trabalhando num projeto antigo e eu compilava no java 4 e no java 8 tem essa sintaxe <?> que eu nunca tinha visto. É um negocinho mas como ainda não me acostumei/aprendi/entendi fica tudo meio confuso pra mim. Parece que agora tem muita coisa com essa sintaxe <?> , como por exemplo ClassLoaders pra fazer uso desse recurso é necessario entender essa sintaxe. Olha se vc tiver algum link ou algum arquivo pdf que explique melhor essa nova maneira de programar eu agradeceria, se não tiver, só o que vc já me ajudou, já ajudou muito. Muito obrigado.
Deus abençoe pela ajuda.
Fábio.

Isso foi introduzido no Java 5, tem bastante material na internet só pesquisar por Java 5 Generics.

Generics basicamente surgiram pra gente não precisar fazendo cast ao trabalhar com coleções ou outras classes que podem conter outros objetos.

Eu gosto de explicar como funciona usando um exemplo hipotético de uma classe Pote que possua os métodos adicionar e remover.

public class Pote {

    public void adicionar(Object item) {
        // aqui você armazena o item numa lista
    }
    
    public void remover(Object item) {
        // aqui você remove o item da lista
    }
}

Até o Java 4 você poderia criar um objeto Pote e adicionar alguns objetos do tipo Bolacha dentro do Pote desse jeito:

Pote poteDeBolacha = new Pote();

Bolacha bolacha1 = new Bolacha();
Bolacha bolacha2 = new Bolacha();
Bolacha bolacha3 = new Bolacha();

poteDeBolacha.adicionar(bolacha1);
poteDeBolacha.adicionar(bolacha2);
poteDeBolacha.adicionar(bolacha3);

Isso funciona perfeitamente bem, mas dá uma margem à erros, por exemplo, nada impede que um programador desatento escreva algo como:

Bala balinha = new Bala();

poteDeBolacha.adicionar(balinha);

Perceba que nada impede o programador de inserir qualquer coisa no objeto poteDeBolacha?

Pois bem, o generics veio justamente pra resolver esse tipo de situação, ele permite que eu diga qual é o conteúdo que meu Pote aceita, então eu posso reescrever a classe Pote dessa forma:

public class Pote<T> {

    public void adicionar(T item) {
        // aqui você armazena o item numa lista
    }
    
    public void remover(T item) {
        // aqui você remove o item da lista
    }
}

Perceba que os parâmetros dos métodos não são mais Object, agora eles são T, que é o nome que eu dei para o tipo genérico de dado na declaração da classe.
É convenção utilizar somente uma letra para nomear tipos genéricos, mas nada impede de você declarar sua classe assim:

public class Pote<TipoDeConteudo> {

    public void adicionar(TipoDeConteudo item) {
        // aqui você armazena o item numa lista
    }
    
    public void remover(TipoDeConteudo item) {
        // aqui você remove o item da lista
    }
}

Vai funcionar da mesma forma.

O bacana disso é que agora você pode declarar um Pote de Bolacha dessa forma:

Pote<Bolacha> poteDeBolacha = new Pote<>();

E continua adicionando bolachas da mesma forma como antes:

Bolacha bolacha1 = new Bolacha();
Bolacha bolacha2 = new Bolacha();
Bolacha bolacha3 = new Bolacha();

poteDeBolacha.adicionar(bolacha1);
poteDeBolacha.adicionar(bolacha2);
poteDeBolacha.adicionar(bolacha3);

O mais legal vem agora, como você declarou o Pote dizendo que o tipo dele é Bolacha, se você tentar fazer isso:

Bala balinha = new Bala();

poteDeBolacha.adicionar(balinha);

Você terá um erro de compilação, pois sua variável poteDeBolacha agora só aceita receber objetos do tipo Bolacha, você não pode mais pôr Bala dentro desse Pote.

E funciona dessa mesma forma para as listas, para maps, para ComboBoxes, enfim, qualquer classe genérica.

Resumindo, se a classe é genérica, significa que durante a declaração eu posso dizer o tipo de dado que aquele objeto vai encapsular, conter e/ou manipular.

1 curtida

Oh Ricardo. Agradeço muito. Essa Sua explicação vai fazer com que eu resolva uma série de problemas que eu tinha no meu projeto. Olha, ganhei meu dia. Ótima explicação! Problema(s) resolvido.
grato.
Fábio.

1 curtida