Pergunta

Leve o seguinte:

public Class<List<String>> getObjectType() {
    // what can I return here?
}

O que a classe da expressão literal posso voltar a partir deste método que irá satisfazer os genéricos e compilar? List.class não irá compilar, e nem vai List.<String>class.

Se você está se perguntando "por que", eu estou escrevendo uma implementação de FactoryBean<List<String>> da Primavera, o que me obriga a implementar Class<List<String>> getObjectType(). No entanto, este é não uma pergunta Primavera.

edit:. Meus gritos lamentosos foram ouvidos pelos poderes que ser pelo SpringSource, e assim Primavera 3.0.1 terá o tipo de retorno de getObjectType() alterado para Class<?>, que evita cuidadosamente o problema

Foi útil?

Solução

Você sempre pode converter para o que você precisa, como esta

return (Class<List<String>>) new ArrayList<String>().getClass();

ou

return (Class<List<String>>) Collections.<String>emptyList().getClass();

Mas presumo que não é o que você está depois. Ele funciona bem, com uma advertência, mas não é exatamente "bela".

Eu encontrei este

Por que não há literal classe para tipos parametrizados curinga?

Porque um tipo parametrizado curinga não tem representação exata tipo de tempo de execução.

Assim elenco pode ser o único caminho a percorrer.

Outras dicas

Você nunca deve usar o Class<List<String>> construção. É sem sentido, e deve produzir um aviso em Java (mas não). instâncias de classe sempre representam tipos matérias, para que possa ter Class<List>; é isso aí. Se você quer algo para representar um reificado tipo genérico como List<String>, você precisa de um "super tipo token" como usos Guice:

http: //google-guice.googlecode. com / git / javadoc / com / google / inserção / TypeLiteral.html

A existência de um Class<List<String>> é inerentemente perigosa. aqui está o porquê:

// This statement generates a warning - for a reason...
Class<List<String>> unsafeListClass = (Class<List<String>>) (Class<?>) List.class;

List<Integer> integerList = new ArrayList<Integer>(); // Ok
integerList.add(42); // Ok

System.out.println(unsafeListClass.isInstance(integerList)); // Prints "true".
List<String> stringList =
   unsafeListClass.cast(integerList); // Succeeds, with no warning!
stringList.add("Hello, World!"); // Also succeeds with no warning

for (int x: integerList) {
    // Compiles without warning, but throws ClassCastException at runtime
    System.out.println(100-x);
}

este link em springframework.org que dá algumas dicas.

por exemplo.

List<String> myList = new ArrayList<String>();
return (Class<List<String>>)myList.getClass();

Você pode implementar esse método como este:

public Class<List<String>> getObjectType() {
    return (Class<List<String>>) ((Class)List.class);
}

Confira esta discussão nos fóruns Sol:

http://forums.sun.com/thread.jspa?threadID=5253007

E o post referência que descreve um trabalho em torno usando "fichas tipo super":

http://gafter.blogspot.com/2006/12 /super-type-tokens.html

Eu não tenho certeza se isso é possível de todo, uma vez que qualquer literal classe será compilado para Class.forName(...) e desde que isso acontece em tempo de execução não há nenhuma informação genérica esquerda.

Eu não tenho certeza, mas a seguinte pergunta que fiz pode ser de relevância para você ...

java genéricos parâmetros de tipo e operações sobre esses tipos

O que sobre isso:

public class TestMain {
    public static void main(String[] args) throws Exception {
        Type type = TestMain.class.getMethod("dummy").getGenericReturnType();
        System.out.println("type = " + type);
    }

    public List<Integer> dummy() {return null;}
}

Esta impressões:

type = java.util.List<java.lang.Integer>

A seguinte abordagem é problemática:

> public Class<List<String>> getModelType() {
>   return (Class<List<String>>) new ArrayList<String>().getClass();
> }

por exemplo. se você quiser testar se um objeto exemplo do tipo

org.eclipse.emf.common.util.BasicEList<String> 

é do tipo

List<String> 

com base no resultado da abordagem getModelType acima mencionado (), por exemplo:

BasicEList<String> fromObject = ...;
if (getModelType().isAssignableFrom(fromObject.getClass())) {
    transferFromModelToUi(getModelType().cast(fromObject));
}

que irá resultar em falso Considerando que deve ser verdade porque ambos os objetos implementar a lista de interfaces (desde getModelType () retorna um objeto de classe do tipo de lista e não ArrayList).

Aqui está uma abordagem que trabalhou para mim (um pesado pouco, mas leva a resultados corretos no exemplo acima, poderia ser transferido para um inicializador estático):

public Class<List<String>> getModelType() {
    Class<?> arrayListClass = new ArrayList<String>().getClass();
    Class<?>[] interfaces = arrayListClass.getInterfaces();
    int index = 0;
    for (int i = 0; i < interfaces.length; i++) {
        if (interfaces[i].equals(List.class)) {
            index = i;
            break;
        }
    }
    return (Class<List<String>>) interfaces[index];
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top