Class<T>
I have cloned the Maven repository, set it to branch 4.0.x (the default is 3.9.10), ran mvn clean install
, then mvn generate-sources
so I could debug it in Intellij to see how it works. I quickly stumbled upon an interface named Lookup, implemented in the ProtoLookup class that sits in package org.apache.maven.cling.invoker in the maven-cli module in the impl module. So far for nested modules and large codebases.
The ProtoLookup class has one member field that puzzled me:
private final Map<Class<?>, Object> components;
The puzzling thing is the Class<?>
type that is used as key for this map. I never used Class<?>
as type, it is new for me.
Reflection and creating Class<T> object
As I never worked with Class<T>
and as it is no part of SE 11 I had no understanding of its use. So I asked ChatGPT who told me that:
- This class is part of the Java Reflection API
- This API is used to inspect and manipulate classes, fields and methods at runtime
- An instance of
Class<T>
is return type of:- MyClass.class
- someObject.getClass()
- Class.forName(“fully.qualified.ClassName”)
General use
You can do the following things with it:
- dynamically create objects
- check types at runtime
- look up methods, fields and annotations
- register or reference types without instantiating them
Dynamically creating objects
There are two ways to create objects from a Class<T>
object:
clazz.newInstance()
clazz.getDeclaredConstructor().newInstance()
Use in Maven
Maven uses class objects as keys in a registry map that is a member field of the ProtoLookup class. As keys must be unique, such a registry map must have unique object types in it and that is indeed the case here. Like many Maven types ProtoLookup has a public static Builder class inside that is used to create a ProtoLookup object and to add objects to the map, and this is the declaration/initialization of the map within that Builder class:
private final Map<Class<?>, Object> components = new HashMap<>();
The reason why this is a fine way of storing unique objects of different complex types, is that when you would use some other key type, you would have a bigger chance of doing the wrong casting when retrieving the element. Using Class<?> as key means you know by definition what the type of the object is. You can just ask for the “SettingsXmlConfigurationProcessor” key/type or the “CliRequest” key/type. It is all more type safe.