< prev index next >
src/java.base/share/classes/java/lang/Class.java
Print this page
@@ -198,11 +198,12 @@
* The string is formatted as a list of type modifiers, if any,
* followed by the kind of type (empty string for primitive types
* and {@code class}, {@code enum}, {@code interface}, or
* <code>@</code>{@code interface}, as appropriate), followed
* by the type's name, followed by an angle-bracketed
- * comma-separated list of the type's type parameters, if any.
+ * comma-separated list of the type's type parameters, if any,
+ * including informative bounds on the type parameters, if any.
*
* A space is used to separate modifiers from one another and to
* separate any modifiers from the kind of type. The modifiers
* occur in canonical order. If there are no type parameters, the
* type parameter list is elided.
@@ -262,11 +263,11 @@
TypeVariable<?>[] typeparms = component.getTypeParameters();
if (typeparms.length > 0) {
StringJoiner sj = new StringJoiner(",", "<", ">");
for(TypeVariable<?> typeparm: typeparms) {
- sj.add(typeparm.getTypeName());
+ sj.add(typeVarBounds(typeparm));
}
sb.append(sj.toString());
}
for (int i = 0; i < arrayDepth; i++)
@@ -274,10 +275,23 @@
return sb.toString();
}
}
+ String typeVarBounds(TypeVariable<?> typeVar) {
+ Type[] bounds = typeVar.getBounds();
+ if (bounds.length == 1 && bounds[0].equals(Object.class)) {
+ return typeVar.getName();
+ } else {
+ StringJoiner sj = new StringJoiner(" & ");
+ for (Type bound : bounds) {
+ sj.add(bound.getTypeName());
+ }
+ return typeVar.getName() + " extends " + sj.toString();
+ }
+ }
+
/**
* Returns the {@code Class} object associated with the class or
* interface with the given string name. Invoking this method is
* equivalent to:
*
< prev index next >