Create a method that receives a generic class?

Asked

Viewed 55 times

3

I’ve been racking my brain with the Reflection API. I am writing a class (reader) that reads a CSV file and creates an Arraylist of objects based on CSV. I made a test class to write the code, only I want to adapt the code so it works with any class that is passed.

Main.java (main)

import java.nio.charset.Charset;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;

public class Principal {

    public static void main(String[] args) {

        ArrayList<Object> listaDeObjetos;
        Leitor objetoDaClasseLeitor = new Leitor();

        Path caminho = Paths.get("/home/filipe/eclipse-workspace/ReadCSVFile/src", "a.csv");
        Charset codificacao = Charset.forName("UTF-8");
        String separador = ",";
        ClasseDeTeste classe;
        classe = new ClasseDeTeste();

        try {
            System.out.println(objetoDaClasseLeitor.leArquivo(caminho, codificacao, separador, classeCriada));
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

}

Classedeteste.java

public class ClasseDeTeste {
    String id;
    String nome;
    String telefone;
    String email;

    public void setId(String id) {
        this.id = id;
    }

    public void setNome(String nome) {
        this.nome = nome;
    }

    public void setTelefone(String telefone) {
        this.telefone = telefone;
    }

    public void setEmail(String email) {
        this.email = email;
    }

}

Java reader.

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.format.TextStyle;
import java.util.ArrayList;
import java.util.List;

public class Leitor {

    List<String> linhas;
    String texto;
    ArrayList<Object> objetosCriados = new ArrayList<>();
    String[] colunas;
    Class<?> classePassada;
    ArrayList<Method>setters;

    ArrayList<Object> leArquivo(Path caminho, Charset codificacao, String separador, ClasseDeTeste classe) throws Exception {
        // Lê e processa o arquivo

        linhas = Files.readAllLines( caminho, codificacao );
        colunas = linhas.get(0).split(separador);

        //Crio um array para o nome dos setters
        String[] nomeDosSetters = new String[colunas.length];       

        //Transformo o nome das Colunas para um SetNome
        for(int i = 0; i < colunas.length; i ++){
            String nomeDoMetodo;
            nomeDoMetodo = ("set" + colunas[i].substring(0, 1).toUpperCase() +
                    colunas[i].substring(1).toLowerCase());

            nomeDosSetters[i] = nomeDoMetodo; 
        }

        //Crio uma nova instância com o nome da classe passada
        classePassada = classe.getClass();

        //Crio um Array de Objetos, será o array a ser retornado no final 
        for(int i = 1; i < linhas.size(); i++) {
            objetosCriados.add(classePassada.newInstance());
        }

        //Percorro as linhas (objetos) do csv
        for(int i = 1; i < linhas.size(); i++) {
            String[] valores = linhas.get(i).split(separador);

            //Percorro os valores de cada linha (objeto) do csv
            for(int j = 0; j < valores.length; j++) {
                Method setter2 = classePassada.getMethod(nomeDosSetters[j], String.class);
                setter2.invoke(objetosCriados.get(i-1), valores[j]);
            }
        }

        return objetosCriados;
    }



}

I want my method to accept any past class, and for that it looks like:

ArrayList<Object> leArquivo(Path caminho, Charset codificacao, String separador, **Class<?> classe**) throws Exception {
    }

It turns out that when I pass

ClasseDeTeste classe

for

Class<?> classe

My main file stops working and I’m not able to solve it. Any idea what might be happening?

  • The example of main apparently does not compile, I believe you changed the name of the variables when calling the System.out.println...

  • I ended up passing a previous version of the code. Where it is: System.out.println(objetoDaClasseLeitor.leArquivo(caminho, codificacao, separador, classeCriada)); Actually it is: System.out.println(objetoDaClasseLeitor.leArquivo(caminho, codificacao, separador, classe));

  • then just upgrade to the most appropriate version of the code =) just click on [Edit] and put the correct information

1 answer

1

If I understand correctly, you don’t need a property Class<?> classe in your class Leitor. Just use in your logic the class informed in the method parameter itself leArquivo(...).

Thus:

1) The signature of its method shall be:

ArrayList<Object> leArquivo(Path caminho, Charset codificacao, String separador, Class<?> classe) throws Exception

2) In its logic in the class Leitor, for example, in this passage:

//Crio um Array de Objetos, será o array a ser retornado no final 
for(int i = 1; i < linhas.size(); i++) {
     objetosCriados.add(classePassada.newInstance());
}

You will, instead of using classePassada.newInstance(), use classe (that came from the parameter) and follow with its logic.

Simplest example yet:

class Leitor {
    void exibirInfosDaClasse(Class<?> clazz){
        //uso direto clazz, não tenho necessidade de ter uma propriedade dentro da classe
        System.out.println(clazz.getName());
        System.out.println(Arrays.toString(clazz.getMethods()));
    }
}

class ClasseQualquer {
    public void metodo1(){};
    public void metodo2(){};
}

public final static void main(String... args) throws Exception {
        Leitor leitor = new Leitor();
        leitor.exibirInfosDaClasse(ClasseQualquer.class);
//imprime
//ClasseQualquer
//[public void ClasseQualquer.metodo1(), public void ClasseQualquer.metodo2() etc...]
    }
}

Browser other questions tagged

You are not signed in. Login or sign up in order to post.