1

I am trying to determine how to convert a string to an sObject and use it in a List, Map, ... For example can I use the acctString as followed:

private Sobject stringToObject;

String objectString = 'Program__c';
SObjectType stringToObject = ((SObject) 
Type.forName(objectString).newInstance()).getSObjectType();

Can I use stringToObject in the example below?

List<stringToObject> actualObjectList = new List<stringToObject>();
Map<Id,stringToObject> actualObjectMap= new Map<Id,stringToObject>();
stringToObject newStringObjectRecord = new stringToObject();

I am passing in different custom object string values to a method and need to be able to use them as stated in the examples above.

1 Answer 1

2

No, you cannot do that in the way you've shown. Collections require you to use types (not variables, not a type variable) that can be resolved at compile-time.

Same deal with variables. The type must be known at compile-time, you cannot use a variable that holds a type as the data type. Apex is a strong, statically-typed language.

You can, however, pass something like 'Map<Id, Project__c>' into Type.forName().

Map<Id, SObject> dynamicMap = (Map<Id, SObject>)Type.forName('Map<Id, ' + objectString + '>').newInstance();

You still need to have the result be a compatible type (known at compile-time) and need to cast the result of newInstance() (to something also known at compile-time). When you're working to make code more generic, we have no way to avoid needing to use the Parent type (SObject in this case) in the generic code.

It is possible to down-cast dynamicMap in a more specialized method though (assuming you only put records of that specific SObject type into the collection). The following can be executed as anonymous apex

public void doWork(Map<Id, SObject> acctMap){
    Map<Id, Account> castMap = (Map<Id, Account>)acctMap;
    system.debug(castMap);
}

Map<Id, SObject> genericMap = (Map<Id, SObject>)Type.forName('Map<Id, Account>').newInstance();

doWork(genericMap);

genericMap.put('001000000000000AAA', (SObject)(new Account(Id = '001000000000000AAA')));
doWork(genericMap);

Note that Sets behave differently (you cannot up-cast or down-cast a Set because of formal Type Theory reasons). You can still create a generic Set<SObject> and add an Account to it, you just can't cast that Set as a Set<Account> or try for(Account acct :genericSObjectSet).

Maps have the same restriction when it comes to the key type. You could not cast a Map<String, SObject> as a Map<Id, SObject>. The key type of a map can never change.

2
  • Ok. So process for a List could look like this? Sorry for formatting. List<SObject> dynamicList = (List<SObject>)Type.forName('List< ' + objectString + '>').newInstance();
    – Phuc
    Commented May 23, 2022 at 13:45
  • @Phuc Yep, that's how you'd do this for a List.
    – Derek F
    Commented May 23, 2022 at 13:49

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .