generics

Hola saludo para todos estoy aprendiendo generics y me puse a inventar algo.

Mi app me da una lista de clases ClaseJava1, ClaseJava2 lo que intento hacer es:

Controler<ClaseJava1> = new Controler(paramtros...);

La pregunta es como <ClaseJava1>? Porque mi variable es un simple String con el nombre de la clase, pero como logro para
que me tome según la clase seleccionada?

Comentarios

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.

la idea

es evitar algo como

    control<Clase1> c = new Control(....);
    control<Clase2> c = new Control(....);
    control<Clase3> c = new Control(....);
    control<Clase4> c = new Control(....);
    control<Clase5> c = new Control(....);
    control<Clase6> c = new Control(....);
    control<Clase7> c = new Control(....);
    control<Clase8> c = new Control(....);
    control<Clase9> c = new Control(....);
    control<Clase10> c = new Control(....);
    control<Clase11> c = new Control(....);
    control<Clase12> c = new Control(....);
Imagen de Sr. Negativo

Re:generics

....

la pregunta es como por que mi variable es un simple String con el nombre de la clase pero como logro para
que me tome según la clase seleccionada

Tal vez lo que buscas es instanceof

 ...
 ...
Control<OtraClase> c= new Control();

if( c instanceof OtraClase){
   //hacer algo
}

ok

pero como defino

Control<OtraClase> c= new Control();
Control<MiClase> c= new Control();
Control<XXX> c= new Control();

la idea es no de finir 3 control y verificar con el instaceof por cual me voy a ir la idea es tratar de que si escojo el tipo de datos PtraClse o Miclase se vaya por definiendo un solo Control c= new Control(); por que si definino 100 clases voy a tener 100 Control c= new Control();????

Imagen de Cid

No entendi muy bien pero

No entendi muy bien pero podría ser que lo que quieres es usar un comodín y en genéricos el comodin es "?" checa esto te servira de algo: Wildcards igualmente sería interesante que checaras la covarianza, contravarianza e invarianza en este tema: aquí

Imagen de ezamudio

no puedes

Recuerda que los generics son borrados en tiempo de ejecución, por lo que no puedes hacer x instanceof Control<OtraClase> sino solamente x instanceof Control.

Tener tipos de parámetro reificados (reified generics) es algo que nos costó mucho trabajo pero logramos tener en Ceylon.

Pero si lo que quieres es además que la instancia que tienes de tu clase Control cambie de tipo así nomás de repente, eso sí no se puede:

class Control<T> {
  T t;
  public Control(T t) { this.t=t; }
  public void set(T t) {this.t=t; }
}

//y entonces sí
Control<Clase1> c1 = new Control<>(new Clase1());

En tiempo de compilación, c1.set() esperará un parámetro de tipo Clase1. Solamente podrías pasarle otros valores del mismo tipo, o bien de un subtipo de Clase1, pero si tienes por ejemplo Clase2 y no tiene nada que ver con Clase1 entonces no podrías pasarle a c1 un valor de tipo Clase2.

WTF!

me toca tener una gran lista y por algun codicional seleccionar cual voy a usar

Control<Clase1> c1 = new Control();
Control<Clase2> c2 = new Control();
Control<Clase3> c3 = new Control();
Control<Clase n> cn = new Control();

una idea para evitar esto???

............

Imagen de ezamudio

diseño

Pues modificar el diseño de tu componente... realmente necesita ese parámetro de tipo? para qué lo usa? en el código que pusiste en tu último comentario ni siquiera parece que le pases el parámetro de tipo al constructor (en Java 7 puedes usar el operador diamante, Control<Clase99> c99 = new Control<>().

Realmente no entiendo qué es lo que pretendes lograr, necesitas darnos más información, porque incluso aunque Java tuviera reified generics tendrías que hacer el instanceof y tener una gran lista de componentes, o tal vez no tan grande pero sí una lista, si el parámetro de tipo fuera covariante.

Imagen de ezamudio

problemas conceptuales

Tal vez estás pensando que los generics están muy limitados y la realidad podría ser que simplemente estás tratando de darles un uso para el cual no fueron incluidos en el lenguaje.

para que lo uso

Hice un programa de reportes, entonces si el control arranca con clase1 se refiere al reporte 1, con base a esa clase por refelxion el me construye el jtable con encabezado por defecto con el nombre de los parámetros de mi clase pero con el uso de anotaciones que me ayuda a personalizar el nombre y que campo quiero que salga el el JTable o no. La magia es que si me cambio a clase2 me carga todo según los atributos y parámetros de clase2 y desde ese jtable hay un botón que me exporta a excel, asi que cuando me manda hacer un reporte nuevo solo creo la clase la consulta a la base y lo demás esta automático. Lo pensé de esa manera.

Imagen de Eduardo Vargas

Idea Reflection & Generics

Hola hackchan

Tal vez también te sería de utilidad que le dieras un vistazo al Diseño en java, para que así nos explicaras un poquito mejor lo que necesitas :=) Pero bueno, te paso una idea, no sé si sea bueno tu diseño, pero la idea es para hacer lo que tú quieres: utilizar generics con reflection, pasando una cadena para instanciar la clase y así evitar tener que hacer cientos o miles de "new Control..."
Te paso el código con la idea general. Compila y corre bien

package cert;

public interface Clase {

        void imprime();
       
}

package cert;

public class Clase1 implements Clase {

        private String name = "Soy clase 1";

        public void imprime() {
                System.out.println(name);
        }

}

package cert;

public class Clase2 implements Clase{

        private String name = "Soy clase 2";   
       
        public void imprime() {
                System.out.println(name);
        }
       
}

package cert;

public class ClaseGeneric <T> {

        T clase;
       
        public ClaseGeneric(T clase){
                this.clase = clase;
        }
       
        T getClase() {
                return clase;
        }
       
       
}

package cert;

public class TestClaseGeneric {

        public static void main(String[] args) {

                String[] claseVariable = { "cert.Clase1", "cert.Clase2" };
                ClaseGeneric<Clase> claseGenerica;
                try {
                        for (String clase : claseVariable) {
                                claseGenerica = new ClaseGeneric<Clase>((Clase) Class.forName(clase)
                                                .newInstance());
                                ((Clase) claseGenerica.getClase()).imprime();
                       
                        }
                } catch (InstantiationException | IllegalAccessException
                                | ClassNotFoundException e) {
                        e.printStackTrace();
                }

        }

}

cool

gracias por tu aporte y cada vez que aprendo mas sobre generics no se como no los usaba antes, me distes unas ideas voy a chekar gracias.

Imagen de bferro

Aun no capto tu problema

Es un poco difícil entender tu problema para poder decidir si es el caso correcto que quieres usar para practicar con programación genérica.

Imagen de Eduardo Vargas

Creo que no es correcto usar generics en este problema

Me parece que hackchan quería que le diéramos ideas para su diseño de sistema de reportes en el que él ya había decidido que sería muy útil utilizar los generics. Tal vez se le olvidó o no alcanzó a ver las ventajas de la herencia, interfaces y del polimorfismo y como anda estudiando sobre generics pensó que esa sería la solución más adecuada.

Creo que hackchan tenía dos problemas principales:
1.- Como evitar escribir cientos de veces "new Clase(....)"
2.- Cómo usar los generics para poder trabajar con cada una de las 100 o más clases de reportes que tuviera, de acuerdo a un parámetro recibido en una clase genérica.

El código que le compartí, sólo es para satisfacer la duda de cómo utilizar los generics y recibir una referencia a un objeto sin tener que escribir cientos de veces "New Clase(...), pero creo que lo más adecuado para que una de los cientos de clases "reporte" se ejecute de acuerdo a un parámetro de tipo "String", es el uso de la herencia, o las interfaces, así como le mostré en el código, pero sin el uso de los generics.
Y seguramente tampoco necesite ese ciclo "for each" que puse, porque con tan sólo recibir un "String", puede instanciar su clase "reporte" correspondiente.

Entonces, la clase con el método main quedaria así:

package cert;

public class TestClaseGeneric2 {
       
        public static void main(String[] args) {

                String[] claseVariable = { "cert.Clase1", "cert.Clase2" };
                try {
                        for (String clase : claseVariable) {
                                ((Clase)Class.forName(clase).newInstance()).imprime();
                        }
                } catch (InstantiationException | IllegalAccessException
                                | ClassNotFoundException e) {
                        e.printStackTrace();
                }
        }
}

ok

no he olvidado las ventajas del poli y la herencia solo que el genircs mas que todo es para un componente que hice
que es no mas que una Jtable dicho jtable su encabezado se contruye apartir de las los atributos de la clase del reporte
la cantidad de columnas que voy a mostar igual depende de unas anotcianes que cree para mis clases
con ese componente generico

cuando incicia mi aplicacion en el menu escojo reporte1 ese reporte1.class en mi dao hago la consulta del reporte
y simplemente todos esos datos de respuetsa los meto en un List que paso como atributoa mi componente
y listo ya tengo un crud automatico con la opcion de filtrar y exportar a excel y pdf la opcion extra es graficar antes para cada crud yo creaba la tabla para lista la info y toda esa vuelta que quita tiempo ahora obtengo un Jlist y se lo paso a mi componente :)

Por lo que describes suena a

Por lo que describes suena a que no necesitas tener tu clase control generificada, sino pasarle la clase como parámetro:

Control  control = new Control( stringConSeleccionDelUsuarioAqui() );
...
class Control {
    Class toIntrospect;
    public Control( String className ) {
        toIntrospect = Class.forName( className );
       // use it, e.g.
        Field[] fields = toIntrospect.getFields();
        Annotation[] annotations = toIntrospect.getAnnotations();
    }
}
...

p.d. Intenta usar comas, puntos y mayúsculas cuando escribas. Tu texto es mucho mas difícil de entender cuando no lo haces

se podria hacer del alguna manera de la siguiente

lo que dices esta bien pero se podria hacer asi o mejor dicho como lograria hacer esto:

Class toIntrospect;
toIntrospect = Class.forName( className );

  List<toIntrospect> listaReportes=
            controlReporte.listaRecaudoPlanPostpago(db, "01/04/14","30/04/14");

la idea es que ese list sea cual sea del tipo ya lo recibe un componente que hize que un jtable con sus filtros y su generador de excel.
la idea es que segun la clase que seleccione generero el jlist de dicha clase se lo paso a mi componente y lito todo esta hecho.

Los generics son una

Los generics son una herramienta para tiempo de compilación y no de ejecución. Te sirven para evitar hacer cast o poder reutilizar alguna funcionalidad "generica" y que el compilador te ayude a detectar errores. Por lo que se puede deducir de lo que escribes, les estas queriendo dar una utilizad para lo que no fueron diseñados por eso se siente tan forzado.

Una idea super simple que puedes aplicar si insistes en usar generics generar ese código con un mini programa, o hasta con excel y pegarlo en tu clase

int i = 0;
for ( String aClass : listOfClasses ) {
    System.out.printf("Control<%s>  control$%d = new Control();", aClass, i++ );
}

ok

pero lo del hacer

Control<Clase> control = new Control()

ya no va, :) la idea es como logro si tengo 20 reportes voy a tener 20 clases, mi componente donde muestro la informacion, la filtro, la grafico,y exporto a excel ya esta listo y funciona muy bien solo debo pasarle a ese componente un List con la informacion;
Pero como te comento si tengo 20 clases o mas voy a tener una lista de
de List lista1 = new ArrayList();
List lista2 = new ArrayList();
List lista3 = new ArrayList();
List lista4 = new ArrayList();
.......................................
.....................................

si el usuario selecciono reporte 1
List lista1 = new ArrayList();
micomponenteGrafisco.set(lista1)
quiero evitar a toda costa que cada vez que tenga una clase para un Nuevo Reporte tengo que ir a editar mi programa añadir que hay una nueva opcion
List lista5 = new ArrayList();
compilar y ejecutar y subir a produccion

Sigue siendo lo mismo,

Sigue siendo lo mismo, quieres instanciar generics en tiempo de ejecución y eso simplemente no funciona porque asi fue diseñado :

http://docs.oracle.com/javase/tutorial/java/generics/restrictions.html#c...

Y lo mejor de todo es que probablemente ni lo necesitas, si estas introspectando tus objetos para determinar sus características, lo puedes seguir haciendo sin generics.

Tu tienes un componente gráfico que recibe una lista de objetos, que es lo que hace con esa lista?

ok

el componente grafico es un Jtable que se contruye segun las carectiristicas de la clase de dicha lista con su anotaciones basicas por ejemplo una clase con tres registros y si la acompaña una anotacion de titulo ese es el titulo del encabezado del Jtable, de la misma forma se me crear un lista de opciones de de filtrado segun la cantidad de atributos de mi clase y el resultado o el contedido de mi jtable lo puedo graficar, o mandar exporta a un excel todo eso lo logo por instropeccion solo le mando el List y listo todo lo demas esta hecjo por arte de magia.

Ah pues mejor aun, no necesitas generics para esto.

Ah pues mejor aun, no necesitas generics para esto.

>el componente grafico es un Jtable que se contruye segun las carectiristicas de la clase de dicha lista con su anotaciones basicas

Ok, eso lo puedes hacer sin generics

> de la misma forma se me crear un lista de opciones de de filtrado segun la cantidad de atributos de mi clase y el resultado o el contenido de mi jtable

También

>lo puedo graficar, o mandar exporta a un excel todo eso lo logo por introspección solo le mando el List y listo todo lo demás esta hecho por arte de magia.

Ah pues esta perfecto, puedes hacer tu lista de objects o si todos tus objetos pertenecen a la misma jerarquía o implementan una interfaz común puedes hacer tu lista de la super clase o de la interfaz

List<Object> lista = new ArrayList<Object>();
o...
List<Reporte> lista = new ArrayList<Reporte>();
// si tus reportes son
class ReporteX extends Reporte {
..
}
o
class ReporteY implements Reporte {
...
}

Si toda la información la sacas de la clase con reflection , usar object deberia de bastar.

Para crear instancias y agregarlas al arreglo usar someClass.newInstance();

ok

perfecto, si claro ya con eso solo es trabajar mis daos para que llame el dao correspodiente.

ahora lo cambie

cambie la vuelta ahora uso spring y tengo en el context todos los daos cargados todos ellos lo centralizo en un gran dao con todas las funciones, cada funcion es un reporte getreporte1, getreporte2,
getReporte3..... ahora como le hago para seleccionar la que necesito no se si tengo un check por ejemplo seleccionado reporte1 me tome automaticamente getReporte1