Apex Oddities
Apex is, for the most part, a simplified version of Java. However, it has a few quirks and undocumented "features", which this article seeks to explore.
Maps use case-sensitive keys… mostly
Generally, Map keys in Apex are case-sensitive. However, there are a few exceptions to this rule! The global describe maps and subsequent field maps are case-insensitive:
// This one:
Map<String, Schema.SObjectType> gd = Schema.getGlobalDescribe();
// And this one:
Map<String, Schema.SObjectField> fieldMap =
gd.get(sObjectName).getDescribe().fields.getMap();
Cloned SObjects do not respect Decimal precision
Deep-cloning a List trims trailing zeroes from Decimal values therein.
List<MyObject__c> myList = new List<MyObject__c> {
new MyObject(Decimal_Field__c = 1000.0000000)
};
List<MyObject__c> clonedList = myList.deepClone(true, true, true);
System.debug(myList.Decimal_Field__c); // 1000.0000000
System.debug(clonedList.Decimal_Field__c); // 1000.00
System.debug(myList == clonedList); // false (see related issue, below)
Equivalent Decimals are not always considered equal
Two equivalent Decimals with different levels of precision are considered equal. However, two Lists or SObjects containing such decimals are not!
Decimal a = 1000.00;
Decimal b = 1000.0000000;
System.debug(a == b); // true
List<Decimal> listA = new List<Decimal>{a};
List<Decimal> listB = new List<Decimal>{b};
System.debug(listA == listB); // false
MyObject__c objA = new MyObject__c(Decimal_Field__c = a);
MyObject__c objB = new MyObject__c(Decimal_Field__c = b);
System.debug(objA == objB); // false
This can be worked around by creating custom areListsEqual
and areSObjectsEqual
methods, which explicitly check for equality between each pair of items or fields, respectively.
Sets cannot be cast
Lists and Sets behave very differently where generics are concerned. More details can be found in this StackOverflow answer.
// This works fine:
List<MyObject__c> myList;
List<SObject> myUpcastList = (List<SObject>) myList;
// This can't be done!
Set<MyObject__c> mySet;
Set<SObject> myUpcastSet = (Set<SObject>) mySet;
Whitespace DOES matter
Unlike in Java, whitespace can sometimes cause compilation errors.
String body;
// Works
body = new System.HttpRequest()
.getBody();
// Does not work
body = new System
.HttpRequest()
.getBody();
It seems like the inner class name cannot be separated from the containing class; System.HttpRequest
is treated as a single token.
Thanks for reading!
And may you never stumble upon an Apex oddity of your own.
Published 2019/11/20
Last updated 2021/03/09