Class TypeView

  • Direct Known Subclasses:
    ArrayTypeView, ClassView, ParameterizedTypeView, TypeVariableView, WildcardTypeView

    public abstract class TypeView
    extends Object
    Simplified and more useful handle of java Type.

    This type is a facade over Type and its all five descendants, that offers unified interface to them.

    It allows easy tests for it:

    • Subtyping and supertyping
    • Getting actual erasure

    In addition, this type allows to "resolve" one type in context of another. Resolving means using variable replacements of context type in with current type. See resolve(java.lang.reflect.Type).

    Instances of this type are immutable, as long as provided implementations of Type and its descendant are. Plain java constructs of those are immutable.

    • Method Detail

      • of

        public static TypeView of​(Type type)
        Creates view over provided type.
        Parameters:
        type - construct to wrap
        Returns:
        view wrapping specified type
      • of

        public static <X> ClassView<X> of​(Class<X> clazz)
        Creates view over provided type.

        This is a overload when argument is known to be Class, to return ClassView

        Type Parameters:
        X - actual type represented by this class
        Parameters:
        clazz - construct to wrap
        Returns:
        view wrapping specified type
      • of

        public static <D extends GenericDeclarationTypeVariableView<D> of​(TypeVariable<D> variable)
        Creates view over provided type.

        This is a overload when argument is known to be TypeVariable, to return TypeVariableView

        Type Parameters:
        D - element type that is declaring this variable
        Parameters:
        variable - construct to wrap
        Returns:
        view wrapping specified type
      • ofTypeOf

        public static TypeView ofTypeOf​(Field field)
        Returns view of corrected type for declared field.
        Parameters:
        field - to extract type from
        Returns:
        view of type of declared field
      • ofParameterOf

        public static TypeView ofParameterOf​(Method method,
                                             int number)
        Returns view of n-th formal parameter declared in method.

        This extracts exactly formal parameters of method, not type of type parameter declared by method.

        In following example, ofTypeParameterOf(<m>, 0) returns String, not E.

             public <E> void m(String i, E j)
         

        For extraction of type parameter, see ofTypeParameterOf(java.lang.reflect.Method, int).

        Parameters:
        method - to extract type from
        number - ordinal number for searched formal parameter, counted from 0
        Returns:
        view of type of formal parameter
        Throws:
        IllegalArgumentException - when type parameter number number is not within method formal parameter range
        See Also:
        ofTypeParameterOf(java.lang.reflect.Method, int)
      • unwrap

        public abstract Type unwrap()
        Extracts native type from this view.

        This is inverse operation from of(Type)

        Returns:
        type that this view was for
      • erasure

        public abstract Class<?> erasure()
        Finds exact class that would be erasure of wrapped type.

        This method is implemented according to JSL section 4.6 with following extensions:

        • Erasure of wildcard type is erasure of its leftmost upper bound, or Object if there isn't one

        These extensions are needed, because these types are cannot be used in declaration, but can be obtained by reflections.

        Returns:
        erasure of wrapped type
      • isSubTypeOf

        public abstract boolean isSubTypeOf​(TypeView other)
        Tests if type wrapped in this view is subtype of the provided one.

        This method tries to adhere to the spirit of subtyping: it answers the question: Having reference of type T, can value of type S be always assigned to it?

        Subtyping is precisely defined for types that can be declared in source, but there are more types that can be constructed or extracted via reflections. This method follows JLS section 4.10 for every aspect it declares, but also defines sensible rule for subtyping wildcards: wildcard is a supertype of its lower bounds, i.e. ? super CharStream is supertype of CharStream and

        Parameters:
        other - type to test subtype relation against
        Returns:
        true if this type is subtype of provided argument
      • isSubTypeOf

        public boolean isSubTypeOf​(Type other)
        Tests if type wrapped in this view is subtype of the provided one.

        See isSubTypeOf(org.perfectable.introspection.type.TypeView) for more.

        Parameters:
        other - type to test subtype relation against
        Returns:
        true if this type is subtype of provided argument
      • isProperSubtypeOf

        public boolean isProperSubtypeOf​(TypeView other)
        Tests if type wrapped in this view is subtype of the provided one, but they are not the same type.

        See isSubTypeOf(org.perfectable.introspection.type.TypeView) for more about testing how subtyping is calculated.

        Parameters:
        other - type to test subtype relation against
        Returns:
        true if this type is subtype of provided argument
      • isProperSubtypeOf

        public boolean isProperSubtypeOf​(Type other)
        Tests if type wrapped in this view is subtype of the provided one, but they are not the same type.

        See isSubTypeOf(org.perfectable.introspection.type.TypeView) for more about testing how subtyping is calculated.

        Parameters:
        other - type to test subtype relation against
        Returns:
        true if this type is subtype of provided argument
      • isSuperTypeOf

        public boolean isSuperTypeOf​(TypeView other)
        Tests if type wrapped in this view is supertype of the provided one.

        Type T is supertype of S iff S is subtype of T.

        Parameters:
        other - type to test supertype relation against
        Returns:
        true if this type is supertype of provided argument
      • isSuperTypeOf

        public boolean isSuperTypeOf​(Type other)
        Tests if type wrapped in this view is supertype of the provided one.

        Type T is supertype of S iff S is subtype of T.

        Parameters:
        other - type to test supertype relation against
        Returns:
        true if this type is supertype of provided argument
      • isProperSupertypeOf

        public boolean isProperSupertypeOf​(TypeView other)
        Tests if type wrapped in this view is supertype of the provided one, but they are not the same type.

        Type T is supertype of S iff S is subtype of T.

        Parameters:
        other - type to test supertype relation against
        Returns:
        true if this type is supertype of provided argument
      • isProperSupertypeOf

        public boolean isProperSupertypeOf​(Type other)
        Tests if type wrapped in this view is supertype of the provided one, but they are not the same type.

        Type T is supertype of S iff S is subtype of T.

        Parameters:
        other - type to test supertype relation against
        Returns:
        true if this type is supertype of provided argument
      • isInstance

        public boolean isInstance​(@Nullable
                                  Object element)
        Tests if provided value is instance of wrapped type.

        Because of type erasure, this method only tests if erasure of provided element type is subtype of this type. This might not always be true! For example, for method boolean m(List<? extends Number> t) extracted parameter type is List<? extends Number> but t has runtime type List. If we have view of type List<? extends Serializable>, then isInstance(t) should return true, when in fact it will return false, as runtime class is treated as parameterized class with no substitutions.

        As in plain java, null is subtype of only of null type, which cannot be obtained as a reference, so this will always return false for it.

        See isSubTypeOf(org.perfectable.introspection.type.TypeView) for how subtyping is calculated.

        Parameters:
        element - type to test supertype relation against
        Returns:
        true if this type is supertype of provided argument
      • asParameterized

        public abstract ParameterizedTypeView asParameterized()
                                                       throws IllegalStateException
        Try to cast or convert wrapped type to ParameterizedType.

        This method is useful if you know that underlying type is ParameterizedType, then this is just a casting.

        This can also be done for regular classes, ClassView, as non-generic class can be treated as generic class with zero type parameters. It also works for class-represented arrays that are currently converted to parameterized types.

        Returns:
        this view casted/converted to view for parameterized type
        Throws:
        IllegalStateException - when this view cannot be converted to ParameterizedView.
      • asClass

        public abstract ClassView<?> asClass()
                                      throws IllegalStateException
        Try to cast or convert wrapped type to Class.

        This method is useful if you know that underlying type is Class, then this is just a casting.

        This can also be done for parameterized types with no actual substitutions and array classes represented by ArrayTypeView

        Returns:
        this view casted/converted to view for class
        Throws:
        IllegalStateException - when this view cannot be converted to Class.
      • asArray

        public abstract ArrayTypeView asArray()
                                       throws IllegalStateException
        Try to cast/convert wrapped type to GenericArrayType.

        This method is useful if you know that underlying type is GenericArrayType, then this is just a casting.

        This can also be done for parameterized types with no actual substitutions that represetn array class, and class view that has array class.

        Returns:
        this view casted/converted to view for array
        Throws:
        IllegalStateException - when this view cannot be converted to view of GenericArrayType.
      • resolve

        public TypeView resolve​(Type other)
        Create view that has variable substitutions copied from provided.

        See documentation on resolve(TypeView) for details.

        Parameters:
        other - type to copy substitutions from
        Returns:
        TypeView that uses substitutions from provided type
      • resolve

        public TypeView resolve​(TypeView other)
        Create view that has variable substitutions copied from provided.

        This method creates type that has any variable substituted by substitutions used in other.

        Substitutions are found recursively. They can be only directly found in parameterized types, as arguments, but these parameterized types can be found in components of some containing type. For example, wildcard might use parameterized type as a bound, and this parameterized type might have substitution for specific variable.

        This method can be used to find what the signature of field or method looks like in some specific type. For example: lets say that there's a generic class class Example<T> that declares field protected List<T> elements. It's descendant class, declared class ExtendedExample extends Example<String> inherits field elements. In this case no conventional method will extract actual field type, List<String>:

        But this can be resolved using this method: TypeView.ofTypeOf(Example.class.getDeclaredField("elements")).resolve(ExampleExtension.class) will wrap List<String>, because variable substitution T -> String is used.
        Parameters:
        other - type to copy substitutions from
        Returns:
        TypeView that uses substitutions from provided type
      • visit

        public abstract <T> T visit​(TypeView.Visitor<T> visitor)
        Visitor patter method dispatching method.

        This method calls specific method on provided visitor, depending on actual implementation of this type.

        It will return whatever the method returns.

        Type Parameters:
        T - type returned by visitor method
        Parameters:
        visitor - method target
        Returns:
        same result as visitors method.