diff --git a/java/fury-core/src/main/java/org/apache/fury/reflect/TypeRef.java b/java/fury-core/src/main/java/org/apache/fury/reflect/TypeRef.java index b984bb3272..3707f15a6f 100644 --- a/java/fury-core/src/main/java/org/apache/fury/reflect/TypeRef.java +++ b/java/fury-core/src/main/java/org/apache/fury/reflect/TypeRef.java @@ -900,16 +900,30 @@ TypeVariable captureAsTypeVariable(Type[] upperBounds) { for (; i < upperBoundsLength; i++) { combinedUpperBounds[i] = upperBounds[i]; } + int skipCount = 0; rootFor: for (; i < combinedUpperBounds.length; i++) { Type typeParamBound = typeParamBounds[i - upperBoundsLength]; for (Type upperBound : upperBounds) { if (upperBound.equals(typeParamBound)) { + skipCount++; continue rootFor; } } combinedUpperBounds[i] = typeParamBound; } + if (skipCount > 0) { + i = upperBoundsLength; + while (combinedUpperBounds[i] == null) { + if (i == combinedUpperBounds.length - 1) { + break; + } else { + combinedUpperBounds[i] = combinedUpperBounds[i++]; + } + } + combinedUpperBounds = + Arrays.copyOf(combinedUpperBounds, combinedUpperBounds.length - skipCount); + } } return super.captureAsTypeVariable(combinedUpperBounds); } diff --git a/java/fury-core/src/main/java/org/apache/fury/reflect/Types.java b/java/fury-core/src/main/java/org/apache/fury/reflect/Types.java index cbfc7cdb7a..5bedac0e05 100644 --- a/java/fury-core/src/main/java/org/apache/fury/reflect/Types.java +++ b/java/fury-core/src/main/java/org/apache/fury/reflect/Types.java @@ -131,17 +131,23 @@ public int hashCode() { @Override public String toString() { - return "ParameterizedTypeImpl{" - + "actualTypeArguments=" - + Arrays.toString(actualTypeArguments) - + ", rawType=" - + rawType - + ", ownerType=" - + ownerType - + '}'; + StringBuilder builder = new StringBuilder(); + builder.append(typeName(rawType)).append('<'); + int i = 0; + for (Type typeArgument : actualTypeArguments) { + if (i++ != 0) { + builder.append(", "); + } + builder.append(typeName(typeArgument)); + } + return builder.append('>').toString(); } } + static String typeName(Type type) { + return (type instanceof Class) ? ((Class) type).getName() : type.toString(); + } + public static class GenericArrayTypeImpl implements GenericArrayType { private final Type genericComponentType; diff --git a/java/fury-core/src/test/java/org/apache/fury/reflect/TypeRefTest.java b/java/fury-core/src/test/java/org/apache/fury/reflect/TypeRefTest.java index a0cc6cf597..6e7913422f 100644 --- a/java/fury-core/src/test/java/org/apache/fury/reflect/TypeRefTest.java +++ b/java/fury-core/src/test/java/org/apache/fury/reflect/TypeRefTest.java @@ -23,10 +23,17 @@ import java.util.LinkedHashMap; import java.util.Map; +import java.util.TreeMap; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.apache.fury.Fury; +import org.apache.fury.FuryTestBase; +import org.apache.fury.collection.Tuple2; import org.apache.fury.type.TypeUtils; +import org.testng.Assert; import org.testng.annotations.Test; -public class TypeRefTest { +public class TypeRefTest extends FuryTestBase { static class MapObject extends LinkedHashMap {} @Test @@ -39,4 +46,42 @@ public void testGetSubtype() { TypeUtils.mapOf(Map.class, String.class, Object.class), new TypeRef>() {}); } + + @Data + static class MyInternalClass { + public int c = 9; + public T t; + } + + @EqualsAndHashCode(callSuper = true) + static class MyInternalBaseClass extends MyInternalClass { + public int d = 19; + } + + @Data + static class MyClass { + protected Map> fields; + private transient int r = 13; + + public MyClass() { + fields = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + fields.put("test", new MyInternalBaseClass()); + } + } + + @Test + public void testWildcardType() { + Tuple2, TypeRef> mapKeyValueType = + TypeUtils.getMapKeyValueType(new TypeRef>>() {}); + Assert.assertEquals(mapKeyValueType.f0.getType(), String.class); + Assert.assertEquals( + mapKeyValueType.f1.getRawType(), new TypeRef>() {}.getRawType()); + } + + @Test(dataProvider = "enableCodegen") + public void testWildcardTypeSerialization(boolean enableCodegen) { + // see issue https://github.com/apache/incubator-fury/issues/1633 + Fury fury = builder().withCodegen(enableCodegen).build(); + serDeCheck(fury, new MyClass()); + } }