Skip to content

Instantly share code, notes, and snippets.

@alan-morey
Last active August 29, 2015 14:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save alan-morey/815e9abae50900d004a0 to your computer and use it in GitHub Desktop.
Save alan-morey/815e9abae50900d004a0 to your computer and use it in GitHub Desktop.
Possible regression in Apex equals() implementation with Salesforce Summer '14
public class PairNumbers {
Integer x,y;
public PairNumbers(Integer a, Integer b) {
x=a;
y=b;
}
public Boolean equals(Object obj) {
if (obj != null && obj instanceof PairNumbers) {
PairNumbers that = (PairNumbers) obj;
return this.x == that.x &&
this.y == that.y;
}
return false;
}
public Integer hashCode() {
return (31 * x) ^ y;
}
}
PairNumbers x = new PairNumbers(1, 2);
Object y = new PairNumbers(3, 4);
// http://www.salesforce.com/us/developer/docs/apexcode/Content/langCon_apex_collections_maps_keys_userdefined.htm
// For any non-null reference value x, x.equals(null) should return false
System.assert(!x.equals(null)); // PASS
System.assert(!y.equals(null)); // FAIL NullPointerException: Argument 2 can not be null. (This passes on Spring '14)
// What appears to be happening in the case of y is, System.equals(ANY, ANY) is being called instead of PairNumbers.equals()
// System.equals(ANY, ANY) throws exception when 2nd argument is null.
30.0 APEX_CODE,FINEST;APEX_PROFILING,ERROR;CALLOUT,ERROR;DB,ERROR;SYSTEM,FINEST;VALIDATION,INFO;VISUALFORCE,ERROR;WORKFLOW,ERROR
Execute Anonymous: public class PairNumbers {
Execute Anonymous: Integer x,y;
Execute Anonymous:
Execute Anonymous: public PairNumbers(Integer a, Integer b) {
Execute Anonymous: x=a;
Execute Anonymous: y=b;
Execute Anonymous: }
Execute Anonymous:
Execute Anonymous: public Boolean equals(Object obj) {
Execute Anonymous: if (obj != null && obj instanceof PairNumbers) {
Execute Anonymous: PairNumbers that = (PairNumbers) obj;
Execute Anonymous: return this.x == that.x &&
Execute Anonymous: this.y == that.y;
Execute Anonymous: }
Execute Anonymous:
Execute Anonymous: return false;
Execute Anonymous: }
Execute Anonymous:
Execute Anonymous: public Integer hashCode() {
Execute Anonymous: return (31 * x) ^ y;
Execute Anonymous: }
Execute Anonymous: }
Execute Anonymous:
Execute Anonymous: PairNumbers x = new PairNumbers(1, 2);
Execute Anonymous: Object y = new PairNumbers(3, 4);
Execute Anonymous:
Execute Anonymous:
Execute Anonymous: // http://www.salesforce.com/us/developer/docs/apexcode/Content/langCon_apex_collections_maps_keys_userdefined.htm
Execute Anonymous: // For any non-null reference value x, x.equals(null) should return false
Execute Anonymous: System.assert(!x.equals(null)); // PASS
Execute Anonymous: System.assert(!y.equals(null)); // FAIL NullPointerException: Argument 2 can not be null. (This passes on Spring '14)
17:01:58.057 (57010236)|EXECUTION_STARTED
17:01:58.057 (57022155)|CODE_UNIT_STARTED|[EXTERNAL]|execute_anonymous_apex
17:01:58.059 (59202389)|VARIABLE_SCOPE_BEGIN|[24]|x|PairNumbers|true|false
17:01:58.059 (59227745)|VARIABLE_SCOPE_BEGIN|[25]|y|Object|false|false
17:01:58.059 (59393403)|HEAP_ALLOCATE|[71]|Bytes:3
17:01:58.059 (59425978)|HEAP_ALLOCATE|[76]|Bytes:152
17:01:58.059 (59448853)|HEAP_ALLOCATE|[272]|Bytes:408
17:01:58.059 (59476830)|HEAP_ALLOCATE|[285]|Bytes:408
17:01:58.059 (59503968)|HEAP_ALLOCATE|[379]|Bytes:48
17:01:58.059 (59534239)|HEAP_ALLOCATE|[131]|Bytes:6
17:01:58.059 (59563548)|HEAP_ALLOCATE|[EXTERNAL]|Bytes:11
17:01:58.059 (59716635)|STATEMENT_EXECUTE|[1]
17:01:58.059 (59722214)|STATEMENT_EXECUTE|[1]
17:01:58.059 (59725540)|STATEMENT_EXECUTE|[24]
17:01:58.059 (59733140)|HEAP_ALLOCATE|[24]|Bytes:6
17:01:58.059 (59756067)|HEAP_ALLOCATE|[24]|Bytes:12
17:01:58.059 (59831669)|HEAP_ALLOCATE|[50]|Bytes:5
17:01:58.059 (59860627)|HEAP_ALLOCATE|[56]|Bytes:5
17:01:58.059 (59873026)|HEAP_ALLOCATE|[63]|Bytes:7
17:01:58.059 (59892523)|SYSTEM_MODE_ENTER|false
17:01:58.059 (59916920)|HEAP_ALLOCATE|[24]|Bytes:5
17:01:58.059 (59947794)|SYSTEM_CONSTRUCTOR_ENTRY|[24]|<init>(Integer,Integer)
17:01:58.059 (59993949)|VARIABLE_SCOPE_BEGIN|[4]|this|PairNumbers|true|false
17:01:58.060 (60049016)|VARIABLE_ASSIGNMENT|[4]|this|{}|0x51cc8885
17:01:58.060 (60056163)|HEAP_ALLOCATE|[2]|Bytes:4
17:01:58.060 (60061574)|VARIABLE_SCOPE_BEGIN|[4]|a|Integer|false|false
17:01:58.060 (60070121)|VARIABLE_ASSIGNMENT|[4]|a|1
17:01:58.060 (60072778)|HEAP_ALLOCATE|[2]|Bytes:4
17:01:58.060 (60076488)|VARIABLE_SCOPE_BEGIN|[4]|b|Integer|false|false
17:01:58.060 (60081235)|VARIABLE_ASSIGNMENT|[4]|b|2
17:01:58.060 (60088004)|STATEMENT_EXECUTE|[1]
17:01:58.060 (60091549)|STATEMENT_EXECUTE|[2]
17:01:58.060 (60095074)|STATEMENT_EXECUTE|[2]
17:01:58.060 (60102902)|STATEMENT_EXECUTE|[4]
17:01:58.060 (60105967)|STATEMENT_EXECUTE|[5]
17:01:58.060 (60110667)|HEAP_ALLOCATE|[5]|Bytes:4
17:01:58.060 (60123650)|VARIABLE_ASSIGNMENT|[5]|this.x|1|0x51cc8885
17:01:58.060 (60127551)|STATEMENT_EXECUTE|[6]
17:01:58.060 (60131015)|HEAP_ALLOCATE|[6]|Bytes:4
17:01:58.060 (60138465)|VARIABLE_ASSIGNMENT|[6]|this.y|2|0x51cc8885
17:01:58.060 (60150604)|SYSTEM_CONSTRUCTOR_EXIT|[24]|<init>(Integer,Integer)
17:01:58.060 (60161192)|SYSTEM_MODE_EXIT|false
17:01:58.060 (60193703)|VARIABLE_ASSIGNMENT|[24]|x|{"x":1,"y":2}|0x51cc8885
17:01:58.060 (60199880)|STATEMENT_EXECUTE|[25]
17:01:58.060 (60206581)|HEAP_ALLOCATE|[25]|Bytes:12
17:01:58.060 (60234531)|SYSTEM_MODE_ENTER|false
17:01:58.060 (60241350)|HEAP_ALLOCATE|[25]|Bytes:5
17:01:58.060 (60253819)|SYSTEM_CONSTRUCTOR_ENTRY|[25]|<init>(Integer,Integer)
17:01:58.060 (60268394)|VARIABLE_SCOPE_BEGIN|[4]|this|PairNumbers|true|false
17:01:58.060 (60288602)|VARIABLE_ASSIGNMENT|[4]|this|{}|0x526b1fe4
17:01:58.060 (60293173)|HEAP_ALLOCATE|[2]|Bytes:4
17:01:58.060 (60296988)|VARIABLE_SCOPE_BEGIN|[4]|a|Integer|false|false
17:01:58.060 (60302743)|VARIABLE_ASSIGNMENT|[4]|a|3
17:01:58.060 (60305322)|HEAP_ALLOCATE|[2]|Bytes:4
17:01:58.060 (60308155)|VARIABLE_SCOPE_BEGIN|[4]|b|Integer|false|false
17:01:58.060 (60312470)|VARIABLE_ASSIGNMENT|[4]|b|4
17:01:58.060 (60317286)|STATEMENT_EXECUTE|[1]
17:01:58.060 (60320490)|STATEMENT_EXECUTE|[2]
17:01:58.060 (60323365)|STATEMENT_EXECUTE|[2]
17:01:58.060 (60329683)|STATEMENT_EXECUTE|[4]
17:01:58.060 (60332584)|STATEMENT_EXECUTE|[5]
17:01:58.060 (60335956)|HEAP_ALLOCATE|[5]|Bytes:4
17:01:58.060 (60344638)|VARIABLE_ASSIGNMENT|[5]|this.x|3|0x526b1fe4
17:01:58.060 (60348422)|STATEMENT_EXECUTE|[6]
17:01:58.060 (60351373)|HEAP_ALLOCATE|[6]|Bytes:4
17:01:58.060 (60358004)|VARIABLE_ASSIGNMENT|[6]|this.y|4|0x526b1fe4
17:01:58.060 (60367521)|SYSTEM_CONSTRUCTOR_EXIT|[25]|<init>(Integer,Integer)
17:01:58.060 (60375181)|SYSTEM_MODE_EXIT|false
17:01:58.060 (60405206)|VARIABLE_ASSIGNMENT|[25]|y|{"x":3,"y":4}
17:01:58.060 (60411584)|STATEMENT_EXECUTE|[30]
17:01:58.060 (60441503)|SYSTEM_MODE_ENTER|false
17:01:58.060 (60451323)|HEAP_ALLOCATE|[30]|Bytes:5
17:01:58.060 (60489332)|SYSTEM_METHOD_ENTRY|[30]|PairNumbers.equals(Object)
17:01:58.060 (60552847)|VARIABLE_SCOPE_BEGIN|[9]|this|PairNumbers|true|false
17:01:58.060 (60577539)|VARIABLE_ASSIGNMENT|[9]|this|{"x":1,"y":2}|0x51cc8885
17:01:58.060 (60587442)|VARIABLE_SCOPE_BEGIN|[9]|obj|Object|false|false
17:01:58.060 (60593625)|VARIABLE_ASSIGNMENT|[9]|obj|null
17:01:58.060 (60608233)|STATEMENT_EXECUTE|[9]
17:01:58.060 (60624558)|STATEMENT_EXECUTE|[10]
17:01:58.060 (60628157)|STATEMENT_EXECUTE|[16]
17:01:58.060 (60638951)|SYSTEM_METHOD_EXIT|[30]|PairNumbers.equals(Object)
17:01:58.060 (60646675)|HEAP_ALLOCATE|[30]|Bytes:5
17:01:58.060 (60654251)|SYSTEM_MODE_EXIT|false
17:01:58.060 (60686270)|SYSTEM_METHOD_ENTRY|[30]|System.assert(Boolean)
17:01:58.060 (60703293)|SYSTEM_METHOD_EXIT|[30]|System.assert(Boolean)
17:01:58.060 (60708477)|STATEMENT_EXECUTE|[31]
17:01:58.060 (60720727)|SYSTEM_METHOD_ENTRY|[31]|PairNumbers.equals(Object)
17:01:58.060 (60732370)|VARIABLE_SCOPE_BEGIN|[9]|this|PairNumbers|true|false
17:01:58.060 (60755138)|VARIABLE_ASSIGNMENT|[9]|this|{"x":3,"y":4}|0x526b1fe4
17:01:58.060 (60759952)|VARIABLE_SCOPE_BEGIN|[9]|obj|Object|false|false
17:01:58.060 (60764840)|VARIABLE_ASSIGNMENT|[9]|obj|null
17:01:58.060 (60770026)|STATEMENT_EXECUTE|[9]
17:01:58.060 (60774611)|STATEMENT_EXECUTE|[10]
17:01:58.060 (60777419)|STATEMENT_EXECUTE|[16]
17:01:58.060 (60784254)|SYSTEM_METHOD_EXIT|[31]|PairNumbers.equals(Object)
17:01:58.060 (60795601)|SYSTEM_METHOD_ENTRY|[31]|System.assert(Boolean)
17:01:58.060 (60806142)|SYSTEM_METHOD_EXIT|[31]|System.assert(Boolean)
17:01:58.060 (60847584)|CODE_UNIT_FINISHED|execute_anonymous_apex
17:01:58.060 (60858268)|EXECUTION_FINISHED
31.0 APEX_CODE,FINEST;APEX_PROFILING,WARN;CALLOUT,ERROR;DB,ERROR;SYSTEM,FINEST;VALIDATION,ERROR;VISUALFORCE,ERROR;WORKFLOW,ERROR
Execute Anonymous: public class PairNumbers {
Execute Anonymous: Integer x,y;
Execute Anonymous:
Execute Anonymous: public PairNumbers(Integer a, Integer b) {
Execute Anonymous: x=a;
Execute Anonymous: y=b;
Execute Anonymous: }
Execute Anonymous:
Execute Anonymous: public Boolean equals(Object obj) {
Execute Anonymous: if (obj != null && obj instanceof PairNumbers) {
Execute Anonymous: PairNumbers that = (PairNumbers) obj;
Execute Anonymous: return this.x == that.x &&
Execute Anonymous: this.y == that.y;
Execute Anonymous: }
Execute Anonymous:
Execute Anonymous: return false;
Execute Anonymous: }
Execute Anonymous:
Execute Anonymous: public Integer hashCode() {
Execute Anonymous: return (31 * x) ^ y;
Execute Anonymous: }
Execute Anonymous: }
Execute Anonymous:
Execute Anonymous: PairNumbers x = new PairNumbers(1, 2);
Execute Anonymous: Object y = new PairNumbers(3, 4);
Execute Anonymous:
Execute Anonymous:
Execute Anonymous: // http://www.salesforce.com/us/developer/docs/apexcode/Content/langCon_apex_collections_maps_keys_userdefined.htm
Execute Anonymous: // For any non-null reference value x, x.equals(null) should return false
Execute Anonymous: System.assert(!x.equals(null)); // PASS
Execute Anonymous: System.assert(!y.equals(null)); // FAIL NullPointerException: Argument 2 can not be null. (This passes on Spring '14)
17:00:19.100 (100236184)|EXECUTION_STARTED
17:00:19.100 (100251630)|CODE_UNIT_STARTED|[EXTERNAL]|execute_anonymous_apex
17:00:19.102 (102527208)|VARIABLE_SCOPE_BEGIN|[24]|x|PairNumbers|true|false
17:00:19.102 (102554958)|VARIABLE_SCOPE_BEGIN|[25]|y|Object|false|false
17:00:19.102 (102709445)|HEAP_ALLOCATE|[71]|Bytes:3
17:00:19.102 (102742989)|HEAP_ALLOCATE|[76]|Bytes:152
17:00:19.102 (102760873)|HEAP_ALLOCATE|[272]|Bytes:408
17:00:19.102 (102784676)|HEAP_ALLOCATE|[285]|Bytes:408
17:00:19.102 (102807166)|HEAP_ALLOCATE|[379]|Bytes:48
17:00:19.102 (102835659)|HEAP_ALLOCATE|[131]|Bytes:6
17:00:19.102 (102866124)|HEAP_ALLOCATE|[EXTERNAL]|Bytes:11
17:00:19.103 (103001667)|STATEMENT_EXECUTE|[1]
17:00:19.103 (103007673)|STATEMENT_EXECUTE|[1]
17:00:19.103 (103010506)|STATEMENT_EXECUTE|[24]
17:00:19.103 (103023046)|HEAP_ALLOCATE|[24]|Bytes:6
17:00:19.103 (103049690)|HEAP_ALLOCATE|[24]|Bytes:12
17:00:19.103 (103117094)|HEAP_ALLOCATE|[50]|Bytes:5
17:00:19.103 (103141939)|HEAP_ALLOCATE|[56]|Bytes:5
17:00:19.103 (103152752)|HEAP_ALLOCATE|[63]|Bytes:7
17:00:19.103 (103179226)|SYSTEM_MODE_ENTER|false
17:00:19.103 (103216108)|HEAP_ALLOCATE|[24]|Bytes:5
17:00:19.103 (103255009)|SYSTEM_CONSTRUCTOR_ENTRY|[24]|<init>(Integer,Integer)
17:00:19.103 (103309703)|VARIABLE_SCOPE_BEGIN|[4]|this|PairNumbers|true|false
17:00:19.108 (108114526)|VARIABLE_ASSIGNMENT|[4]|this|{}|0x4dbcf17a
17:00:19.108 (108126537)|HEAP_ALLOCATE|[2]|Bytes:4
17:00:19.108 (108136795)|VARIABLE_SCOPE_BEGIN|[4]|a|Integer|false|false
17:00:19.111 (111710153)|VARIABLE_ASSIGNMENT|[4]|a|1
17:00:19.111 (111721395)|HEAP_ALLOCATE|[2]|Bytes:4
17:00:19.111 (111731500)|VARIABLE_SCOPE_BEGIN|[4]|b|Integer|false|false
17:00:19.115 (115345594)|VARIABLE_ASSIGNMENT|[4]|b|2
17:00:19.115 (115359795)|STATEMENT_EXECUTE|[1]
17:00:19.115 (115363068)|STATEMENT_EXECUTE|[2]
17:00:19.115 (115368471)|STATEMENT_EXECUTE|[2]
17:00:19.115 (115383734)|HEAP_ALLOCATE|[2]|Bytes:6
17:00:19.115 (115402199)|VARIABLE_SCOPE_BEGIN|[2]|this|system.ApexBaseClass|true|false
17:00:19.119 (119223160)|VARIABLE_ASSIGNMENT|[2]|this|{}|0x4dbcf17a
17:00:19.119 (119254449)|STATEMENT_EXECUTE|[4]
17:00:19.119 (119261264)|STATEMENT_EXECUTE|[5]
17:00:19.119 (119271412)|HEAP_ALLOCATE|[5]|Bytes:4
17:00:19.122 (122860223)|VARIABLE_ASSIGNMENT|[5]|this.x|1|0x4dbcf17a
17:00:19.122 (122874369)|STATEMENT_EXECUTE|[6]
17:00:19.122 (122882960)|HEAP_ALLOCATE|[6]|Bytes:4
17:00:19.126 (126574119)|VARIABLE_ASSIGNMENT|[6]|this.y|2|0x4dbcf17a
17:00:19.126 (126598601)|SYSTEM_CONSTRUCTOR_EXIT|[24]|<init>(Integer,Integer)
17:00:19.126 (126612840)|SYSTEM_MODE_EXIT|false
17:00:19.131 (131664718)|VARIABLE_ASSIGNMENT|[24]|x|{"x":1,"y":2}|0x4dbcf17a
17:00:19.131 (131678335)|STATEMENT_EXECUTE|[25]
17:00:19.131 (131693592)|HEAP_ALLOCATE|[25]|Bytes:12
17:00:19.131 (131731586)|SYSTEM_MODE_ENTER|false
17:00:19.131 (131749410)|HEAP_ALLOCATE|[25]|Bytes:5
17:00:19.131 (131765696)|SYSTEM_CONSTRUCTOR_ENTRY|[25]|<init>(Integer,Integer)
17:00:19.131 (131786186)|VARIABLE_SCOPE_BEGIN|[4]|this|PairNumbers|true|false
17:00:19.136 (136202665)|VARIABLE_ASSIGNMENT|[4]|this|{}|0x69798f07
17:00:19.136 (136214190)|HEAP_ALLOCATE|[2]|Bytes:4
17:00:19.136 (136219956)|VARIABLE_SCOPE_BEGIN|[4]|a|Integer|false|false
17:00:19.140 (140084475)|VARIABLE_ASSIGNMENT|[4]|a|3
17:00:19.140 (140095795)|HEAP_ALLOCATE|[2]|Bytes:4
17:00:19.140 (140101246)|VARIABLE_SCOPE_BEGIN|[4]|b|Integer|false|false
17:00:19.144 (144364530)|VARIABLE_ASSIGNMENT|[4]|b|4
17:00:19.144 (144377539)|STATEMENT_EXECUTE|[1]
17:00:19.144 (144380757)|STATEMENT_EXECUTE|[2]
17:00:19.144 (144385964)|STATEMENT_EXECUTE|[2]
17:00:19.144 (144395238)|VARIABLE_SCOPE_BEGIN|[2]|this|system.ApexBaseClass|true|false
17:00:19.147 (147899832)|VARIABLE_ASSIGNMENT|[2]|this|{}|0x69798f07
17:00:19.147 (147919730)|STATEMENT_EXECUTE|[4]
17:00:19.147 (147923580)|STATEMENT_EXECUTE|[5]
17:00:19.147 (147930110)|HEAP_ALLOCATE|[5]|Bytes:4
17:00:19.151 (151371257)|VARIABLE_ASSIGNMENT|[5]|this.x|3|0x69798f07
17:00:19.151 (151384477)|STATEMENT_EXECUTE|[6]
17:00:19.151 (151392247)|HEAP_ALLOCATE|[6]|Bytes:4
17:00:19.154 (154758488)|VARIABLE_ASSIGNMENT|[6]|this.y|4|0x69798f07
17:00:19.154 (154783514)|SYSTEM_CONSTRUCTOR_EXIT|[25]|<init>(Integer,Integer)
17:00:19.154 (154796713)|SYSTEM_MODE_EXIT|false
17:00:19.159 (159120332)|VARIABLE_ASSIGNMENT|[25]|y|{"x":3,"y":4}
17:00:19.159 (159133778)|STATEMENT_EXECUTE|[30]
17:00:19.159 (159180943)|SYSTEM_MODE_ENTER|false
17:00:19.159 (159201465)|HEAP_ALLOCATE|[30]|Bytes:5
17:00:19.159 (159258118)|SYSTEM_METHOD_ENTRY|[30]|PairNumbers.equals(Object)
17:00:19.159 (159334699)|VARIABLE_SCOPE_BEGIN|[9]|this|PairNumbers|true|false
17:00:19.163 (163756880)|VARIABLE_ASSIGNMENT|[9]|this|{"x":1,"y":2}|0x4dbcf17a
17:00:19.163 (163780961)|VARIABLE_SCOPE_BEGIN|[9]|obj|Object|false|false
17:00:19.167 (167296184)|VARIABLE_ASSIGNMENT|[9]|obj|null
17:00:19.167 (167318543)|STATEMENT_EXECUTE|[9]
17:00:19.167 (167328900)|STATEMENT_EXECUTE|[10]
17:00:19.167 (167334581)|STATEMENT_EXECUTE|[16]
17:00:19.167 (167348540)|SYSTEM_METHOD_EXIT|[30]|PairNumbers.equals(Object)
17:00:19.167 (167357069)|HEAP_ALLOCATE|[30]|Bytes:5
17:00:19.167 (167368307)|SYSTEM_MODE_EXIT|false
17:00:19.167 (167401631)|SYSTEM_METHOD_ENTRY|[30]|System.assert(Boolean)
17:00:19.167 (167421015)|SYSTEM_METHOD_EXIT|[30]|System.assert(Boolean)
17:00:19.167 (167426529)|STATEMENT_EXECUTE|[31]
17:00:19.167 (167443354)|SYSTEM_METHOD_ENTRY|[31]|System.equals(ANY, ANY)
17:00:19.167 (167507473)|EXCEPTION_THROWN|[31]|System.NullPointerException: Argument 2 cannot be null
17:00:19.167 (167635226)|HEAP_ALLOCATE|[31]|Bytes:29
17:00:19.167 (167647078)|SYSTEM_METHOD_EXIT|[31]|System.equals(ANY, ANY)
17:00:19.167 (167757431)|FATAL_ERROR|System.NullPointerException: Argument 2 cannot be null
AnonymousBlock: line 31, column 1
17:00:19.167 (167800268)|CODE_UNIT_FINISHED|execute_anonymous_apex
17:00:19.170 (170013475)|EXECUTION_FINISHED
@alan-morey
Copy link
Author

@alan-morey
Copy link
Author

Appears to be fixed in Winter '15 preview

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment