Take the following line of code:
Set<Object> accounts = new Set<Account>();
When I try to execute this in developer console I get an error Illegal assignment from SET to SET
Same error applies if I use a non-SObject type:
Set<Object> strings = new Set<String>(); // Illegal assignment from SET to SET
What has me confused is that we are able to do this with Lists, so the following is valid code:
List<Object> accounts = new List<Account>(); List<Object> strings = new List<String>();
I ran into this problem while trying to write a helper class as follows with an isEmpty() method I could call and pass it any type of collection.
class Util { public static Boolean isEmpty(Set<Object> collection) { return collection.isEmpty(); } public static Boolean isEmpty(List<Object> collection) { return collection.isEmpty(); } public static Boolean isEmpty(Map<Object, Object> collection) { return collection.isEmpty(); } }
By the way, a similar problem occurs for Maps:
Map<Object, Object> accounts = new Map<Id, Account>(); // Illegal assignment from MAP to MAP Map<Object, Object> strings = new Map<String, String>(); // Illegal assignment from MAP to MAP
Anyone know why this is the way it is? Are there some technical reasons? Is there any way around this?
Answer
I couldn’t find any exact documentation, but I suspect that it has to do with SOSL. SOSL returns a List whose elements are Lists themselves of different types. For example:
List<List<SObject>> searchList = peformSosl();
That means that List<Account>
, List<Contact>
, etc. must be subtypes of List<sObject>
in order to be on the SOSL result List.
In the absence of SOSL, I would’ve thought the List scenario would not be possible. I understand that when it comes to the element types on the Lists an Account IS-A Object, but I didn’t think that a List<Account>
IS-A List<Object>
.
Also, it is unsafe to me. Consider the following:
List<Object> accts = new List<Account>();
accts.add(new Contact(LastName='oops'));`
That compiles and there is no casting whatsoever. Run it and you get an error. Contrast that with the following, which catches the error at compile time.
List<Account> accts = new List<Account>();
accts.add(new Contact(LastName='noCompile'));
If you needed a List that could contain multiple types safely you can just instantiate a new List<Object>
.
List<Object> objs = new List<Object>();
objs.add(new Contact(LastName='ok'));
objs.add(new Account(Name='ok2'));
Java, which definitely has a big influence on the design of Apex would not allow the unsafe List creation. The following in Java would not compile and would result in an incompatible type error.
List<Object> objs = new ArrayList<String>();
Sets, and Maps aren’t returned in SOSL, so they don’t have to suffer this fate and their type safety can be enforced at compile time.
Attribution
Source : Link , Question Author : Alan Morey , Answer Author : Peter Knolle