1

I've read this SO question that talks about the difference between classes and types in java

However, this talks about classes declared with the class keyword rather than the actual class Class in java. In Java, I can have a Class<T> where T is a class/interface/array type (and for primitives, T would be the autoboxed class, but the instance of Class<T> would be associated with the primitive type, such as int.class). Point is, Class is used with more than just class types.

What is the difference between the classClass and interface Type? When would I ever use Type in a java program?

Mario Ishac
  • 5,060
  • 3
  • 21
  • 52
  • Did you bother to **read the documentation**? `Class`: represent *classes* and *interfaces* in a running Java application. `Type`: include *raw types*, *parameterized types*, *array types*, *type variables* and *primitive types*. `Type` is an interface. `Class` is a class *implementing* that interface. It's all right there in the javadoc to `Type`. You even linked the javadoc. Now **read it**. – Andreas Dec 26 '18 at 02:05
  • @Andreas I did read that, but the documentation only provides technical details, whereas the answer below provides practical details as well. – Mario Ishac Dec 26 '18 at 02:07
  • @Andreas In addition, I already explained why "raw types, parameterized types, array types, type variables and primitive types" was unclear: `Class` is possible, but at the same time `Class` "represent[s] classes and interfaces", so why would an `int[]` be possible as a type argument? – Mario Ishac Dec 26 '18 at 02:12
  • What other *practical* details is needed other than objects of type `GenericArrayType`, `ParameterizedType`, `TypeVariable`, and `WildcardType` are not `Class` objects, but are all `Type` objects? – Andreas Dec 26 '18 at 02:12

1 Answers1

3

Type is a superinterface of Class. You won't generally need to use it unless you're doing reflection with generic types.

As an example, we can get the type of a field using Field.getType():

Class<?> c =
    String.class.getField("CASE_INSENSITIVE_ORDER")
        .getType();

The problem is that String.CASE_INSENSITIVE_ORDER is actually a Comparator<String>, and the above code will only get us Comparator.class. This doesn't work for us if we needed to know what the type argument was.

Type and its uses were added in Java 1.5 (along with generics) for this type of situation. We could instead use the method Field.getGenericType():

Type t =
    String.class.getField("CASE_INSENSITIVE_ORDER")
        .getGenericType();

In this case, it would return an instance of ParameterizedType, with Comparator.class as its raw type and String.class in its type arguments:

ParameterizedType pt = (ParameterizedType) t;
pt.getRawType(); // interface java.util.Comparator
pt.getActualTypeArguments(); // [class java.lang.String]

This part of the API isn't very well developed, but there are some better ones built around it, like Guava TypeToken.

Radiodef
  • 37,180
  • 14
  • 90
  • 125
  • I thought the generic type isn't available at runtime due to type erasure. Am I missing something? How would `ParametrizedType#getActualTypeArguments` be able to determine it? – Mario Ishac Dec 26 '18 at 01:39
  • 2
    Some generic type information is stored in the class file. Otherwise the compiler wouldn't be able to work with compiled class files when you do something like import a library. Type erasure affects situations involving object instances: if you have, say an `ArrayList` and an `ArrayList`, there's no way to tell them apart at run-time except to inspect their contents. – Radiodef Dec 26 '18 at 01:55