How are array and primitive types represented as Class objects, and how do their names encode dimensions?
answer
- one [ per dimension; [I = int[], [[I = int[][]
- reference element: L + binaryName + ; ([Ljava.lang.String;)
- primitive codes: I J D F S B C Z (and V for void)
- isArray() + getComponentType() to inspect
- getName round-trips via forName; primitives don't (use int.class / Integer.TYPE)
basics
~20 sPrimitives and arrays each have their own Class objects. Array getName() uses one leading [ per dimension plus an element code: [I is int[], [[I is int[][], and [Ljava.lang.String; is String[]. Primitives use single letters like I, Z, J, D.
solid answer
~40 sYes, primitives (int.class, boolean.class, void.class) and array types all have real Class objects. The interesting part is getName()'s encoding for arrays: one leading bracket per dimension, then a single-letter code for a primitive element or L<binaryName>; for a reference element. So int[] is [I, int[][] is [[I, and String[] is [Ljava.lang.String;. The primitive codes are I int, J long, D double, F float, S short, B byte, C char, Z boolean, plus V for void. You detect arrays with Class.isArray() and step into the element type with getComponentType(). getSimpleName() and getCanonicalName() instead render the friendly form with [] brackets (String[], java.lang.String[]). This encoding mirrors the JVM type descriptors used throughout the class-file format, which is why getName round-trips through Class.forName.
code
java · 15 linesint.class.getName(); // int
int.class.isPrimitive(); // true
int.class == Integer.TYPE; // true (but != Integer.class)
int[].class.getName(); // [I
int[][].class.getName(); // [[I
String[].class.getName(); // [Ljava.lang.String;
String[].class.getSimpleName(); // String[]
String[].class.isArray(); // true
String[].class.getComponentType(); // class java.lang.String
int[][].class.getComponentType(); // [I (i.e. int[])
// forName round-trips the binary array name:
Class<?> c = Class.forName("[Ljava.lang.String;"); // == String[].classgo deeper
Know that arrays and primitives have Class objects and that array names look odd, like [I for int[].
Decode the array encoding (brackets per dimension plus element code) and use isArray()/getComponentType().
Explain the full descriptor grammar including L...; references, the J/Z primitive codes, the forName round-trip, and that primitives can't be looked up by name.
Connect the encoding to the class-file type-descriptor format used in signatures and the constant pool, and discuss reflective array construction and type-system edge cases.
## Everything is a Class — even primitives and arrays The JVM models *every* type as a `Class` object, including the eight primitives, `void`, and array types. So `int.class`, `void.class`, `int[].class`, and `String[].class` are all valid and distinct `Class` instances. ### Primitive Class objects Each primitive has a singleton `Class`: - `int.class`, `long.class`, `double.class`, `float.class`, `short.class`, `byte.class`, `char.class`, `boolean.class`, and `void.class`. - `Class.isPrimitive()` returns true for them. - Note these differ from their **wrapper** classes: `int.class != Integer.class`. Wrappers expose the primitive via `Integer.TYPE` (== `int.class`). ### Array Class objects and the name encoding This is where `getName()` looks cryptic. The encoding is the JVM **field/type descriptor** grammar: - **One `[` per dimension**, left to right. - Then the **element type code**: - Primitive single letters: `I`=int, `J`=long, `D`=double, `F`=float, `S`=short, `B`=byte, `C`=char, `Z`=boolean. (`J` and `Z` are the surprising ones — chosen because `L` and `B` were already taken.) - Reference type: `L` + binary name + `;` (e.g. `Ljava.lang.String;`). Examples: | Type | getName() | |---|---| | `int[]` | `[I` | | `int[][]` | `[[I` | | `long[]` | `[J` | | `boolean[]` | `[Z` | | `String[]` | `[Ljava.lang.String;` | | `String[][]` | `[[Ljava.lang.String;` | | `Object[]` | `[Ljava.lang.Object;` | `getSimpleName()` and `getCanonicalName()` show the friendly form instead: - `int[].class.getSimpleName()` → `int[]`, `getCanonicalName()` → `int[]`. - `String[].class.getSimpleName()` → `String[]`, `getCanonicalName()` → `java.lang.String[]`. ### Inspecting array types reflectively - `Class.isArray()` — true for array types. - `Class.getComponentType()` — the `Class` of the element type one dimension down (`int[][].class.getComponentType()` is `int[].class`; `int[].class.getComponentType()` is `int.class`); returns `null` for non-arrays. - To create arrays reflectively: `java.lang.reflect.Array.newInstance(componentType, length)`. - To get an array's `Class` from a component type: `arrayInstance.getClass()`, or build via `Array.newInstance(...).getClass()`. ### Why the weird encoding exists The `[`/`L...;`/single-letter scheme is not arbitrary: it is exactly the **type descriptor** notation the class-file format uses everywhere — in field signatures, method signatures (`(I[Ljava/lang/String;)V`), and constant-pool entries. `getName()` exposes that internal form. The pragmatic consequence: `Class.forName("[Ljava.lang.String;")` works and returns `String[].class`, so `getName()` round-trips through `forName`, whereas the friendly `getSimpleName`/`getCanonicalName` forms do not. ### Round-trip caveat `Class.forName` accepts the array descriptor form, but for the *element* you still need the binary name. And note `forName("int")` does **not** work — primitive `Class` objects are obtained via the literal (`int.class`) or `Integer.TYPE`, not by name.
- How do you get the element type of a multidimensional array Class?Call getComponentType() repeatedly; it strips one dimension per call. int[][].class.getComponentType() is int[].class, and calling it again gives int.class.
- How do you obtain the Class for a primitive type, given forName("int") fails?Use the class literal int.class (or void.class), or the wrapper's TYPE field, e.g. Integer.TYPE which equals int.class. These primitive Class objects cannot be looked up by name.
saying these in an interview costs you the question
- Thinking int.class equals Integer.class
- Expecting Class.forName("int") to return int.class
- Reading [Ljava.lang.String; as anything other than String[]
- Assuming getComponentType only drops to a primitive (it drops one dimension at a time)