Lista + Generics

Ola Pessoal,

Estou tentando implementar o seguinte trecho de codigo:

public class Resultado(){
   boolean status;
   List<?> lista;
}

Na classe acima a lista estou tentando adicionar dois tipos de objetos:

public class Casa{
  //campos casa
}

...

public class Apartamento{
   //campos apartamento
}

Tento criar um handler para tratar essas listas

public class Handler{
    private List<?> lista;

    public void handle(int tipoImovel){
        if(tipoImovel = 1){
           lista = new ArrayList<Casa>();

           Casa casa = new Casa();

           lista.add(casa); 
        }
    }
}

A linha lista.add(casa) nao compila, o que estou fazendo errado?

Valeu

Posta o erro que está sendo apresentado e referencia qual a linha está sendo indicada como causa do mesmo.

Tentei simplificar o exemplo

public class Main {
	
	public List<?> lista;
	
	public void gerarList(){
		
		lista = new ArrayList<Casa>();
		
		Casa casa = new Casa();
		
		lista.add(casa);
		
	}
}

A linha lista.add(casa) não compila.

O que estou fazendo de errado?

Acho que descobri o que eu estava errando, mas agora como faço para ler a lista?

public class Main {
	
	public List<?> lista;
	
	public void criarLista(){
		
		List<Casa> listaCasa = new ArrayList<Casa>();
		
		Casa casa = new Casa();
		casa.setProprietario("Joao");
		
		listaCasa.add(casa);
		lista = listaCasa;
		
	}
	
	public void lerLista(){
		//TODO: Não sei como fazer :(	
	}
	
	
}

Se alguém tiver alguma sugestão sobre os wildcards para melhorar esse exemplo eu agradeço.

Valeu.

Consegui fazer a leitura da lista

	public void lerLista(){
		Iterator<?> it = lista.iterator();
		
		while(it.hasNext()){
			Object obj = it.next();
			
			if(obj instanceof Casa){
				Casa casa = (Casa) obj;
				System.out.println(casa.getProprietario());
			}
			
		}
	}

Agora não estou conseguindo imaginar como faço a engenharia reversa para obter a lista original.

Quando criei a lista generica eu fiz:

List<Casa> listaCasa = new ArrayList<Casa>();
List<?> lista = listaCasa;

Agora ao obter a lista quero fazer algo como:

List<Casa> listaCasa = lista;

Abraço.

Acho que era só isso:

	@SuppressWarnings("unchecked")
	public void engenhariaReversa(){
			
		List<Casa> listaCasa = (List<Casa>) lista;
			
		for(Casa casa : listaCasa){
			System.out.println("Proprietário: " + casa.getProprietario());
		}
	}

Mas a última dúvida que tenho é se haveria uma maneira mais prática para descobrir o tipo da lista, por exemplo, digamos que eu tivesse que identificar se a lista é de casas ou de apartamentos, acredito que eu teria que fazer:

		ArrayList<?> arrayList = (ArrayList<?>) lista;
		
		if(arrayList.get(0) instanceof  Casa){
			List<Casa> listaCasa = (List<Casa>) lista;
		}else if(arrayList.get(0) instanceof  Apartamento){
			List<Apartamento> listaApartamento = (List<Apartamento>) lista;
		}

Haveria uma maneira mais fácil de se fazer ou é assim mesmo que devo manipular as listas?

Abraço

Bom dia.

Ao que eu sei, essa linha nem compila: [quote]ArrayList<?> arrayList = (ArrayList<?>) lista; [/quote]
O seu ArrayList teria de definir um tipo, se quiser algo “generico”, use um Object.

Eu desconheço uma forma de testar se a sua lista é de um objeto tipo x ou tipo y, o que você poderia fazer é utilizar reflection para invocar o método desejado por você.
Eu já fiz isso, eu precisava realizar uma implementação indêntica mas com objetos distintos, o que eu fiz foi chamar via reflection o método que eu precisava.

Usando singleton e tals, mas enfim, dê uma pesquisa ou outra pessoa lhe indica um meio.
Abraços.

Bom dia.

A linha compilou, mas se eu fosse usar com reflection como eu poderia fazer.

Podes criar um Singleton que lhe retorne a instancia da qual você precisa.
Antes para pensar em uma solução, porque você quer uma lista generica?!

Qual seria o uso dela?!:slight_smile:
É melhor entender bem o contexto, pois estou em dúvida.

Abraços.

A aplicação irá receber um arquivo várias linhas durante o upload do arquivo o usuário indica qual é o tipo de arquivo (Casa ou Apartamento).

Depois que a aplicação recebe o arquivo ela deverá realizar o parse do arquivo de acordo com o seu template (basea-se no tipo de arquivo) e gera uma lista com os objetos Casa ou Apartamento.
Após realizar o parse e popular a lista a aplicação irá direcionar essa lista para que ela seja processada por outros serviços.

– Controler

Recebe arquivo

FileManager

Recebe o arquivo e o seu tipo -> Processa arquivo que pode retornar um List<Casa> ou um List<Apartamento> por isso pensei em fazer List<?>

O List<?> retorna para o controler, e o controler precisa obter o objeto especifico por exemplo Lista<Casa> para que essa lista seja processada no seu devido serviço.

Se alguém puder me ajudar até mesmo com outra solução eu agradeço.

Segue uma simulação do código completo, o código abaixo está funcionado.

O risco só vai ser confiar na linha List<Casa> listaCasa = (List<Casa>) lista, apesar que como no método que processa o arquivo eu vou indicar o tipo de arquivo acho que não vai ter problema, o que você acham?


public class Main {
	
	public List<?> lista;
	
	public void criarLista(){
		
		List<Casa> listaCasa = new ArrayList<Casa>();
		
		Casa casa = new Casa();
		casa.setProprietario("Joao");
		
		listaCasa.add(casa);
		lista = listaCasa;
		
	}

	public void engenhariaReversa(){
			
		@SuppressWarnings("unchecked")
		List<Casa> listaCasa = (List<Casa>) lista;
			
		for(Casa casa : listaCasa){
			System.out.println("Proprietário: " + casa.getProprietario());
		}
		
	}
	
	public static void main(String[] args) {
		Main main = new Main();
		
		main.criarLista();
		main.engenhariaReversa();
	}
	
	
}

Abraço

Opa!
Então, fica muito mais fácil assim.

Se existe um padrão x para documentos do tipo casa, um y para apartamentos e assim por diantes, podes criar apenas um ENUM e posteriormente um SWITCH para identificar qual o tipo de objeto que você vai utilizar. Não há necessidade de reflection ou coisa do tipo.

Abraços!