The Source for Java Technology Collaboration

Home » java.net Forums » JDK » Feedback and Suggestions

Thread: Identifying Generics

Welcome, Guest Help
Login Login
Guest Settings Guest Settings
Reply to this Thread Reply to this Thread Search Forum Search Forum Back to Thread List Back to Thread List

Permlink Replies: 11 - Last Post: Jan 15, 2006 4:42 AM by: aviadbd
aviadbd

Posts: 15
Identifying Generics
Posted: Dec 17, 2005 9:56 PM
  Click to reply to this thread Reply

Anyone thought of adding the ability to discover which generics types are currently effective on a certain class?

Meaning: I have a field defined as:

Collection<Integer> myCollection;

Reflecting it's type would reveal only the type parameters (using getTypeParameters) which would be named "E" with no bounds. There is no way to get "Integer" with the current reflection ability - Even though the JRE could keep that information when a generic class is instantiated.

Two options I can see on doing that:
* Saving the info for each instance. Adds some info to a class, indeed.
* Creating a different Class for each type parameters set (like what's being done with arrays of different compound types and dimensions?). Might slow down reflection even more, but that's what reflection's all about.. :)

Aviad.

alexlamsl

Posts: 343
Re: Identifying Generics
Posted: Dec 18, 2005 1:53 AM   in response to: aviadbd
  Click to reply to this thread Reply

Generics is implemented through type-erasure, hence the information that you want (Integer in Collection<Integer> ) would not be present in the class file.

Although I often find that such information can be rendered redundant by a change of design, when one needs to one can employ the following constructor pattern to preserve such information:


public class A<T> {

private final Class<T> type;

// Option 1
public A(T obj) // and other params
{
type = (Class<T> ) obj.getClass();
// ...
}

// Option 2
public A(Class<T> type) // and other params
{
this.type = type;
// ...
}

}


aviadbd

Posts: 15
Re: Identifying Generics
Posted: Dec 18, 2005 2:26 AM   in response to: alexlamsl
  Click to reply to this thread Reply

Oh I know about Erasure. You can read my thoughts about it, which are similar to what I wrote above, here: http://javachaos.blogspot.com/2005/12/avoiding-erasure.html

What I'm saying is that Erasure and keeping the identity of the generic types aren't contradictive. If the JVM is of version 6, it can save the data in Object or generate a different Class instance. That's my suggestion - To maintain this data during the runtime.

soupdragon

Posts: 81
Re: Identifying Generics
Posted: Jan 9, 2006 10:09 AM   in response to: aviadbd
  Click to reply to this thread Reply

It seems to me that, if you don't do erasure, you have to add the generics information to the Object memory structure. For small objects this could be a substantial increase in overhead, plus a significant change in the JVM. And there are small generic objects (e.g. references).

tackline

Posts: 238
Re: Identifying Generics
Posted: Jan 9, 2006 10:56 AM   in response to: soupdragon
  Click to reply to this thread Reply

Currently objects have a pointer to their runtime class information. If they had runtime generic parameter information, they would still only need a single pointer.

The necessary change is that instead of pointing to class information, a structure is referenced containing the old erased class pointer and pointers to the generic arguments. In most cases there would be a one-to-one correspondence between these type information structures and non-abstract classes, so the memory overhead is quite minimal.

Reference objects may be bigger than you expect. To be useful, they also need to point to something.

soupdragon

Posts: 81
Re: Identifying Generics
Posted: Jan 9, 2006 11:47 AM   in response to: tackline
  Click to reply to this thread Reply

> Currently objects have a pointer to their runtime
> class information. If they had runtime generic
> parameter information, they would still only need a
> single pointer.
>

You could do it that way, of course, but wouldn't that signifcantly increase access times to class, which I presume the JVM needs to do rather a lot?

tackline

Posts: 238
Re: Identifying Generics
Posted: Jan 9, 2006 1:12 PM   in response to: soupdragon
  Click to reply to this thread Reply

> You could do it that way, of course, but wouldn't
> that signifcantly increase access times to class,
> which I presume the JVM needs to do rather a lot?

Not significantly. One extra load. It's not like anyone cares too much about "virtual" method call overhead as it is. I'd be surprised if reduction in runtime type checking didn't more than make up for the penalty.

aviadbd

Posts: 15
Re: Identifying Generics
Posted: Jan 9, 2006 11:47 AM   in response to: tackline
  Click to reply to this thread Reply

Also, you need to remember that the data needs to be stored in the bytecode of the .class file itself. Currently, it doesn't seem like instances in inner scopes carry on their generic definitions.

aviadbd

Posts: 15
Re: Identifying Generics
Posted: Jan 15, 2006 4:42 AM   in response to: aviadbd
  Click to reply to this thread Reply

Basically, it sounds like its about claiming that some things just won't work on earlier JVMs. Or, produce a minor version for each that knows to ignore this extra data in the .class files. I don't know the exact complications of it. Anyone?

tackline

Posts: 238
Re: Identifying Generics
Posted: Dec 18, 2005 3:17 AM   in response to: aviadbd
  Click to reply to this thread Reply

It's retrieving full type information from objects which is the problem (as it doesn't exist). Type information from fields and the like is straightforward. I put a little code together to dump a field's type.

import java.lang.reflect.*;

class DumpFieldType {
public static void main(String[] args) throws Throwable {
dumpFieldType(Example.class, "field");
}
private static void dumpFieldType(
Class<?> clazz, String fieldName
) throws Throwable {
Field field = clazz.getDeclaredField(fieldName);
field.setAccessible(true);
dumpType(field.getGenericType());
dump("\n");
}
private static void dumpType(Type type) {
if (type instanceof GenericArrayType) {
// Type[]
GenericArrayType t = (GenericArrayType)type;
dumpType(t.getGenericComponentType());
dump("[]");
} else if (type instanceof ParameterizedType) {
// TypeA<X>.TypeB<Y, Z> or Map.Entry<String,Object>
ParameterizedType t = (ParameterizedType)type;
Type owner = t.getOwnerType();
if (owner != null) {
dumpType(owner);
dump(".");
}

dumpType(t.getRawType());
Type[] actualTypes = t.getActualTypeArguments();
if (actualTypes != null) {
dump("");
}
} else if (type instanceof TypeVariable) {
// T extends X&Y
TypeVariable t = (TypeVariable)type;
dump(t.getName());
dumpUpperBounds(t.getBounds());
} else if (type instanceof WildcardType) {
// ? extends X&Y super Z
WildcardType t = (WildcardType)type;
dump("?");
dumpUpperBounds(t.getUpperBounds());
dumpTypes(" super " , "|", t.getLowerBounds());
} else if (type instanceof Class) {
// Type
Class t = (Class)type;
dump(t.getSimpleName());
} else if (type == null) {
// We probably messed up.
dump("?[? null ?]?");
} else {
// Eh?
dump("?[" + type.getClass() + "]?");
}
}
private static void dumpUpperBounds(Type[] types) {
if (types.length == 1 && types[0] == Object.class) {
return;
}
dumpTypes(" extends ", "&", types);
}
private static void dumpTypes(String prefix, String sep, Type[] types) {
String s = prefix;
for (Type type : types) {
dump(s);
dumpType(type);
s = sep;
}
}
private static void dump(String str) {
System.out.print(str);
}
}

import java.util.Collection;

public class Example {
private Collection<Integer> field;
}

aviadbd

Posts: 15
Re: Identifying Generics
Posted: Dec 18, 2005 9:10 AM   in response to: tackline
  Click to reply to this thread Reply

However, as you stated yourself, this is only accessible through methods and fields. What happens if I get a POJO?

And it should be much simpler than what you've shown. Seriously, we're not talking about a language for rocket scientists. This is something that the framework Could know about, just chooses not to! It should be simple to access it.

aviadbd

Posts: 15
Re: Identifying Generics
Posted: Dec 19, 2005 9:27 PM   in response to: aviadbd
  Click to reply to this thread Reply

What about a parameter to the compiler? When -no-erasure is specified, it will Not perform erasure. The code will Not be compatible and runnable at JVMs lower than 1.4, and any method in Class which would normally return the parameter types' Real types would return an empty list (or a list of the highest bound, as left currently by erasure).

Would that make more sense?




 XML java.net RSS