Java 1.5 List's

classic Classic list List threaded Threaded
9 messages Options
Reply | Threaded
Open this post in threaded view
|

Java 1.5 List's

Nathan Maves
When using this code...


List<Student> students = new List<Student>();


why does it not come out as...

<students>
        <student>
        </student>
</students>



How can I write a converts for a List<Student>?

Nathan
Reply | Threaded
Open this post in threaded view
|

Re: Java 1.5 List's

Madoc
Do You know what is called "type erasure"? - If not, read it in the
documentation for the JDK 1.5 Generics feature.

Generics are only part of the Java syntax. At runtime, the information
contained in "<Student>" is not there anymore. So XStream has no chance
to "know" that it is a list of students.

You could also do the following:

List<Student> students = new List<Student>();
((List)students).add(new Integer(42));

This wouldn't throw an exception. What do You say now? ;-)

Nathan Maves schrieb:

> When using this code...
>
>
> List<Student> students = new List<Student>();
>
>
> why does it not come out as...
>
> <students>
>     <student>
>     </student>
> </students>
>
>
>
> How can I write a converts for a List<Student>?
>
> Nathan
>
Reply | Threaded
Open this post in threaded view
|

Re: Java 1.5 List's

Matthias-15

Correction:

The example code must be:

    List<Student> = new ArrayList<Student>();
    ((List)students).add(new Integer(42));

(Of course, "new List()" won't work because List is an interface.)

Matthias schrieb:
Do You know what is called "type erasure"? - If not, read it in the documentation for the JDK 1.5 Generics feature.

Generics are only part of the Java syntax. At runtime, the information contained in "<Student>" is not there anymore. So XStream has no chance to "know" that it is a list of students.

You could also do the following:

List<Student> students = new List<Student>();
((List)students).add(new Integer(42));

This wouldn't throw an exception. What do You say now? ;-)

Nathan Maves schrieb:
When using this code...


List<Student> students = new List<Student>();


why does it not come out as...

<students>
    <student>
    </student>
</students>



How can I write a converts for a List<Student>?

Nathan


Reply | Threaded
Open this post in threaded view
|

Re: Java 1.5 List's

Nathan Maves
In reply to this post by Madoc
I was looking more into it and found this in the Class.class api.

public TypeVariable<Class<T>>[] getTypeParameters()

and TypeVariable.getName()
        Returns the name of this type variable, as it occurs in the source  
code.

Any thoughts?

Nathan

On Jan 30, 2006, at 9:50 AM, Matthias wrote:

> Do You know what is called "type erasure"? - If not, read it in the  
> documentation for the JDK 1.5 Generics feature.
>
> Generics are only part of the Java syntax. At runtime, the  
> information contained in "<Student>" is not there anymore. So  
> XStream has no chance to "know" that it is a list of students.
>
> You could also do the following:
>
> List<Student> students = new List<Student>();
> ((List)students).add(new Integer(42));
>
> This wouldn't throw an exception. What do You say now? ;-)
>
> Nathan Maves schrieb:
>> When using this code...
>> List<Student> students = new List<Student>();
>> why does it not come out as...
>> <students>
>>     <student>
>>     </student>
>> </students>
>> How can I write a converts for a List<Student>?
>> Nathan

Reply | Threaded
Open this post in threaded view
|

Re: Java 1.5 List's

Madoc
Would return and array of containing one "java.lang.Object" type
variable in this case. The concrete type parameter information is lost
at runtime, believe me, and there is absolutely NO way around this.

If You are desparate, write Your own Converter and use annotations.

Nathan Maves schrieb:

> I was looking more into it and found this in the Class.class api.
>
> public TypeVariable<Class<T>>[] getTypeParameters()
>
> and TypeVariable.getName()
>     Returns the name of this type variable, as it occurs in the source  
> code.
>
> Any thoughts?
>
> Nathan
>
> On Jan 30, 2006, at 9:50 AM, Matthias wrote:
>
>> Do You know what is called "type erasure"? - If not, read it in the  
>> documentation for the JDK 1.5 Generics feature.
>>
>> Generics are only part of the Java syntax. At runtime, the  
>> information contained in "<Student>" is not there anymore. So  XStream
>> has no chance to "know" that it is a list of students.
>>
>> You could also do the following:
>>
>> List<Student> students = new List<Student>();
>> ((List)students).add(new Integer(42));
>>
>> This wouldn't throw an exception. What do You say now? ;-)
>>
>> Nathan Maves schrieb:
>>
>>> When using this code...
>>> List<Student> students = new List<Student>();
>>> why does it not come out as...
>>> <students>
>>>     <student>
>>>     </student>
>>> </students>
>>> How can I write a converts for a List<Student>?
>>> Nathan
>
>
>
Reply | Threaded
Open this post in threaded view
|

Re: Java 1.5 List's

Justin T. Sampson-2
The type variable information is indeed available at runtime.
Class.getTypeParameters returns the type parameters of the class
itself, which isn't what you want here. What you want here is the
actual classes bound to those type variables in the particular
field, which is available from Field. See below for an example.

More to the point, though, XStream does use the name of (or alias
for) the actual class of each element of a collection, even
without generics, doesn't it?

Cheers,
Justin


[sandbox/TypeVariablesTest.java]

package sandbox;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import junit.framework.TestCase;

public class TypeVariablesTest extends TestCase
{
    public void testClassTypeParameters()
    {
        TypeVariable<Class<Foo>>[] typeParameters =
                Foo.class.getTypeParameters();
        assertEquals(1, typeParameters.length);
        assertEquals("T", typeParameters[0].getName());
    }

    public void testField() throws Exception
    {
        Field field = Bar.class.getField("foo");
        ParameterizedType type =
                (ParameterizedType) field.getGenericType();
        Type[] typeArguments = type.getActualTypeArguments();
        assertEquals(1, typeArguments.length);
        assertEquals(Long.class, typeArguments[0]);
    }
}


[sandbox/Foo.java]

package sandbox;

public class Foo<T>
{
}


[sandbox/Bar.java]

package sandbox;

public class Bar
{
    public Foo<Long> foo;
}
Reply | Threaded
Open this post in threaded view
|

Re: Java 1.5 List's

Nathan Maves
Good to know!

Yeah my real issue is how to get

List<List<Content>> dataMatrix;

to print out

<row>
        <content>
        <content>
        ...
</row>
...


On Jan 30, 2006, at 1:09 PM, Justin T. Sampson wrote:

> The type variable information is indeed available at runtime.
> Class.getTypeParameters returns the type parameters of the class
> itself, which isn't what you want here. What you want here is the
> actual classes bound to those type variables in the particular
> field, which is available from Field. See below for an example.
>
> More to the point, though, XStream does use the name of (or alias
> for) the actual class of each element of a collection, even
> without generics, doesn't it?
>
> Cheers,
> Justin
>
>
> [sandbox/TypeVariablesTest.java]
>
> package sandbox;
>
> import java.lang.reflect.Field;
> import java.lang.reflect.ParameterizedType;
> import java.lang.reflect.Type;
> import java.lang.reflect.TypeVariable;
> import junit.framework.TestCase;
>
> public class TypeVariablesTest extends TestCase
> {
>     public void testClassTypeParameters()
>     {
>         TypeVariable<Class<Foo>>[] typeParameters =
>                 Foo.class.getTypeParameters();
>         assertEquals(1, typeParameters.length);
>         assertEquals("T", typeParameters[0].getName());
>     }
>
>     public void testField() throws Exception
>     {
>         Field field = Bar.class.getField("foo");
>         ParameterizedType type =
>                 (ParameterizedType) field.getGenericType();
>         Type[] typeArguments = type.getActualTypeArguments();
>         assertEquals(1, typeArguments.length);
>         assertEquals(Long.class, typeArguments[0]);
>     }
> }
>
>
> [sandbox/Foo.java]
>
> package sandbox;
>
> public class Foo<T>
> {
> }
>
>
> [sandbox/Bar.java]
>
> package sandbox;
>
> public class Bar
> {
>     public Foo<Long> foo;
> }

Reply | Threaded
Open this post in threaded view
|

Re: Java 1.5 List's

Nathan Maves
In reply to this post by Justin T. Sampson-2
Good to know!

Yeah my real issue is how to get

List<List<Content>> dataMatrix;

to print out

<row>
        <content>
        <content>
        ...
</row>
...


On Jan 30, 2006, at 1:09 PM, Justin T. Sampson wrote:

> The type variable information is indeed available at runtime.
> Class.getTypeParameters returns the type parameters of the class
> itself, which isn't what you want here. What you want here is the
> actual classes bound to those type variables in the particular
> field, which is available from Field. See below for an example.
>
> More to the point, though, XStream does use the name of (or alias
> for) the actual class of each element of a collection, even
> without generics, doesn't it?
>
> Cheers,
> Justin
>
>
> [sandbox/TypeVariablesTest.java]
>
> package sandbox;
>
> import java.lang.reflect.Field;
> import java.lang.reflect.ParameterizedType;
> import java.lang.reflect.Type;
> import java.lang.reflect.TypeVariable;
> import junit.framework.TestCase;
>
> public class TypeVariablesTest extends TestCase
> {
>     public void testClassTypeParameters()
>     {
>         TypeVariable<Class<Foo>>[] typeParameters =
>                 Foo.class.getTypeParameters();
>         assertEquals(1, typeParameters.length);
>         assertEquals("T", typeParameters[0].getName());
>     }
>
>     public void testField() throws Exception
>     {
>         Field field = Bar.class.getField("foo");
>         ParameterizedType type =
>                 (ParameterizedType) field.getGenericType();
>         Type[] typeArguments = type.getActualTypeArguments();
>         assertEquals(1, typeArguments.length);
>         assertEquals(Long.class, typeArguments[0]);
>     }
> }
>
>
> [sandbox/Foo.java]
>
> package sandbox;
>
> public class Foo<T>
> {
> }
>
>
> [sandbox/Bar.java]
>
> package sandbox;
>
> public class Bar
> {
>     public Foo<Long> foo;
> }

Reply | Threaded
Open this post in threaded view
|

Re: Java 1.5 List's

Justin T. Sampson-2
In reply to this post by Nathan Maves
Nathan Maves wrote:

> Yeah my real issue is how to get
>
> List<List<Content>> dataMatrix;
>
> to print out
>
> <row>
>         <content>
>         <content>
>         ...
> </row>
> ...

Ah, so you were hoping to be able to do this, which isn't legal:

    xstream.alias("row", List<Content>.class);

Instead you probably have to define something like this:

    public class Row extends ArrayList<Content> {}

And then register the alias like this:

    xstream.alias("row", Row.class);

You can still declare the field as:

    List<List<Content>> dataMatrix;

But just use 'new Row()' when you construct rows, instead of using
'new ArrayList<Content>()'.

As Matthias pointed out, the list object itself doesn't give any
clue as to its own parameterization, and it's not enforced anyway
(except when reading out of the list in a context where the
parameterized type is known), so it's not trivial to define an
alias for a parameterized type. It might be possible to implement
it using indirect information from field declarations, though.

Cheers,
Justin