Instanciar objeto a partir de uma String

Olá pessoal,
estou com um problema…
preciso instanciar uma classe a partir de se nome contido numa string.
é meio estranho mas vai funcionar +/- assim…

Em um determinado ponto do programa, usuário digita/escolhe o nome de uma classe numa lista
suponhamos que eu tenha um classe carro

public class carro{

   public carro(){

   }

}

entao o usuário digita num campo a palavra “carro” e a partir dessa string eu tenho que fazer o new carro();

pesquisei sobre refletion e generics, mas acho que não estou sabendo usar… ou realmente não tem jeito…
se alguem tiver uma dica…

Valew galera;;

Ponha os try/catchs adequados.

Object obj = Class.forName ("carro").newInstance();

Obviamente um objeto obj tal como o criado dessa maneira é meio inútil, já que o programa não sabe que métodos dele devem ser chamados (fora os que já estão definidos em java.lang.Object).

Você tambem deve lembrar que o nome que é passado para o reflection deve ser o nome completo da classe, ou seja caminho do pacote onde a classe esta + nome da classe (ex “com.minhaEmpresa.automoveis.Carro”). Outra coisa que pode causar problemas é a maneira como a instanciação é feita. Você pode usar o método newInstance(), mas o ideal é criar um objeto de contrutor e usa-lo para a instanciação.
Fora isso tem o que o thingol falou, para usar um método da classe o usuário teria que passar o nome do método, e, caso houvessem, os parâmetros e seus tipos…

Espero que tenha ajudado

Abraço

[quote=thingol]Ponha os try/catchs adequados.

Object obj = Class.forName ("carro").newInstance();

Obviamente um objeto obj tal como o criado dessa maneira é meio inútil, já que o programa não sabe que métodos dele devem ser chamados (fora os que já estão definidos em java.lang.Object).[/quote]

Continuando.

Mas voce ainda tem algumas opções interessantes para invocalos.

Class<?> clazz = Class.forName("carro");
Method metodo = clazz.getDeclaredMethod("umMetodo");
Object obj = clazz.newInstance();
metodo.invoke(obj);

Uma opção mais interessante era obrigar todas essas classes implementarem uma interface e fazer o cast.

Class<?> clazz = Class.forName("carro");
Method metodo = clazz.getDeclaredMethod("umMetodo");
Object obj = clazz.newInstance();
InterfaceImpl objeto = (InterfaceImpl) obj;

Olá… vamos supor que o metodo que eu queira invocar é um getNomeCarro() que retorna uma String
Sem fazer o cast pra uma interface carro nao tem jeito de eu pegar o valor de retorno no caso uma string ?

Valew

[quote=guilherme_ha]Olá… vamos supor que o metodo que eu queira invocar é um getNomeCarro() que retorna uma String
Sem fazer o cast pra uma interface carro nao tem jeito de eu pegar o valor de retorno no caso uma string ?

Valew[/quote]

É claro que tem, mas aí você precisa saber várias coisas:

  • Qual é o nome do método
  • Que parâmetros você precisa passar
  • Qual o tipo do objeto retornado pelo método

Isso é um porre, e fica bem mais fácil se você souber que o tal objeto pertence a uma classe que implementa uma determinada interface (além de ser mais rápido. )

Entao…
eu sei o nome do metodo a ser chamado
e seu retorno…
porem eu não sei qual é o objeto…

como ficaria pra eu pegar a string de retorno de um metodo ?

Valew

Digamos que a tal classe não implemente uma determinada interface, mas você saiba que ela tem um método

public String getNome(); 

Por favor, estude as classes de java.lang.reflect. Olhe o Javadoc (http://java.sun.com/javase/6/docs/api/java/lang/reflect/package-summary.html ); reflection é mais chato do que difícil.

import java.lang.reflect.*;

class Carro {
    public String getNome () {
        return "Herbie";
    }
}

class Aviao {
    public String getNome () {
        return "B-52";
    }
}

class TesteCarro {
    public static void main(String[] args) throws Exception {
        Object obj1 = Class.forName ("Carro").newInstance();
        Object obj2 = Class.forName ("Aviao").newInstance();
        Method m1 = obj1.getClass().getMethod ("getNome", new Class[0]);
        Object ret1 = m1.invoke (obj1, new Object [0]);
        if (ret1 instanceof String) {
            System.out.println ("new Carro().getNome() retornou " + (String) ret1);
        }
        Method m2 = obj2.getClass().getMethod ("getNome", new Class[0]);
        Object ret2 = m2.invoke (obj2, new Object [0]);
        if (ret2 instanceof String) {
            System.out.println ("new Aviao().getNome() retornou " + (String) ret2);
        }
    }
}

era exatamente isso que eu queria…
me ajudou pra karamba…
valew…

Uma duvida galera,
e pra fazer isso caso a classe esteja em outro projeto dentro do meu workspace?
como funciona?