What is the difference between (Id)str and Id.valueOf(str)?

The first is casting. The second is calling a static method on the Id class.

One major advantage of the former is that it is more null safe.

Id idVal1 = (Id)null; // works
Id idVal2 = Id.valueOf(null); // blows up

One advantage of the latter is that you can one-line more of your code by calling instance methods on the cast result. You can get one-liners by adding some parentheses to the casting approach, though some might object on stylistic grounds. I find it a little more visually confusing.

SObjectType t1a = (Id)'001000000000000AAA'.getSObjectType(); // blows up
SObjectType t1b = ((Id)'001000000000000AAA').getSObjectType(); // works
SObjectType t2 = Id.valueOf('001000000000000AAA').getSObjectType(); // works

The above pros/cons are independent of type, so you can carry these conclusions over to String, Decimal, etc.


Casting is not required to convert a String to an Id:

String strVal = '001000000000000AAA';
Id idVal1 = strVal;
Id idVal2 = '001000000000000AAA';

Id is a specialization of String.

This can be shown by:

Id idVal = '001000000000000AAA';
System.assert(idVal instanceof String); // ERROR: Operation instanceof is always true since an instance of Id is always an instance of String

There is a slight difference in heap space used for Id.valueOf vs cast:

Id id1 = '001000000000000';
Id id2 = (Id) id1;
System.debug(Limits.getHeapSize()); // 1047

vs

Id id1 = '001000000000000';
Id id2 = Id.valueOf(id1);
System.debug(Limits.getHeapSize()); // 1051