Implicit return codes (e.g. return int, -1 means error, 0+ means OK) are equivalent to unchecked exceptions. Explicit return codes, where you must process them or compiler will yell at you are equivalent to checked exceptions. I think, that checked exceptions are a good idea, but they must be improved. E.g. Rust have syntax for almost implicit converting one error to another and return it; checked exceptions could use similar approach, so you can declare another exception in your "throws" cause and compiler'll generate conversion code for any unhandled checked exception.
Anyway for me exceptions are way easier to work with, than return codes.