But it does not protect you from the guy who changes his API without changing the signature of the method ("off with these pesky empty lists, let's return null instead").
Thats correct, and ultimately these were the rocks I flailed against for a few months before giving up. There are ways that you can change what something does that don't look semantically different to the compiler. That means you can't capture a semantic signature completely.