Newer Version Available
Type Class
Namespace
Usage
Use the forName methods to retrieve the type of an Apex class, which can be a built-in or a user-defined class. You can use these methods to retrieve the type of public and global classes, and not private classes even if the context user has access. Also, use the newInstance method if you want to instantiate a Type that implements an interface and call its methods while letting someone else, such as a subscriber of your package, provide the methods’ implementations.
Example: Instantiating a Type Based on Its Name
The following sample shows how to use the Type methods to instantiate a Type based on its name. A typical application of this scenario is when a package subscriber provides a custom implementation of an interface that is part of an installed package. The package can get the name of the class that implements the interface through a custom setting in the subscriber’s org. The package can then instantiate the type that corresponds to this class name and invoke the methods that the subscriber implemented.
In this sample, Vehicle represents the interface that the VehicleImpl class implements. The last class contains the code sample that invokes the methods implemented in VehicleImpl.
1global interface Vehicle {
2 Long getMaxSpeed();
3 String getType();
4}1global class VehicleImpl implements Vehicle {
2 global Long getMaxSpeed() { return 100; }
3 global String getType() { return 'Sedan'; }
4}1public class CustomerImplInvocationClass {
2
3 public static void invokeCustomImpl() {
4 // Get the class name from a custom setting.
5 // This class implements the Vehicle interface.
6 CustomImplementation__c cs = CustomImplementation__c.getInstance('Vehicle');
7
8 // Get the Type corresponding to the class name
9 Type t = Type.forName(cs.className__c);
10
11 // Instantiate the type.
12 // The type of the instantiated object
13 // is the interface.
14 Vehicle v = (Vehicle)t.newInstance();
15
16 // Call the methods that have a custom implementation
17 System.debug('Max speed: ' + v.getMaxSpeed());
18 System.debug('Vehicle type: ' + v.getType());
19 }
20}Class Property
The class property returns the System.Type of the type it is called on. It is exposed on all Apex built-in types including primitive data types and collections, sObject types, and user-defined classes. This property can be used instead of forName methods.
1System.Type t = Integer.class;You can use this property for the second argument of JSON.deserialize, deserializeStrict, JSONParser.readValueAs, and readValueAsStrict methods to get the type of the object to deserialize. For example:
1Decimal n = (Decimal)JSON.deserialize('100.1', Decimal.class);Type Methods
The following are methods for Type.
equals(typeToCompare)
Signature
public Boolean equals(Object typeToCompare)
Parameters
- typeToCompare
- Type: Object
- The type to compare with the current type.
Return Value
Type: Boolean
Example
1Type t1 = Account.class;
2Type t2 = Type.forName('Account');
3System.assert(t1.equals(t2));forName(fullyQualifiedName)
Signature
public static System.Type forName(String fullyQualifiedName)
Parameters
- fullyQualifiedName
- Type: String
- The fully qualified name of the class to get the type of. The fully qualified class name contains the namespace name, for example, MyNamespace.ClassName.
Return Value
Type: System.Type
Usage
forName(namespace, name)
Signature
public static System.Type forName(String namespace, String name)
Parameters
Return Value
Type: System.Type
Usage
Example
This example shows how to get the type that corresponds to the ClassName class and the MyNamespace namespace.
1Type myType =
2 Type.forName('MyNamespace', 'ClassName');getName()
Signature
public String getName()
Return Value
Type: String
Example
This example shows how to get a Type’s name. It first obtains a Type by calling forName, then calls getName on the Type object.
1Type t =
2 Type.forName('MyClassName');
3
4String typeName =
5 t.getName();
6System.assertEquals('MyClassName',
7 typeName);hashCode()
Signature
public Integer hashCode()
Return Value
Type: Integer
Usage
The returned hash code value corresponds to the type name hash code that String.hashCode returns.
isAssignableFrom(sourceType)
Signature
public Boolean isAssignableFrom(Type sourceType)
Parameters
- sourceType
- The type of the object with which you are checking compatibility.
Return Value
Type: Boolean
- childType.isAssignableFrom(parentType)
- typeA.isAssignableFrom(TypeB) where TypeB is a sibling of TypeA
- typeA.isAssignableFrom(TypeB) where TypeB and TypeA are unrelated
Usage
Unlike the instanceof operator, this method allows you to check type compatibility without having to create a class instance. This method eliminates static compile-time dependencies that instanceof requires.
1//Scenario: Managed package code loading a “plugin” class that implements a managed interface; the implementation done outside of the package
2String pluginNameStr = Config__c.getInstance().PluginApexType__c;
3Type customerProvidedPluginType = Type.forName(pluginNameStr);
4Type pluginInterface = ManagedPluginInterface.class;
5
6// Constructors may have side-effects, including potentially unsafe DML/callouts.
7// We want to make sure the class is really designed to be a valid plugin before we instantiate it
8Boolean validPlugin = pluginInterface.isAssignableFrom(customerProvidedPluginType); // validate that it implements the right interface
9
10if(!validPlugin){
11 throw new SecurityException('Cannot create instance of '+customerProvidedPluginType+'. Does not implement ManagedPluginInterface');
12}else{
13 return Type.newInstance(validPlugin);
14}Example
The following code snippet first defines sibling classes A and B that both implement the Callable interface and an unrelated class C. Then, it explores several type comparisons using isAssignableFrom().
1//Define classes A, B, and C
2
3global class A implements Database.Batchable<String>, Callable {
4 global Iterable<String> start(Database.BatchableContext context) { return null; }
5 global void execute(Database.BatchableContext context, String[] scope) { }
6 global void finish(Database.BatchableContext context) { }
7 global Object call(String action, Map<String, Object> args) { return null; }
8}1global class B implements Callable {
2 global Object call(String action, Map<String, Object> args) { return null; }
3}1global class C { }1Type listOfStrings = Type.forName('List<String>');
2Type listOfIntegers = Type.forName('List<Integer>');
3boolean flagListTypes = listOfIntegers.isAssignableFrom(listOfStrings); // false1//Examples with stringType and idType
2Type stringType = Type.forName('String');
3Type idType = Type.forName('Id');
4boolean isId_assignableFromString = idType.isAssignableFrom(stringType); // true
5//isAssignableFrom respects that String can be assigned to Id without an explicit cast1//Examples with typeA, typeB, and typeC
2Type typeA = Type.forName('A');
3Type typeB = Type.forName('B');
4Type typeC = Type.forName('C');
5boolean isTypeB_ofTypeA = typeB.isAssignableFrom( typeA ); // false - siblings
6boolean isTypeA_ofTypeC = typeA.isAssignableFrom( typeC ); // false - unrelated types
7boolean isTypeA_ofTypeA = typeA.isAssignableFrom(typeA); // true - identity1//Examples with callableType and batchableType
2Type callableType = Type.forName('Callable');
3Type batchableType = Type.forName('Database.Batchable');
4boolean isTypeA_Callable = callableType.isAssignableFrom( typeA ); // true - type A is a child of Callable type
5boolean isTypeA_Batchable = batchableType.isAssignableFrom( typeA ); // true - type A is a child of Batchable type
6boolean isCallableOfTypeA = typeA.isAssignableFrom( callableType ); // false - Callable type is not a child of type A
7boolean isBatchableOfTypeA = typeA.isAssignableFrom( batchableType ); // false - Batchable type is not a child of type AnewInstance()
Signature
public Object newInstance()
Return Value
Type: Object
Usage
Because newInstance returns the generic object type, you should cast the return value to the type of the variable that will hold this value.
This method enables you to instantiate a Type that implements an interface and call its methods while letting someone else provide the methods’ implementation. For example, a package developer can provide an interface that a subscriber who installs the package can implement. The code in the package calls the subscriber's implementation of the interface methods by instantiating the subscriber’s Type.
Example
This example shows how to create an instance of a Type. It first gets a Type by calling forName with the name of a class (ShapeImpl), then calls newInstance on this Type object. The newObj instance is declared with the interface type (Shape) that the ShapeImpl class implements. The return value of the newInstance method is cast to the Shape type.
1Type t =
2 Type.forName('ShapeImpl');
3
4Shape newObj =
5 (Shape)t.newInstance();toString()
Signature
public String toString()
Return Value
Type: String
Usage
This method returns the same value as getName. String.valueOf and System.debug use this method to convert their Type argument into a String.
Example
This example calls toString on the Type corresponding to a list of Integers.
1Type t = List<Integer>.class;
2String s = t.toString();
3System.assertEquals('List<Integer>', s);