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.