# Class Classes

Object
Static
Classes

public final class Classes extends Static
Static methods working on `Class` objects. This class defines helper methods for working with reflection. Some functionalities are:

- Add or remove dimension to an array type (`changeArrayDimension`)
- Find the common parent of two or more classes (`findCommonClass`, `findCommonInterfaces`)
- Getting the bounds of a parameterized field or method (`boundOfParameterizedProperty`)
- Getting a short class name (`getShortName`, `getShortClassName`)

Since:
  0.3

- ## Method Summary

  Modifier and Type
  Method
  Description
  `static Class<?>`
  `boundOfParameterizedDeclaration(GenericDeclaration typeOrMethod)`
  Returns a single bound declared in a parameterized class or a parameterized method.
  `static Class<?>`
  `boundOfParameterizedProperty(Field field)`
  Returns the upper bounds of the parameterized type of the given property.
  `static Class<?>`
  `boundOfParameterizedProperty(Method method)`
  If the given method is a getter or a setter for a parameterized property, returns the upper bounds of the parameterized type.
  `static Class<?>`
  `changeArrayDimension(Class<?> element, int change)`
  Changes the array dimension by the given amount.
  `static Class<?>`
  `findCommonClass(Class<?> c1, Class<?> c2)`
  Returns the most specific class which is assignable from the given classes or a parent of those classes.
  `static Class<?>`
  `findCommonClass(Iterable<?> objects)`
  Returns the most specific class which is assignable from the type of all given objects.
  `static Set<Class<?>>`
  `findCommonInterfaces(Class<?> c1, Class<?> c2)`
  Returns the interfaces which are implemented by the two given classes.
  `static Class<?>`
  `findSpecializedClass(Iterable<?> objects)`
  Returns the most specific class of the objects in the given collection.
  `static <T> Class<? super T>[]`
  `getAllInterfaces(Class<T> type)`
  Returns every interfaces implemented, directly or indirectly, by the given class or interface.
  `static <T> Class<? extends T>`
  `getClass(T object)`
  Returns the class of the specified object, or `null` if `object` is null.
  `static <T> Class<? extends T>[]`
  `getLeafInterfaces(Class<?> type, Class<T> baseInterface)`
  Returns the interfaces implemented by the given class and assignable to the given base interface, or an empty array if none.
  `static String`
  `getShortClassName(Object object)`
  Returns the class name of the given object without package name, but including the enclosing class names if any.
  `static String`
  `getShortName(Class<?> classe)`
  Returns the name of the given class without package name, but including the names of enclosing classes if any.
  `static <T> Class<? super T>`
  `getStandardType(Class<T> type)`
  Returns the first type or super-type (including interface) considered "standard" in Apache SIS sense.
  `static boolean`
  `implementSameInterfaces(Class<?> object1, Class<?> object2, Class<?> baseInterface)`
  Returns `true` if the two specified objects implements exactly the same set of interfaces.
  `static boolean`
  `isAssignableToAny(Class<?> type, Class<?>... allowedTypes)`
  Returns `true` if the given type is assignable to one of the given allowed types.
  `static boolean`
  `isParameterizedProperty(Class<?> type)`
  Returns whether the actual type of a property is the parameterized type according SIS.
  `static boolean`
  `isPossibleGetter(Method method)`
  Returns `true` if the given method may possibly be the getter method for a property.
  `static boolean`
  `isPublic(Class<?> type)`
  Returns `true` if the given class is non-null, public and exported.

  ### Methods inherited from class Object

  `clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

- ## Method Details

  - ### changeArrayDimension

    public static Class<?> changeArrayDimension(Class<?> element, int change)
    Changes the array dimension by the given amount. The given class can be a primitive type, a Java object, or an array of the above. If the given `change` is positive, then the array dimension will be increased by that amount. For example, a change of +1 dimension will change an `int` class into `int[]`, and a `String[]` class into `String[][]`. A change of +2 dimensions is like applying two times a change of +1 dimension.

    The change of dimension can also be negative. For example, a change of -1 dimension will change a `String[]` class into a `String`. More specifically:

    - If the given `element` is null, then this method returns `null`.
    - Otherwise if the given `change` is 0, then the given `element` is returned unchanged.
    - Otherwise if the given `change` is negative, then `Class​.getComponentType()` is invoked `abs(change)` times. The result is a `null` value if `abs(change)` is greater than the array dimension.
    - Otherwise if `element` is `Void​.TYPE`, then this method returns `Void​.TYPE` since arrays of `void` do not exist.
    - Otherwise this method returns a class that represents an array of the given class augmented by the given number of dimensions.
    Parameters:
      `element` - the type of elements in the array.
      `change` - the change of dimension, as a negative or positive number.
    Returns:
      the type of an array of the given element type augmented by the given number of dimensions (which may be negative), or `null`.

  - ### boundOfParameterizedProperty

    public static Class<?> boundOfParameterizedProperty(Field field)
    Returns the upper bounds of the parameterized type of the given property. If the property does not have a parameterized type, returns `null`. If the property has more than one parameterized type, then the parameter examined by this method depends on the property type:
    - If `Map`, then this method returns the type of keys in map entries.
    - For all other types, this method expects exactly one parameterized type for avoiding ambiguity. If this is not the case, `null` is returned.
    This method is used for fetching the type of elements in a collection. This information cannot be obtained from a `Class` instance because of the way parameterized types are implemented in Java (by erasure).

    #### Examples

    When invoking this method for a field of the following types:
    - `Map<String,Number>`: returns `String​.class`, the type of keys.
    - `Set<Number>`: returns `Number​.class`.
    - `Set<? extends Number>`: returns `Number​.class` as well, because that collection cannot contain instances of super-classes. `Number` is the upper bound.
    - `Set<? super Number>`: returns `Object​.class`, because that collection is allowed to contain such elements.
    - `Set`: returns `null` because that collection is declared with raw type.
    - `Long`: returns `null` because that type is not parameterized.
    Parameters:
      `field` - the field for which to obtain the parameterized type.
    Returns:
      the upper bound of parameterized type, or `null` if the given field is not of a parameterized type.
    See Also:
      - `isParameterizedProperty(Class)`

  - ### boundOfParameterizedProperty

    public static Class<?> boundOfParameterizedProperty(Method method)
    If the given method is a getter or a setter for a parameterized property, returns the upper bounds of the parameterized type. Otherwise returns `null`. This method provides the same semantic as `boundOfParameterizedProperty(Field)`, but works on a getter or setter method rather than a field. See `boundOfParameterizedProperty(Field)` javadoc for details.

    This method is used for fetching the type of elements in a collection. This information cannot be obtained from a `Class` instance because of the way parameterized types are implemented in Java (by erasure).

    Parameters:
      `method` - the getter or setter method for which to obtain the parameterized type.
    Returns:
      the upper bound of parameterized type, or `null` if the given method is not a getter or setter for a property of a parameterized type.
    See Also:
      - `isParameterizedProperty(Class)`

  - ### boundOfParameterizedDeclaration

    public static Class<?> boundOfParameterizedDeclaration(GenericDeclaration typeOrMethod)
    Returns a single bound declared in a parameterized class or a parameterized method. The `typeOrMethod` argument is usually a `Class` for a collection type. If the given argument is a non-parameterized class, then this method searches for the first parameterized super-class (see example below). If no parameterized declaration is found, then this method returns `null`. If the declaration has more than one parameterized type, then this method applies the same heuristic rule as `boundOfParameterizedProperty(Field)` (see the javadoc of that method for details).

    #### Examples

    When invoking this method with the following `Class` argument values:
    - `List​.class`: returns `Object​.class` because `List` is declared as `List<E>` (implicitly `<E extends Object>`).
    - `Map​.class`: returns `Object​.class` because `Map` is declared as `Map<K,V>` and, as an heuristic rule, we return the key type of map entry.
    - `PrinterStateReasons​.class`: returns `PrinterStateReason​.class` because `PrinterStateReasons` is not parameterized but extends `HashMap<PrinterStateReason,Severity>`.
    - `Long​.class`: returns `null` because that type is not parameterized.
    This method is used as a fallback when `boundOfParameterizedProperty(…)` cannot be used.
    Parameters:
      `typeOrMethod` - the `Class` or `Method` from which to get the bounds of its parameter.
    Returns:
      the upper bound of parameterized class or method, or `null` if this method cannot identify a single parameterized type to return.
    Since:
      1.3
    See Also:
      - `boundOfParameterizedProperty(Field)`
      - `boundOfParameterizedProperty(Method)`

  - ### getClass

    @Workaround(library="JDK", version="1.7") public static <T> Class<? extends T> getClass(T object)
    Returns the class of the specified object, or `null` if `object` is null. This method is also useful for fetching the class of an object known only by its bound type. As of Java 6, the usual pattern:

        Number n = 0;
        Class<? extends Number> c = n.getClass();

    doesn't seem to work if `Number` is replaced by a parameterized type `T`.
    Type Parameters:
      `T` - the type of the given object.
    Parameters:
      `object` - the object for which to get the class, or `null`.
    Returns:
      the class of the given object, or `null` if the given object was null.

  - ### getStandardType

    public static <T> Class<? super T> getStandardType(Class<T> type)
    Returns the first type or super-type (including interface) considered "standard" in Apache SIS sense. This method applies the following heuristic rules, in that order:
    - If the given type implements at least one interface having the `UML` annotation, then the first annotated interface is returned.
    - Otherwise the first public class or parent class is returned.
    Those heuristic rules may be adjusted in any future Apache SIS version.
    Type Parameters:
      `T` - the compile-time type argument.
    Parameters:
      `type` - the type for which to get the standard interface or class. May be `null`.
    Returns:
      a standard interface implemented by `type`, or otherwise the most specific public class. Is `null` if the given `type` argument was null.
    Since:
      1.0

  - ### getAllInterfaces

    public static <T> Class<? super T>[] getAllInterfaces(Class<T> type)
    Returns every interfaces implemented, directly or indirectly, by the given class or interface. This is similar to `Class​.getInterfaces()` except that this method searches recursively in the super-interfaces. For example if the given type is `ArrayList`, then the returned set will contain `List` (which is implemented directly) together with its parent interfaces `Collection` and `Iterable`.

    #### Elements ordering

    All interfaces implemented directly by the given type are first and in the order they are declared in the `implements` or `extends` clause. Parent interfaces are next.
    Type Parameters:
      `T` - the compile-time type of the `Class` argument.
    Parameters:
      `type` - the class or interface for which to get all implemented interfaces.
    Returns:
      all implemented interfaces (not including the given `type` if it was an interface), or an empty array if none.
    See Also:
      - `Class​.getInterfaces()`

  - ### getLeafInterfaces

    public static <T> Class<? extends T>[] getLeafInterfaces(Class<?> type, Class<T> baseInterface)
    Returns the interfaces implemented by the given class and assignable to the given base interface, or an empty array if none. If more than one interface extends the given base, then the most specialized interfaces are returned. For example if the given class implements both the `Set` and `Collection` interfaces, then the returned array contains only the `Set` interface.

    #### Example

    `getLeafInterfaces(ArrayList​.class, Collection​.class)` returns an array of length 1 containing `List​.class`.
    Type Parameters:
      `T` - the type of the `baseInterface` class argument.
    Parameters:
      `type` - a class for which the implemented interfaces are desired, or `null`.
      `baseInterface` - the base type of the interfaces to search.
    Returns:
      the leaf interfaces matching the given criterion, or an empty array if none.

  - ### findSpecializedClass

    public static Class<?> findSpecializedClass(Iterable<?> objects)
    Returns the most specific class of the objects in the given collection. If there is more than one specialized class, returns their most specific common super class.

    This method searches for classes only, not interfaces.

    Parameters:
      `objects` - a collection of objects. May contains duplicated values and null values.
    Returns:
      the most specialized class, or `null` if the given collection does not contain at least one non-null element.

  - ### findCommonClass

    public static Class<?> findCommonClass(Iterable<?> objects)
    Returns the most specific class which is assignable from the type of all given objects. If no element in the given collection has a type assignable from the type of all other elements, then this method searches for a common super class.

    This method searches for classes only, not interfaces.

    Parameters:
      `objects` - a collection of objects. May contains duplicated values and null values.
    Returns:
      the most specific class common to all supplied objects, or `null` if the given collection does not contain at least one non-null element.

  - ### findCommonClass

    public static Class<?> findCommonClass(Class<?> c1, Class<?> c2)
    Returns the most specific class which is assignable from the given classes or a parent of those classes. This method returns either `c1`, `c2` or a common parent of `c1` and `c2`.

    This method considers classes only, not the interfaces.

    Parameters:
      `c1` - the first class, or `null`.
      `c2` - the second class, or `null`.
    Returns:
      the most specific class common to the supplied classes, or `null` if both `c1` and `c2` are null.

  - ### findCommonInterfaces

    public static Set<Class<?>> findCommonInterfaces(Class<?> c1, Class<?> c2)
    Returns the interfaces which are implemented by the two given classes. The returned set does not include the parent interfaces. For example if the two given objects implement the `Collection` interface, then the returned set will contain the `Collection` type but not the `Iterable` type, since it is implied by the collection type.
    Parameters:
      `c1` - the first class.
      `c2` - the second class.
    Returns:
      the interfaces common to both classes, or an empty set if none. Callers can freely modify the returned set.

  - ### implementSameInterfaces

    public static boolean implementSameInterfaces(Class<?> object1, Class<?> object2, Class<?> baseInterface)
    Returns `true` if the two specified objects implements exactly the same set of interfaces. Only interfaces assignable to `baseInterface` are compared. Declaration order does not matter.

    #### Example

    in ISO 19111, different interfaces exist for different coordinate system (CS) geometries (`CartesianCS`, `PolarCS`, etc.). One can check if two implementations have the same geometry with the following code:

        if (implementSameInterfaces(cs1, cs2, CoordinateSystem.class)) {
            // The two Coordinate Systems are of the same kind.
        }

    Parameters:
      `object1` - the first object to check for interfaces.
      `object2` - the second object to check for interfaces.
      `baseInterface` - the parent of all interfaces to check.
    Returns:
      `true` if both objects implement the same set of interfaces, considering only sub-interfaces of `baseInterface`.

  - ### getShortName

    public static String getShortName(Class<?> classe)
    Returns the name of the given class without package name, but including the names of enclosing classes if any. This method is similar to the `Class​.getSimpleName()` method, except that if the given class is an inner class, then the returned value is prefixed with the outer class name. Another difference is that if the given class is local or anonymous, then this method returns the name of the parent class.

    The following table compares the various kind of names for some examples:

    Class name comparisons
    Class | `getName()` | `getSimpleName()` | `getCanonicalName()` | `getShortName()`
    --- | --- | --- | --- | ---
    `String` | `"java.lang.String"` | `"String"` | `"java.lang.String"` | `"String"`
    `double[]` | `"[D"` | `"double[]"` | `"double[]"` | `"double[]"`
    `Point2D.Double` | `"java.awt.geom.Point2D$Double"` | `"Double"` | `"java.awt.geom.Point2D.Double"` | `"Point2D.Double"`
    Anonymous `Comparable` | `"com.mycompany.myclass$1"` | `""` | `null` | `"Object"`

    Parameters:
      `classe` - the object class (may be `null`).
    Returns:
      the simple name with outer class name (if any) of the first non-anonymous class in the hierarchy, or `"<*>"` if the given class is null.
    See Also:
      - `getShortClassName(Object)`
      - `Class​.getSimpleName()`

  - ### getShortClassName

    public static String getShortClassName(Object object)
    Returns the class name of the given object without package name, but including the enclosing class names if any. Invoking this method is equivalent to invoking `getShortName(object​.getClass())` except for `null` value. See `getShortName(Class)` for more information on the class name returned by this method.
    Parameters:
      `object` - the object (may be `null`).
    Returns:
      the simple class name with outer class name (if any) of the first non-anonymous class in the hierarchy, or `"<*>"` if the given object is null.
    See Also:
      - `getShortName(Class)`

  - ### isAssignableToAny

    public static boolean isAssignableToAny(Class<?> type, Class<?>... allowedTypes)
    Returns `true` if the given type is assignable to one of the given allowed types. More specifically, if at least one `allowedTypes[i]` element exists for which `allowedTypes[i].isAssignableFrom(type)` returns `true`, then this method returns `true`.

    Special cases:

    - If `type` is null, then this method returns `false`.
    - If `allowedTypes` is null, then this method returns `true`. This is to be interpreted as "no restriction on the allowed types".
    - Any null element in the `allowedTypes` array are silently ignored.
    Parameters:
      `type` - the type to be tested, or `null`.
      `allowedTypes` - the allowed types.
    Returns:
      `true` if the given type is assignable to one of the allowed types.

  - ### isPossibleGetter

    public static boolean isPossibleGetter(Method method)
    Returns `true` if the given method may possibly be the getter method for a property. This method implements the algorithm used by SIS in order to identify getter methods in metadata interfaces. We do not rely on naming convention (method names starting with "`get`" or "`is`" prefixes) because not every methods follow such convention (e.g. `ConformanceResult​.pass()`).

    The current implementation returns `true` if the given method meets all the following conditions. Note that a `true` value is not a guaranteed that the given method is really a getter. The caller is encouraged to perform additional checks if possible.

    - The method does no expect any argument.
    - The method returns a value (anything except `void`).
    - The method name is not `clone`, `getClass`, `hashCode`, `toString` or `toWKT`.
    - The method is not synthetic.

    Those conditions may be updated in any future SIS version.

    Parameters:
      `method` - the method to inspect.
    Returns:
      `true` if the given method may possibly be a non-deprecated getter method.

  - ### isParameterizedProperty

    public static boolean isParameterizedProperty(Class<?> type)
    Returns whether the actual type of a property is the parameterized type according SIS. The given `type` argument should be the type of a field or the return type of a getter method. If this method returns `true`, then a `boundOfParameterizedProperty(…)` method needs to be invoked in order to get the actual property type.

    The current implementation tests only if the given type is `Optional`. More types may be added in future Apache SIS versions, depending on API evolutions. Note that collections are intentionally not recognized by this method, because they usually need to be handled in a special way by the caller.

    Parameters:
      `type` - the field type or getter method return type to test.
    Returns:
      whether a `boundOfParameterizedProperty(…)` method need to be invoked for getting the actual property type.
    Since:
      1.5
    See Also:
      - `boundOfParameterizedProperty(Field)`
      - `boundOfParameterizedProperty(Method)`

  - ### isPublic

    public static boolean isPublic(Class<?> type)
    Returns `true` if the given class is non-null, public and exported.
    Parameters:
      `type` - the class to test, or `null`.
    Returns:
      whether the given class is part of public API.
    Since:
      1.5