You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@empire-db.apache.org by Rainer Döbele <do...@esteam.de> on 2011/07/24 14:00:20 UTC

Stupid generics question (possibly)

Hi,

 

This might be a stupid question possibly but I just don't feel like investigating myself.

 

I have introduced a new simple helper class called BeanResult to simplify queries for a list of POJO's a bit.

I looks roughly like this:

 

public class BeanResult<T extends Object> extends ArrayList<T>

{

    private DBCommand cmd;

    private Class<T> type;

    

    public BeanResult(Class<T> type, DBCommand cmd)

    {

        this.type = type;

        this.cmd = cmd;

    }

    

    public int fetch(Connection conn, int maxItems)

    {

        clear();

        DBReader reader = new DBReader();

        try {

            // Open and Read

            reader.open(cmd, conn);

            reader.getBeanList(this, type, maxItems);

            return size();

            

        } finally {

            reader.close();

        }

    }

}

 

In order to use it, I must write the following:

 

BeanResult<SampleBean> result = new BeanResult<SampleBean>(SampleBean.class, cmd);

 

What I don't like is, that I have to pass the SampleBean.class in the constructor.

I would rather just write:

 

BeanResult<SampleBean> result = new BeanResult<SampleBean>(cmd);

 

This is beause the getBeanList uses type.newInstance() to create new Instances of the bean.

 

Does anyone know whether and how to determine the Class from T or another option to get rid of this extra parameter.

I have checked the code in under the EMPIREDB-99 branch.

 

Regards

Rainer

 


re: Stupid generics question (possibly)

Posted by Rainer Döbele <do...@esteam.de>.
Hi Vladimir,

excellent. 
That answers all my questions.
And I do agree, that it's neither worth it nor desirable to sacrifice readability and robustness for one parameter.

So I will stick to my solution.
Just wanted to make sure, there is no better one :-)

Thanks,
Rainer


> from: Vladimir Lahoda [mailto:vlahoda@gmail.com]
> to: empire-db-dev@incubator.apache.org
> re: Re: Stupid generics question (possibly)
> 
> Hi, it is possible to obtain the runtime type of the generic parameter
> through a trick using subclassing and reflection, as described in this
> post:
> 
> http://www.artima.com/weblogs/viewpost.jsp?thread=208860
> 
> But I think that your solution with explicit constructor parameter is
> more robust, straightforward and readable.
> 
> Cheers,
> Vladimir
> 
> On 25. 7. 2011, at 8:36, Francis De Brabandere wrote:
> 
> > Because this generics info is not available at runtime?
> >
> > http://gafter.blogspot.com/2004/09/puzzling-through-erasure-
> answer.html
> > http://gafter.blogspot.com/2006/11/reified-generics-for-java.html
> >
> > On Mon, Jul 25, 2011 at 8:26 AM, Rainer Döbele <do...@esteam.de>
> wrote:
> >> Hi Andi,
> >>
> >> thanks for your answer. I should possibly have a look at Guava.
> >>
> >> As mentioned the problem is not really the DBReader, but the fact,
> that in order to fill the list, new instances of T have to created.
> >> So basically the problem can be reduced to:
> >>
> >> public class BeanResult<T extends Object> extends ArrayList<T>
> >> {
> >>
> >>    public BeanResult(Class<T> c, DBCommand cmd)
> >>    {
> >>        T obj = c.newInstance();
> >>    }
> >> ...
> >>
> >> And the question remains, whether or not it is possible at all, to
> get rid of the "Class<T> c" parameter.
> >> I don't really understand, why it is not possible to extract the
> Class from T.
> >>
> >> Regards,
> >> Rainer
> >>
> >>
> >> Andreas Fink wrote:
> >>> from: Andreas Fink [mailto:andi@andreasfink.com]
> >>> to: empire-db-dev@incubator.apache.org
> >>> re: Re: Stupid generics question (possibly)
> >>>
> >>> Hi Rainer.
> >>>
> >>> As long as you do not refactor "new DBReader()" to "new
> DBReader<T>()"
> >>> there won't be a way around it.
> >>> If you do not need to know the type in "reader.getBeanList" except
> for
> >>> casting, this Could suffice:
> >>>
> >>> class DBReader<T> {
> >>>
> >>>       getBeanList(beanResult, maxItems) {
> >>>               ...
> >>>               T someData = (T) someMethodCall();
> >>>               ...
> >>>       }
> >>>
> >>> }
> >>>
> >>> If you need to do more, stick to what you posted (this is how Google
> >>> Guava does it, btw.) or do something funny at runtime using
> reflection.
> >>>
> >>> The best source for help in cases like this is Angelika Langers
> generics
> >>> FAQ: http://www.angelikalanger.com/GenericsFAQ/JavaGenericsFAQ.html
> >>>
> >>> Cheers,
> >>> Andi.
> >>>
> >>> On Jul 24, 2011, at 2:00 PM, Rainer Döbele wrote:
> >>>
> >>>> Hi,
> >>>>
> >>>>
> >>>>
> >>>> This might be a stupid question possibly but I just don't feel like
> >>> investigating myself.
> >>>>
> >>>>
> >>>>
> >>>> I have introduced a new simple helper class called BeanResult to
> >>> simplify queries for a list of POJO's a bit.
> >>>>
> >>>> I looks roughly like this:
> >>>>
> >>>>
> >>>>
> >>>> public class BeanResult<T extends Object> extends ArrayList<T>
> >>>>
> >>>> {
> >>>>
> >>>>    private DBCommand cmd;
> >>>>
> >>>>    private Class<T> type;
> >>>>
> >>>>
> >>>>
> >>>>    public BeanResult(Class<T> type, DBCommand cmd)
> >>>>
> >>>>    {
> >>>>
> >>>>        this.type = type;
> >>>>
> >>>>        this.cmd = cmd;
> >>>>
> >>>>    }
> >>>>
> >>>>
> >>>>
> >>>>    public int fetch(Connection conn, int maxItems)
> >>>>
> >>>>    {
> >>>>
> >>>>        clear();
> >>>>
> >>>>        DBReader reader = new DBReader();
> >>>>
> >>>>        try {
> >>>>
> >>>>            // Open and Read
> >>>>
> >>>>            reader.open(cmd, conn);
> >>>>
> >>>>            reader.getBeanList(this, type, maxItems);
> >>>>
> >>>>            return size();
> >>>>
> >>>>
> >>>>
> >>>>        } finally {
> >>>>
> >>>>            reader.close();
> >>>>
> >>>>        }
> >>>>
> >>>>    }
> >>>>
> >>>> }
> >>>>
> >>>>
> >>>>
> >>>> In order to use it, I must write the following:
> >>>>
> >>>>
> >>>>
> >>>> BeanResult<SampleBean> result = new
> >>> BeanResult<SampleBean>(SampleBean.class, cmd);
> >>>>
> >>>>
> >>>>
> >>>> What I don't like is, that I have to pass the SampleBean.class in
> the
> >>> constructor.
> >>>>
> >>>> I would rather just write:
> >>>>
> >>>>
> >>>>
> >>>> BeanResult<SampleBean> result = new BeanResult<SampleBean>(cmd);
> >>>>
> >>>>
> >>>>
> >>>> This is beause the getBeanList uses type.newInstance() to create
> new
> >>> Instances of the bean.
> >>>>
> >>>>
> >>>>
> >>>> Does anyone know whether and how to determine the Class from T or
> >>> another option to get rid of this extra parameter.
> >>>>
> >>>> I have checked the code in under the EMPIREDB-99 branch.
> >>>>
> >>>>
> >>>>
> >>>> Regards
> >>>>
> >>>> Rainer
> >>>>
> >>>>
> >>>>
> >>>
> >>>
> >>> --
> >>> web:   http://andreasfink.com/
> >>> mail:  af@andreasfink.com
> >>> mobil: +34 65 1728443
> >>> tel:   +34 93 2082949
> >>
> >>
> >
> >
> >
> > --
> > http://www.somatik.be
> > Microsoft gives you windows, Linux gives you the whole house.


Re: Stupid generics question (possibly)

Posted by Vladimir Lahoda <vl...@gmail.com>.
Hi, it is possible to obtain the runtime type of the generic parameter through a trick using subclassing and reflection, as described in this post:

http://www.artima.com/weblogs/viewpost.jsp?thread=208860

But I think that your solution with explicit constructor parameter is more robust, straightforward and readable.

Cheers,
Vladimir
 
On 25. 7. 2011, at 8:36, Francis De Brabandere wrote:

> Because this generics info is not available at runtime?
> 
> http://gafter.blogspot.com/2004/09/puzzling-through-erasure-answer.html
> http://gafter.blogspot.com/2006/11/reified-generics-for-java.html
> 
> On Mon, Jul 25, 2011 at 8:26 AM, Rainer Döbele <do...@esteam.de> wrote:
>> Hi Andi,
>> 
>> thanks for your answer. I should possibly have a look at Guava.
>> 
>> As mentioned the problem is not really the DBReader, but the fact, that in order to fill the list, new instances of T have to created.
>> So basically the problem can be reduced to:
>> 
>> public class BeanResult<T extends Object> extends ArrayList<T>
>> {
>> 
>>    public BeanResult(Class<T> c, DBCommand cmd)
>>    {
>>        T obj = c.newInstance();
>>    }
>> ...
>> 
>> And the question remains, whether or not it is possible at all, to get rid of the "Class<T> c" parameter.
>> I don't really understand, why it is not possible to extract the Class from T.
>> 
>> Regards,
>> Rainer
>> 
>> 
>> Andreas Fink wrote:
>>> from: Andreas Fink [mailto:andi@andreasfink.com]
>>> to: empire-db-dev@incubator.apache.org
>>> re: Re: Stupid generics question (possibly)
>>> 
>>> Hi Rainer.
>>> 
>>> As long as you do not refactor "new DBReader()" to "new DBReader<T>()"
>>> there won't be a way around it.
>>> If you do not need to know the type in "reader.getBeanList" except for
>>> casting, this Could suffice:
>>> 
>>> class DBReader<T> {
>>> 
>>>       getBeanList(beanResult, maxItems) {
>>>               ...
>>>               T someData = (T) someMethodCall();
>>>               ...
>>>       }
>>> 
>>> }
>>> 
>>> If you need to do more, stick to what you posted (this is how Google
>>> Guava does it, btw.) or do something funny at runtime using reflection.
>>> 
>>> The best source for help in cases like this is Angelika Langers generics
>>> FAQ: http://www.angelikalanger.com/GenericsFAQ/JavaGenericsFAQ.html
>>> 
>>> Cheers,
>>> Andi.
>>> 
>>> On Jul 24, 2011, at 2:00 PM, Rainer Döbele wrote:
>>> 
>>>> Hi,
>>>> 
>>>> 
>>>> 
>>>> This might be a stupid question possibly but I just don't feel like
>>> investigating myself.
>>>> 
>>>> 
>>>> 
>>>> I have introduced a new simple helper class called BeanResult to
>>> simplify queries for a list of POJO's a bit.
>>>> 
>>>> I looks roughly like this:
>>>> 
>>>> 
>>>> 
>>>> public class BeanResult<T extends Object> extends ArrayList<T>
>>>> 
>>>> {
>>>> 
>>>>    private DBCommand cmd;
>>>> 
>>>>    private Class<T> type;
>>>> 
>>>> 
>>>> 
>>>>    public BeanResult(Class<T> type, DBCommand cmd)
>>>> 
>>>>    {
>>>> 
>>>>        this.type = type;
>>>> 
>>>>        this.cmd = cmd;
>>>> 
>>>>    }
>>>> 
>>>> 
>>>> 
>>>>    public int fetch(Connection conn, int maxItems)
>>>> 
>>>>    {
>>>> 
>>>>        clear();
>>>> 
>>>>        DBReader reader = new DBReader();
>>>> 
>>>>        try {
>>>> 
>>>>            // Open and Read
>>>> 
>>>>            reader.open(cmd, conn);
>>>> 
>>>>            reader.getBeanList(this, type, maxItems);
>>>> 
>>>>            return size();
>>>> 
>>>> 
>>>> 
>>>>        } finally {
>>>> 
>>>>            reader.close();
>>>> 
>>>>        }
>>>> 
>>>>    }
>>>> 
>>>> }
>>>> 
>>>> 
>>>> 
>>>> In order to use it, I must write the following:
>>>> 
>>>> 
>>>> 
>>>> BeanResult<SampleBean> result = new
>>> BeanResult<SampleBean>(SampleBean.class, cmd);
>>>> 
>>>> 
>>>> 
>>>> What I don't like is, that I have to pass the SampleBean.class in the
>>> constructor.
>>>> 
>>>> I would rather just write:
>>>> 
>>>> 
>>>> 
>>>> BeanResult<SampleBean> result = new BeanResult<SampleBean>(cmd);
>>>> 
>>>> 
>>>> 
>>>> This is beause the getBeanList uses type.newInstance() to create new
>>> Instances of the bean.
>>>> 
>>>> 
>>>> 
>>>> Does anyone know whether and how to determine the Class from T or
>>> another option to get rid of this extra parameter.
>>>> 
>>>> I have checked the code in under the EMPIREDB-99 branch.
>>>> 
>>>> 
>>>> 
>>>> Regards
>>>> 
>>>> Rainer
>>>> 
>>>> 
>>>> 
>>> 
>>> 
>>> --
>>> web:   http://andreasfink.com/
>>> mail:  af@andreasfink.com
>>> mobil: +34 65 1728443
>>> tel:   +34 93 2082949
>> 
>> 
> 
> 
> 
> -- 
> http://www.somatik.be
> Microsoft gives you windows, Linux gives you the whole house.


Re: Stupid generics question (possibly)

Posted by Francis De Brabandere <fr...@gmail.com>.
Because this generics info is not available at runtime?

http://gafter.blogspot.com/2004/09/puzzling-through-erasure-answer.html
http://gafter.blogspot.com/2006/11/reified-generics-for-java.html

On Mon, Jul 25, 2011 at 8:26 AM, Rainer Döbele <do...@esteam.de> wrote:
> Hi Andi,
>
> thanks for your answer. I should possibly have a look at Guava.
>
> As mentioned the problem is not really the DBReader, but the fact, that in order to fill the list, new instances of T have to created.
> So basically the problem can be reduced to:
>
> public class BeanResult<T extends Object> extends ArrayList<T>
> {
>
>    public BeanResult(Class<T> c, DBCommand cmd)
>    {
>        T obj = c.newInstance();
>    }
> ...
>
> And the question remains, whether or not it is possible at all, to get rid of the "Class<T> c" parameter.
> I don't really understand, why it is not possible to extract the Class from T.
>
> Regards,
> Rainer
>
>
> Andreas Fink wrote:
>> from: Andreas Fink [mailto:andi@andreasfink.com]
>> to: empire-db-dev@incubator.apache.org
>> re: Re: Stupid generics question (possibly)
>>
>> Hi Rainer.
>>
>> As long as you do not refactor "new DBReader()" to "new DBReader<T>()"
>> there won't be a way around it.
>> If you do not need to know the type in "reader.getBeanList" except for
>> casting, this Could suffice:
>>
>> class DBReader<T> {
>>
>>       getBeanList(beanResult, maxItems) {
>>               ...
>>               T someData = (T) someMethodCall();
>>               ...
>>       }
>>
>> }
>>
>> If you need to do more, stick to what you posted (this is how Google
>> Guava does it, btw.) or do something funny at runtime using reflection.
>>
>> The best source for help in cases like this is Angelika Langers generics
>> FAQ: http://www.angelikalanger.com/GenericsFAQ/JavaGenericsFAQ.html
>>
>> Cheers,
>> Andi.
>>
>> On Jul 24, 2011, at 2:00 PM, Rainer Döbele wrote:
>>
>> > Hi,
>> >
>> >
>> >
>> > This might be a stupid question possibly but I just don't feel like
>> investigating myself.
>> >
>> >
>> >
>> > I have introduced a new simple helper class called BeanResult to
>> simplify queries for a list of POJO's a bit.
>> >
>> > I looks roughly like this:
>> >
>> >
>> >
>> > public class BeanResult<T extends Object> extends ArrayList<T>
>> >
>> > {
>> >
>> >    private DBCommand cmd;
>> >
>> >    private Class<T> type;
>> >
>> >
>> >
>> >    public BeanResult(Class<T> type, DBCommand cmd)
>> >
>> >    {
>> >
>> >        this.type = type;
>> >
>> >        this.cmd = cmd;
>> >
>> >    }
>> >
>> >
>> >
>> >    public int fetch(Connection conn, int maxItems)
>> >
>> >    {
>> >
>> >        clear();
>> >
>> >        DBReader reader = new DBReader();
>> >
>> >        try {
>> >
>> >            // Open and Read
>> >
>> >            reader.open(cmd, conn);
>> >
>> >            reader.getBeanList(this, type, maxItems);
>> >
>> >            return size();
>> >
>> >
>> >
>> >        } finally {
>> >
>> >            reader.close();
>> >
>> >        }
>> >
>> >    }
>> >
>> > }
>> >
>> >
>> >
>> > In order to use it, I must write the following:
>> >
>> >
>> >
>> > BeanResult<SampleBean> result = new
>> BeanResult<SampleBean>(SampleBean.class, cmd);
>> >
>> >
>> >
>> > What I don't like is, that I have to pass the SampleBean.class in the
>> constructor.
>> >
>> > I would rather just write:
>> >
>> >
>> >
>> > BeanResult<SampleBean> result = new BeanResult<SampleBean>(cmd);
>> >
>> >
>> >
>> > This is beause the getBeanList uses type.newInstance() to create new
>> Instances of the bean.
>> >
>> >
>> >
>> > Does anyone know whether and how to determine the Class from T or
>> another option to get rid of this extra parameter.
>> >
>> > I have checked the code in under the EMPIREDB-99 branch.
>> >
>> >
>> >
>> > Regards
>> >
>> > Rainer
>> >
>> >
>> >
>>
>>
>> --
>> web:   http://andreasfink.com/
>> mail:  af@andreasfink.com
>> mobil: +34 65 1728443
>> tel:   +34 93 2082949
>
>



-- 
http://www.somatik.be
Microsoft gives you windows, Linux gives you the whole house.

re: Stupid generics question (possibly)

Posted by Rainer Döbele <do...@esteam.de>.
Hi Andi,

thanks for your answer. I should possibly have a look at Guava.

As mentioned the problem is not really the DBReader, but the fact, that in order to fill the list, new instances of T have to created.
So basically the problem can be reduced to:

public class BeanResult<T extends Object> extends ArrayList<T>
{
    
    public BeanResult(Class<T> c, DBCommand cmd)
    {
        T obj = c.newInstance();
    }
...

And the question remains, whether or not it is possible at all, to get rid of the "Class<T> c" parameter.
I don't really understand, why it is not possible to extract the Class from T.

Regards,
Rainer


Andreas Fink wrote:
> from: Andreas Fink [mailto:andi@andreasfink.com]
> to: empire-db-dev@incubator.apache.org
> re: Re: Stupid generics question (possibly)
> 
> Hi Rainer.
> 
> As long as you do not refactor "new DBReader()" to "new DBReader<T>()"
> there won't be a way around it.
> If you do not need to know the type in "reader.getBeanList" except for
> casting, this Could suffice:
> 
> class DBReader<T> {
> 
> 	getBeanList(beanResult, maxItems) {
> 		...
> 		T someData = (T) someMethodCall();
> 		...
> 	}
> 
> }
> 
> If you need to do more, stick to what you posted (this is how Google
> Guava does it, btw.) or do something funny at runtime using reflection.
> 
> The best source for help in cases like this is Angelika Langers generics
> FAQ: http://www.angelikalanger.com/GenericsFAQ/JavaGenericsFAQ.html
> 
> Cheers,
> Andi.
> 
> On Jul 24, 2011, at 2:00 PM, Rainer Döbele wrote:
> 
> > Hi,
> >
> >
> >
> > This might be a stupid question possibly but I just don't feel like
> investigating myself.
> >
> >
> >
> > I have introduced a new simple helper class called BeanResult to
> simplify queries for a list of POJO's a bit.
> >
> > I looks roughly like this:
> >
> >
> >
> > public class BeanResult<T extends Object> extends ArrayList<T>
> >
> > {
> >
> >    private DBCommand cmd;
> >
> >    private Class<T> type;
> >
> >
> >
> >    public BeanResult(Class<T> type, DBCommand cmd)
> >
> >    {
> >
> >        this.type = type;
> >
> >        this.cmd = cmd;
> >
> >    }
> >
> >
> >
> >    public int fetch(Connection conn, int maxItems)
> >
> >    {
> >
> >        clear();
> >
> >        DBReader reader = new DBReader();
> >
> >        try {
> >
> >            // Open and Read
> >
> >            reader.open(cmd, conn);
> >
> >            reader.getBeanList(this, type, maxItems);
> >
> >            return size();
> >
> >
> >
> >        } finally {
> >
> >            reader.close();
> >
> >        }
> >
> >    }
> >
> > }
> >
> >
> >
> > In order to use it, I must write the following:
> >
> >
> >
> > BeanResult<SampleBean> result = new
> BeanResult<SampleBean>(SampleBean.class, cmd);
> >
> >
> >
> > What I don't like is, that I have to pass the SampleBean.class in the
> constructor.
> >
> > I would rather just write:
> >
> >
> >
> > BeanResult<SampleBean> result = new BeanResult<SampleBean>(cmd);
> >
> >
> >
> > This is beause the getBeanList uses type.newInstance() to create new
> Instances of the bean.
> >
> >
> >
> > Does anyone know whether and how to determine the Class from T or
> another option to get rid of this extra parameter.
> >
> > I have checked the code in under the EMPIREDB-99 branch.
> >
> >
> >
> > Regards
> >
> > Rainer
> >
> >
> >
> 
> 
> --
> web:   http://andreasfink.com/
> mail:  af@andreasfink.com
> mobil: +34 65 1728443
> tel:   +34 93 2082949


Re: Stupid generics question (possibly)

Posted by Andreas Fink <an...@andreasfink.com>.
Hi Rainer.

As long as you do not refactor "new DBReader()" to "new DBReader<T>()" there won't be a way around it.
If you do not need to know the type in "reader.getBeanList" except for casting, this Could suffice:

class DBReader<T> {
	
	getBeanList(beanResult, maxItems) {
		...
		T someData = (T) someMethodCall();
		...
	}
	
}

If you need to do more, stick to what you posted (this is how Google Guava does it, btw.) or do something funny at runtime using reflection.

The best source for help in cases like this is Angelika Langers generics FAQ: http://www.angelikalanger.com/GenericsFAQ/JavaGenericsFAQ.html

Cheers,
Andi.

On Jul 24, 2011, at 2:00 PM, Rainer Döbele wrote:

> Hi,
> 
> 
> 
> This might be a stupid question possibly but I just don't feel like investigating myself.
> 
> 
> 
> I have introduced a new simple helper class called BeanResult to simplify queries for a list of POJO's a bit.
> 
> I looks roughly like this:
> 
> 
> 
> public class BeanResult<T extends Object> extends ArrayList<T>
> 
> {
> 
>    private DBCommand cmd;
> 
>    private Class<T> type;
> 
> 
> 
>    public BeanResult(Class<T> type, DBCommand cmd)
> 
>    {
> 
>        this.type = type;
> 
>        this.cmd = cmd;
> 
>    }
> 
> 
> 
>    public int fetch(Connection conn, int maxItems)
> 
>    {
> 
>        clear();
> 
>        DBReader reader = new DBReader();
> 
>        try {
> 
>            // Open and Read
> 
>            reader.open(cmd, conn);
> 
>            reader.getBeanList(this, type, maxItems);
> 
>            return size();
> 
> 
> 
>        } finally {
> 
>            reader.close();
> 
>        }
> 
>    }
> 
> }
> 
> 
> 
> In order to use it, I must write the following:
> 
> 
> 
> BeanResult<SampleBean> result = new BeanResult<SampleBean>(SampleBean.class, cmd);
> 
> 
> 
> What I don't like is, that I have to pass the SampleBean.class in the constructor.
> 
> I would rather just write:
> 
> 
> 
> BeanResult<SampleBean> result = new BeanResult<SampleBean>(cmd);
> 
> 
> 
> This is beause the getBeanList uses type.newInstance() to create new Instances of the bean.
> 
> 
> 
> Does anyone know whether and how to determine the Class from T or another option to get rid of this extra parameter.
> 
> I have checked the code in under the EMPIREDB-99 branch.
> 
> 
> 
> Regards
> 
> Rainer
> 
> 
> 


--
web:   http://andreasfink.com/
mail:  af@andreasfink.com
mobil: +34 65 1728443
tel:   +34 93 2082949