Again, you're just shoe-horning in your preconceived ideas about how errors should be handled into a different language.
The philosophy of Java and C# especially* is that software should be resilient to errors in production. It doesn't matter if one function for one request with some obscure parameter failed because of a network failure or because of a bug that led to an NPE when that parameter was encountered. What matters is that all other requests that don't have that bug should continue running and not impact users unnecessarily.
So, at some points in my code, I need to handle any possible exception, and decide how to continue from that point. I also need to properly clean up resources and so on regardless of whether I encountered a bug in a subcomponent or an external failure.
Now sure, I probably don't want to be writing "catch (NullPointerException) { ... }", while I may occasionally want "catch (IOException e) {....}" . So there is some difference, but that is where the type system comes in (and the oh-so-hated checked exceptions feature).
* C++'s philosophy is the worse here, of course: programs that have bugs are not valid C++ so they don't even discuss them. Rust's "any bug should crash your program as soon as possible", while still very strange to me, is of course much better.
The philosophy of Java and C# especially* is that software should be resilient to errors in production. It doesn't matter if one function for one request with some obscure parameter failed because of a network failure or because of a bug that led to an NPE when that parameter was encountered. What matters is that all other requests that don't have that bug should continue running and not impact users unnecessarily.
So, at some points in my code, I need to handle any possible exception, and decide how to continue from that point. I also need to properly clean up resources and so on regardless of whether I encountered a bug in a subcomponent or an external failure.
Now sure, I probably don't want to be writing "catch (NullPointerException) { ... }", while I may occasionally want "catch (IOException e) {....}" . So there is some difference, but that is where the type system comes in (and the oh-so-hated checked exceptions feature).
* C++'s philosophy is the worse here, of course: programs that have bugs are not valid C++ so they don't even discuss them. Rust's "any bug should crash your program as soon as possible", while still very strange to me, is of course much better.