You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
In the same vein as #73, probably GenericType should not implement java.lang.reflect.Type. It's not really a "type" itself—it's a type holder.
I can appreciated that the original conception was to have GenericType be a "type" representing a "type with generics" (sort of like an improved ParameterizedType). But in the larger scheme of things and in hindsight, it's really just one of many duplicates of the Super Type Token pattern. And to put this in context:
The original example in Neil Gafter's famous Super Type Tokens does not implement Type.
Thus ClassMate's GenericType<T> is the only one that implements java.lang.reflect.Type.
The reason I bring this up is that the whole Type system (as you explain so well) is already confusing and awkward; adding one other wrapper that itself pretends to be a Type, in contrast with all the other uses of this pattern, adds even more confusion.
Let me give an illustration of the confusion it can cause. Let's say (following the discussion in #69) that I want to make a general method to convert some "type token" to a Type (so that I can then use Jackson to convert it to a JavaType, etc.). Look closely at this code:
publicstaticTypetypeTokenToType(@NonnullfinalObjecttypeToken) {
//super type token (check first, because ClassMate `GenericType<T>` is also a `Type`)finalTypesuperTypeTokenSuperClass = typeToken.getClass().getGenericSuperclass();
if(superTypeTokenSuperClassinstanceofParameterizedTypeparameterizedType) {
finalType[] actualTypeArguments = parameterizedType.getActualTypeArguments();
if(actualTypeArguments.length == 1) {
returnactualTypeArguments[0];
}
}
//typeif(typeTokeninstanceofType) { //types in general, if they are not super type tokens needing "unwrapping", can be returned directly return (Type)typeToken;
}
thrownewIllegalArgumentException("Type token must be an instance of `Class`, or have a super class providing a single generic type argument.");
}
You see the potential bug if the developer weren't paying attention? In a perfect world, I would first test to see if typeToken is a Type, and just return it, because the type token is already a Type (e.g. a Class<?> or a ParameterizedType). Otherwise I would see if it is a "super type token". And that approach would work with all the other super type tokens—except for ClassMate's GenericType<T>, because GenericType<T> claims it is a Type itself already!
The fix for this example is easy (as shown in the method above): just leave the instanceof Type check for last. But it would be more efficient to test for Type up front. More worrisome, I would have had to have noticed before writing the method (I actually didn't at first) that GenericType<T> implements Type, or I would have wound up with such a bug.
Lots of other bugs may crop up. A developer may write a doFoo(Type type) method, assuming the type has already been "unwrapped", and someone could send it a GenericType<T>, forgetting to unwrap/extract the Type first. I could see this happening all over the place.
At the end of the day this isn't a blocker, and it's certainly not a critical bug. And if you don't agree with me, and you see value in having GenericType<T> implement Type, that's fine. Nevertheless I thought I'd document what I see as an issue so that you can think about it. Cheers!
The text was updated successfully, but these errors were encountered:
In fact, I have hard time understanding why on earth did I make GenericType claim to be java.lang.reflect.Type.
But... alas, removing breaks out all the things within library that rely on "convenience" of common base type.
So I guess that's the answer really; API takes in GenericType as well as variations.
So: I am +1 on getting rid of this, but don't have much time to spend on figuring it out (yes there's bit of theme here :) ).
On plus side I was able to upgrade things so that:
master is now for 1.7.0, with JDK 8 baseline
CI exists, for 1.7 it runs JDK 8, 11 and 17
which should improve project management, make easier to verify goodness of PRs and so on.
In the same vein as #73, probably
GenericType
should not implementjava.lang.reflect.Type
. It's not really a "type" itself—it's a type holder.I can appreciated that the original conception was to have
GenericType
be a "type" representing a "type with generics" (sort of like an improvedParameterizedType
). But in the larger scheme of things and in hindsight, it's really just one of many duplicates of the Super Type Token pattern. And to put this in context:Type
.TypeReference
does not implementType
.ParameterizedTypeReference
does not implementType
.TypeLiteral
does not implementType
.TypeToken
which does not implementType
.TypeToken
does not implementType
.Thus ClassMate's
GenericType<T>
is the only one that implementsjava.lang.reflect.Type
.The reason I bring this up is that the whole
Type
system (as you explain so well) is already confusing and awkward; adding one other wrapper that itself pretends to be aType
, in contrast with all the other uses of this pattern, adds even more confusion.Let me give an illustration of the confusion it can cause. Let's say (following the discussion in #69) that I want to make a general method to convert some "type token" to a
Type
(so that I can then use Jackson to convert it to aJavaType
, etc.). Look closely at this code:You see the potential bug if the developer weren't paying attention? In a perfect world, I would first test to see if
typeToken
is aType
, and just return it, because the type token is already aType
(e.g. aClass<?>
or aParameterizedType
). Otherwise I would see if it is a "super type token". And that approach would work with all the other super type tokens—except for ClassMate'sGenericType<T>
, becauseGenericType<T>
claims it is aType
itself already!The fix for this example is easy (as shown in the method above): just leave the
instanceof Type
check for last. But it would be more efficient to test forType
up front. More worrisome, I would have had to have noticed before writing the method (I actually didn't at first) thatGenericType<T>
implementsType
, or I would have wound up with such a bug.Lots of other bugs may crop up. A developer may write a
doFoo(Type type)
method, assuming the type has already been "unwrapped", and someone could send it aGenericType<T>
, forgetting to unwrap/extract theType
first. I could see this happening all over the place.At the end of the day this isn't a blocker, and it's certainly not a critical bug. And if you don't agree with me, and you see value in having
GenericType<T>
implementType
, that's fine. Nevertheless I thought I'd document what I see as an issue so that you can think about it. Cheers!The text was updated successfully, but these errors were encountered: