Signature of MethodHandleInfo.reflectAs is not specific enough
The is a stupid issue with the signature of MethodHandleInfo.reflectAs, j.l.r.Field, Method or Constructor implement two interfaces Member and AnnotatedElement, with the current signature, the code info.reflectAs(Member.class, lookup) works but the code info.reflectAs(AnnotatedElement.class, lookup) doesn't work. Because there is no way to do an 'or' between several bounds of a type variable, I think that the signature of reflectAs should be changed from : public <T extends Member> T reflectAs(Class<T> expected, Lookup lookup); to public <T> T reflectAs(Class<T> expected, Lookup lookup); and the javadoc should be modified to explain that a Member or AnnotatedElement are valid bounds of T. As a side effect, the signature of MethodHandles.reflectAs(Class<T>, MethodHandle) should be updated accordingly. There is a workaround, one can write: (AnnotatedElement)info.reflectAs(Member.class, lookup) but it's at best weird. cheers, Rémi
This is another workaround: public <T extends Member&AnnotatedElement, R> R reflectAs(Class<? super T> expected, Lookup lookup); info.reflectAs(Member.class, lookup);//works info.reflectAs(AnnotatedElement.class, lookup);//works info.reflectAs(Member.class, lookup);//works info.reflectAs(AnnotatedElement.class, lookup);//works info.reflectAs(Object.class, lookup);doesn't work. info.reflectAs(Other.class, lookup);doesn't work. with this does not need to your javadoc and is more type safe. . On Mon, Nov 11, 2013 at 1:59 AM, Remi Forax <forax@univ-mlv.fr> wrote:
The is a stupid issue with the signature of MethodHandleInfo.reflectAs, j.l.r.Field, Method or Constructor implement two interfaces Member and AnnotatedElement, with the current signature, the code info.reflectAs(Member.class, lookup) works but the code info.reflectAs(AnnotatedElement.class, lookup) doesn't work.
Because there is no way to do an 'or' between several bounds of a type variable, I think that the signature of reflectAs should be changed from : public <T extends Member> T reflectAs(Class<T> expected, Lookup lookup); to public <T> T reflectAs(Class<T> expected, Lookup lookup);
and the javadoc should be modified to explain that a Member or AnnotatedElement are valid bounds of T.
As a side effect, the signature of MethodHandles.reflectAs(Class<T>, MethodHandle) should be updated accordingly.
There is a workaround, one can write: (AnnotatedElement)info.reflectAs(Member.class, lookup) but it's at best weird.
cheers, Rémi
_______________________________________________ mlvm-dev mailing list mlvm-dev@openjdk.java.net http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev
On 11/11/2013 02:24 AM, Ali Ebrahimi wrote:
This is another workaround:
public <T extends Member&AnnotatedElement, R> R reflectAs(Class<? super T> expected, Lookup lookup);
info.reflectAs(Member.class, lookup);//works info.reflectAs(AnnotatedElement.class, lookup);//works info.reflectAs(Member.class, lookup);//works info.reflectAs(AnnotatedElement.class, lookup);//works
info.reflectAs(Object.class, lookup);doesn't work. info.reflectAs(Other.class, lookup);doesn't work.
with this does not need to your javadoc and is more type safe. .
Hm... it doesn't look very compile-time type-safe: String s = info.reflectAs(Method.class, lookup); // compiles !!! IMO, I would rather remove the Class parameter altogether. It serves no purpose in the method implementation other than to perform a cast-check on the returned object. The method could simply be: public <T extends Member> T reflect(Lookup lookup); This would not solve the problem Remi put forward. I.e. this would not compile: AnnotatedElement ae = info.reflect(lookup); But with an explicit cast, It compiles: AnnotatedElement ae = (AnnotatedElement) info.reflect(lookup); And compared to what we would have with Class parameter and loosened compile-time type-safety as per Remi's suggestion, it is still shorter: AnnotatedElement ae = info.reflectAs(AnnotatedElement.class, lookup); // this is longer! A type-unsafe variant is possible too (I'm not advocating it): public <T> T reflect(Lookup lookup); Now that Generalized Target-Type Inference <http://openjdk.java.net/projects/jdk8/features#101> is part of Java 8, using Class<T> parameters just as hints to the compiler is not needed in many cases. But if one needs to hint the compiler, explicit type parameters can be used as an escape hatch as always: Object o = info.<Method>reflect(lookup); Regards, Peter
On Mon, Nov 11, 2013 at 1:59 AM, Remi Forax <forax@univ-mlv.fr <mailto:forax@univ-mlv.fr>> wrote:
The is a stupid issue with the signature of MethodHandleInfo.reflectAs, j.l.r.Field, Method or Constructor implement two interfaces Member and AnnotatedElement, with the current signature, the code info.reflectAs(Member.class, lookup) works but the code info.reflectAs(AnnotatedElement.class, lookup) doesn't work.
Because there is no way to do an 'or' between several bounds of a type variable, I think that the signature of reflectAs should be changed from : public <T extends Member> T reflectAs(Class<T> expected, Lookup lookup); to public <T> T reflectAs(Class<T> expected, Lookup lookup);
and the javadoc should be modified to explain that a Member or AnnotatedElement are valid bounds of T.
As a side effect, the signature of MethodHandles.reflectAs(Class<T>, MethodHandle) should be updated accordingly.
There is a workaround, one can write: (AnnotatedElement)info.reflectAs(Member.class, lookup) but it's at best weird.
cheers, Rémi
_______________________________________________ mlvm-dev mailing list mlvm-dev@openjdk.java.net <mailto:mlvm-dev@openjdk.java.net> http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev
_______________________________________________ mlvm-dev mailing list mlvm-dev@openjdk.java.net http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev
On 11/11/2013 08:14 AM, Peter Levart wrote:
The method could simply be:
public <T extends Member> T reflect(Lookup lookup);
But if one needs to hint the compiler, explicit type parameters can be used as an escape hatch as always:
Object o = info.<Method>reflect(lookup);
Well, well, explicit type parameters for method invocation are not needed in above example: Object o = info.reflect(lookup); // compiles One would only need them in situations like: info.<Method>reflect(lookup).invoke(...); Regards, Peter
Hi, I know this is not fully type safe, in fact java generics is not fully type safe. We don't have any better solution with current language support. if we had: <T extends A|B> or <T super R> we had better solutions: public <T extends Member | AnnotatedElement> T reflectAs(Class<T> expected, Lookup lookup) public <T extends Member & AnnotatedElement, R super T> R reflectAs(Class<? super T> expected, Lookup lookup) but we don't have such support in language. But I think there is another solution that require change in j.l.r API Make Member an AnnotatedElement interface Member implements AnnotatedElement { ...} and public <T extends AnnotatedElement> T reflectAs(Class<T> expected, Lookup lookup) On Mon, Nov 11, 2013 at 10:44 AM, Peter Levart <peter.levart@gmail.com>wrote:
On 11/11/2013 02:24 AM, Ali Ebrahimi wrote:
This is another workaround:
public <T extends Member&AnnotatedElement, R> R reflectAs(Class<? super T> expected, Lookup lookup);
info.reflectAs(Member.class, lookup);//works info.reflectAs(AnnotatedElement.class, lookup);//works info.reflectAs(Member.class, lookup);//works info.reflectAs(AnnotatedElement.class, lookup);//works
info.reflectAs(Object.class, lookup);doesn't work. info.reflectAs(Other.class, lookup);doesn't work.
with this does not need to your javadoc and is more type safe. .
Hm... it doesn't look very compile-time type-safe:
String s = info.reflectAs(Method.class, lookup); // compiles !!!
IMO, I would rather remove the Class parameter altogether. It serves no purpose in the method implementation other than to perform a cast-check on the returned object. The method could simply be:
public <T extends Member> T reflect(Lookup lookup);
This would not solve the problem Remi put forward. I.e. this would not compile:
AnnotatedElement ae = info.reflect(lookup);
But with an explicit cast, It compiles:
AnnotatedElement ae = (AnnotatedElement) info.reflect(lookup);
And compared to what we would have with Class parameter and loosened compile-time type-safety as per Remi's suggestion, it is still shorter:
AnnotatedElement ae = info.reflectAs(AnnotatedElement.class, lookup); // this is longer!
A type-unsafe variant is possible too (I'm not advocating it):
public <T> T reflect(Lookup lookup);
Now that Generalized Target-Type Inference<http://openjdk.java.net/projects/jdk8/features#101>is part of Java 8, using Class<T> parameters just as hints to the compiler is not needed in many cases. But if one needs to hint the compiler, explicit type parameters can be used as an escape hatch as always:
Object o = info.<Method>reflect(lookup);
Regards, Peter
On Mon, Nov 11, 2013 at 1:59 AM, Remi Forax <forax@univ-mlv.fr> wrote:
The is a stupid issue with the signature of MethodHandleInfo.reflectAs, j.l.r.Field, Method or Constructor implement two interfaces Member and AnnotatedElement, with the current signature, the code info.reflectAs(Member.class, lookup) works but the code info.reflectAs(AnnotatedElement.class, lookup) doesn't work.
Because there is no way to do an 'or' between several bounds of a type variable, I think that the signature of reflectAs should be changed from : public <T extends Member> T reflectAs(Class<T> expected, Lookup lookup); to public <T> T reflectAs(Class<T> expected, Lookup lookup);
and the javadoc should be modified to explain that a Member or AnnotatedElement are valid bounds of T.
As a side effect, the signature of MethodHandles.reflectAs(Class<T>, MethodHandle) should be updated accordingly.
There is a workaround, one can write: (AnnotatedElement)info.reflectAs(Member.class, lookup) but it's at best weird.
cheers, Rémi
_______________________________________________ mlvm-dev mailing list mlvm-dev@openjdk.java.net http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev
_______________________________________________ mlvm-dev mailing listmlvm-dev@openjdk.java.nethttp://mail.openjdk.java.net/mailman/listinfo/mlvm-dev
Hmm, maybe I don't understand you correctly, but I can see no compelling need to be able to do "info.reflectAs(AnnotatedElement.class, lookup)", as the method's spec clearly says that it will return one of the three types known to implement java.lang.reflect.Member. Those types all implement java.lang.reflect.AnnotatedElement, so you're on the safe side if you apply such a cast to the return value. That said, since we know that Java allows Annotations on all class members, a possibly more consistent API would make j.l.r.Member extend j.l.r.AnnotatedElement! (Now that we have default methods, such a change could even be made without breaking compatibility.) 2013/11/10 Remi Forax <forax@univ-mlv.fr>
The is a stupid issue with the signature of MethodHandleInfo.reflectAs, j.l.r.Field, Method or Constructor implement two interfaces Member and AnnotatedElement, with the current signature, the code info.reflectAs(Member.class, lookup) works but the code info.reflectAs(AnnotatedElement.class, lookup) doesn't work.
Because there is no way to do an 'or' between several bounds of a type variable, I think that the signature of reflectAs should be changed from : public <T extends Member> T reflectAs(Class<T> expected, Lookup lookup); to public <T> T reflectAs(Class<T> expected, Lookup lookup);
and the javadoc should be modified to explain that a Member or AnnotatedElement are valid bounds of T.
As a side effect, the signature of MethodHandles.reflectAs(Class<T>, MethodHandle) should be updated accordingly.
There is a workaround, one can write: (AnnotatedElement)info.reflectAs(Member.class, lookup) but it's at best weird.
cheers, Rémi
Hi, I know, this is too late, but I want to share my suggestion: public <T extends AccessibleObject&AnnotatedElement> T reflectAs(Class<? super T> expected, MethodHandles.Lookup lookup) Member mr = reflectAs(Member.class, MethodHandles.lookup()); AnnotatedElement ae = reflectAs(AnnotatedElement.class, MethodHandles.lookup()); AnnotatedElement am = reflectAs(Member.class, MethodHandles.lookup()); Field fd= reflectAs(Field.class, MethodHandles.lookup()); Constructor cr = reflectAs(Constructor.class, MethodHandles.lookup()); Method md = reflectAs(Method.class, MethodHandles.lookup()); Field fm= reflectAs(Member.class, MethodHandles.lookup()); Constructor cm = reflectAs(Member.class, MethodHandles.lookup()); Method mm = reflectAs(Member.class, MethodHandles.lookup()); Field fa= reflectAs(AnnotatedElement.class, MethodHandles.lookup()); Constructor ca = reflectAs(AnnotatedElement.class, MethodHandles.lookup()); Method ma = reflectAs(AnnotatedElement.class, MethodHandles.lookup()); Member mf= reflectAs(Field.class, MethodHandles.lookup()); Member mc = reflectAs(Constructor.class, MethodHandles.lookup()); Member mrm = reflectAs(Method.class, MethodHandles.lookup()); AnnotatedElement af= reflectAs(Field.class, MethodHandles.lookup()); AnnotatedElement ac = reflectAs(Constructor.class, MethodHandles.lookup()); AnnotatedElement aem = reflectAs(Method.class, MethodHandles.lookup()); Method mdc = reflectAs(Constructor.class, MethodHandles.lookup());//fails Constructor crm = reflectAs(Method.class, MethodHandles.lookup());//fails Constructor cf = reflectAs(Field.class, MethodHandles.lookup());//fails Field fc = reflectAs(Constructor.class, MethodHandles.lookup());//fails AnnotatedElement as = reflectAs(String.class, MethodHandles.lookup());//fails String ss = reflectAs(String.class, MethodHandles.lookup());//fails String sm = reflectAs(Method.class, MethodHandles.lookup());//fails Regards, Ali Ebrahimi On Mon, Nov 11, 2013 at 1:59 AM, Remi Forax <forax@univ-mlv.fr> wrote:
The is a stupid issue with the signature of MethodHandleInfo.reflectAs, j.l.r.Field, Method or Constructor implement two interfaces Member and AnnotatedElement, with the current signature, the code info.reflectAs(Member.class, lookup) works but the code info.reflectAs(AnnotatedElement.class, lookup) doesn't work.
Because there is no way to do an 'or' between several bounds of a type variable, I think that the signature of reflectAs should be changed from : public <T extends Member> T reflectAs(Class<T> expected, Lookup lookup); to public <T> T reflectAs(Class<T> expected, Lookup lookup);
and the javadoc should be modified to explain that a Member or AnnotatedElement are valid bounds of T.
As a side effect, the signature of MethodHandles.reflectAs(Class<T>, MethodHandle) should be updated accordingly.
There is a workaround, one can write: (AnnotatedElement)info.reflectAs(Member.class, lookup) but it's at best weird.
cheers, Rémi
_______________________________________________ mlvm-dev mailing list mlvm-dev@openjdk.java.net http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev
On Feb 25, 2014, at 3:13 AM, Ali Ebrahimi <ali.ebrahimi1781@gmail.com> wrote:
I know, this is too late, but I want to share my suggestion:
public <T extends AccessibleObject&AnnotatedElement> T reflectAs(Class<? super T> expected, MethodHandles.Lookup lookup)
Isn't this the same as public <T extends AccessibleObject> T reflectAs... ? I think we considered AccessibleObject but rejected it as not buying anything significant compared with Member which is an interface. Perhaps public <T extends Member & AnnotatedElement> T reflectAs... with both interfaces, would have been slightly better. As the API is written (and yes it is too late to change) I don't think there are any use cases (at least with ground types) which require an extra cast. Thank you for looking at it. — John
Hi, On Sat, Mar 1, 2014 at 12:16 AM, John Rose <john.r.rose@oracle.com> wrote:
On Feb 25, 2014, at 3:13 AM, Ali Ebrahimi <ali.ebrahimi1781@gmail.com> wrote:
I know, this is too late, but I want to share my suggestion:
public <T extends AccessibleObject&AnnotatedElement> T reflectAs(Class<? super T> expected, MethodHandles.Lookup lookup)
Isn't this the same as
public <T extends AccessibleObject> T reflectAs...
Oh, sorry, this is my bad. I mean this: public <T extends AccessibleObject&Member> T reflectAs(Class<? super T> expected, MethodHandles.Lookup lookup)
I think we considered AccessibleObject but rejected it as not buying anything significant compared with Member which is an interface.
Perhaps
public <T extends Member & AnnotatedElement> T reflectAs...
I considered this case, but unfortunately compiler accepts following test case with this signature: String ss = reflectAs(String.class, MethodHandles.lookup()); //OK!!!!!!! This seams as compiler bug, any way with <T extends AccessibleObject&Member> compiler catches error. Finally, one case that compiler accepts with both signature is: Object mo = reflectAs(Object.class, MethodHandles.lookup()); Maybe I'm wrong for this, Dan Smith can better interpret this. T inferred to Object and T is not within its bound (AccessibleObject&Member). Regards, Ali Ebrahimi
participants (5)
-
Ali Ebrahimi
-
Gernot Neppert
-
John Rose
-
Peter Levart
-
Remi Forax