Creación de instancias de una clase genérica en Java [duplicado]

Resuelto ripper234 asked hace 15 años • 10 respuestas

Sé que los genéricos de Java son algo inferiores a los de .Net.

Tengo una clase genérica Foo<T>y realmente necesito crear una Tinstancia Foousando un constructor sin parámetros. ¿Cómo se puede solucionar la limitación de Java?

ripper234 avatar Jul 07 '09 12:07 ripper234
Aceptado

Una opción es pasar Bar.class(o cualquier tipo que le interese, cualquier forma de especificar la Class<T>referencia adecuada) y mantener ese valor como campo:

public class Test {
    public static void main(String[] args) throws IllegalAccessException,
            InstantiationException {
        Generic<Bar> x = new Generic<>(Bar.class);
        Bar y = x.buildOne();
    }
}

public class Generic<T> {
    private Class<T> clazz;

    public Generic(Class<T> clazz) {
        this.clazz = clazz;
    }

    public T buildOne() throws InstantiationException, IllegalAccessException {
        return clazz.newInstance();
    }
}

public class Bar {
    public Bar() {
        System.out.println("Constructing");
    }
}

Otra opción es tener una interfaz "de fábrica" ​​y pasar una fábrica al constructor de la clase genérica. Eso es más flexible y no necesita preocuparse por las excepciones de reflexión.

Jon Skeet avatar Jul 07 '2009 05:07 Jon Skeet

Y esta es la implementación de Factory, como sugirió Jon Skeet :

interface Factory<T> {
    T factory();
}

class Araba {
    //static inner class for Factory<T> implementation
    public static class ArabaFactory implements Factory<Araba> {
        public Araba factory() {
            return new Araba();
        }
    }
    public String toString() { return "Abubeee"; }
}

class Generic<T> {
    private T var;

    Generic(Factory<T> fact) {
        System.out.println("Constructor with Factory<T> parameter");
        var = fact.factory();
    }
    Generic(T var) {
        System.out.println("Constructor with T parameter");
        this.var = var;
    }
    T get() { return var; }
}

public class Main {
    public static void main(String[] string) {
        Generic<Araba> gen = new Generic<Araba>(new Araba.ArabaFactory());
        System.out.print(gen.get());
    }
}

Producción:

Constructor with Factory<T> parameter
Abubeee
Özgür avatar Mar 12 '2010 11:03 Özgür

Aquí hay una forma bastante artificial de hacerlo sin usar explícitamente un argumento de constructor. Necesita extender una clase abstracta parametrizada.

public class Test {   
    public static void main(String [] args) throws Exception {
        Generic g = new Generic();
        g.initParameter();
    }
}

import java.lang.reflect.ParameterizedType;
public abstract class GenericAbstract<T extends Foo> {
    protected T parameter;

    @SuppressWarnings("unchecked")
    void initParameter() throws Exception, ClassNotFoundException, 
        InstantiationException {
        // Get the class name of this instance's type.
        ParameterizedType pt
            = (ParameterizedType) getClass().getGenericSuperclass();
        // You may need this split or not, use logging to check
        String parameterClassName
            = pt.getActualTypeArguments()[0].toString().split("\\s")[1];
        // Instantiate the Parameter and initialize it.
        parameter = (T) Class.forName(parameterClassName).newInstance();
    }
}

public class Generic extends GenericAbstract<Foo> {
}

public class Foo {
    public Foo() {
        System.out.println("Foo constructor...");
    }
}
Glenn avatar Jul 07 '2009 22:07 Glenn

Realmente necesito crear una instancia de una T en Foo usando un constructor sin parámetros

La respuesta simple es "no puedes hacer eso". Java usa el borrado de tipos para implementar genéricos que te impedirían hacer esto.

¿Cómo se puede solucionar la limitación de Java?

Una forma (podría haber otras) es pasar el objeto del que pasarías la instancia de T al constructor de Foo<T>. O podría tener un método setBar(T theInstanceofT);para obtener su T en lugar de crear una instancia en la clase misma.

hhafez avatar Jul 07 '2009 05:07 hhafez