Not sure what you mean.
Is it okay to stick exception types that extend RuntimeException in the throws clause of a method?
Java implies certain things and usually you can't undo these things.
For example, all java files act like they have import java.lang.*; at the top even if don't write that. All classes that don't have an extends clause act like they have extends java.lang.Object...
and all methods act like you have throws RuntimeException, Error on them whether you write it or not.
It's legal to write import java.lang.*;, although it would be completely pointless to do this. It is similarly legal to write:
void foo() throws RuntimeException {}
even though this is rather pointless. However, unlike import java.lang.*;, adding some specific runtime exception can be useful in the sense that it documents (It has absolutely no effect whatsoever on what the code does). Some linting tools (I would disagree with the style they are espousing, though!) flag it down as 'useless code' but I wouldn't be so hasty. For example, this method:
public static int parseInt(String in) throws NumberFormatException { .. }
is declaring the NFEx for no programmatic purpose (NFEx is a RuntimeException and all methods trivially can throw those without declaring them), but it is documentary: It highlights that that's an exception you should be taking into consideration when invoking this method / it's the obvious "thing you are looking for" (in the sense that 'soooo... what if I pass a string that does not contain a number to this method, what happens then' - is the obvious question to ask).
So, do it, if that's your intent. Your javadoc should probably have a:
* @throws NumberFormatException If the provided {@code input} is not parseable as an integer number.
or similar, for each explicit RuntimeException you care to state.
Is it okay to wrap SQLException to RuntimeException
Usually: No. The notion of declared checked exceptions is that they are part of your signature. A signature is all about what a method does. It is very much not at all about how it does so.
Thus, the crucial question to ask is: Is the SQLException aspect of it fundamental to what your method does, or fundamental to how it does it?
A trivial example:
saveGame() may simply 'save your game to some persistent storage mechanism'. That's what it does. Perhaps the how involves a database today. Perhaps tomorrow it'll involve the file system. Perhaps next year it's a cloud save system and it involves network access. If the point of this method is merely to force a save, and the method's signature intentionally does not explain how (because you want the future flexibility of changing this, and thus any callers should not assume it's disk, or DB, or network, or anything else), then and only then: SQLException would purely be about the how - and thus it has no place being thrown from the saveGame method. You should wrap it. I highly doubt it's a good idea to wrap that in RuntimeException, I'd invent your own exception (SaveGameException perhaps). Should that exception be checked or unchecked? That depends on too many factors to get into for this answer.
However, something like Files.newOutputStream is different. The what of this method includes the notion that its file based. Fundamentally: It would be nuts if that method doesn't interact with a file system at all and instead opens a database connection. The very name of that method spells it out: It is, after all, in a class named Files - the fact that it interacts with files is a fundamental, unremovable aspect of it. Hence, that method should most absolutely be declared to throws IOException. Similarly, if you have a method called saveToDb, that method should definitely be declared as throws SQLException - and thus, you should not be wrapping your SQLException in anything else.
In rare cases, convenience and intended usage strongly dictates you do not want the exception to be checked. In that case, make an unchecked variant and wrap that. Java itself has UncheckedIOException already - reuse that if it's about IOExceptions. Write the same principle if its about SQLException. However, usually if this comes up you've badly designed your classes - if there's an aspect of your system that is fundamentally tied closely to the notion of interacting with DBs, that entire chain of methods should all be declared to throws SQLException, at which point the need to make that unchecked no longer exists.
Can RuntimeExceptions happen?
Yes, by their nature, RuntimeExceptions can happen at any time. Looking at the greater java ecosystem, RuntimeExceptions cover 3 mostly separate use cases (this isn't getting into what the feature was ever intended for, this is solely about what common java libraries and code actually use them for):
- Programming errors (bugs)
The quintessential example is NullPointerException. There is a bug, the bug should cause some kind of RuntimeException to be thrown. We do not want to make such exceptions checked (because nobody likes a catch block that literally is impossible to trigger unless you actively write bugs to do so - what could you possibly stick in the catch block?), but we DO want to throw something: Breaking off the method and 'unrolling' the entire call stack until some general handler deals with the problem (and gets lots of details about where that problem occurred and why) is precisely what we want. Hence, exception good, checked bad - these should be runtime exceptions and generally are.
Similar examples: Many methods that have rules about what you can pass to them which cannot be expressed in the type system (say, a method that requires you pass a non-negative integer) will throw IllegalArgumentException if you pass a negative number to them, for example. Some methods cannot be called when the object is in a certain state, and will throw IllegalStateException or UnsupportedOperationException, both unchecked (subtypes of RuntimeException) - for example, if you attempt to invoke .add() on an immutable list, you'd get that.
Sometimes checked exceptions can occur but you just don't care, either because you're a lazy programmer who wants to just go home (that'd be quite bad, of course), or because you cannot fathom why a checked exception could occur. For example, an IOException when writing to an OutputStream that is memory based.
IDEs tend to suggest this incredibly stupid 'fix':
try { code(); } catch (IOException e) { e.printStackTrace(); }
I do not know why. Mass delusion? At any rate, all IDEs are very wrong, that is bad code, the correct 'I do not want to think about this checked exception right now' handle block is throw new RuntimeException("uncaught", e); - and smart folks have updated their IDEs to auto-generate this. It's wrapping a checked exception in an unchecked one simply for convenience, or because the coder did not think it could happen.
- For API/programming model reasons
See UncheckedIOException - usually because the code is designed to be used in stream pipelines which doesn't allow checked exceptions. Somewhat rare.
It could be reasonable for the programmer of this library to fail to account for some exotic situation which nevertheless is also reasonable for your specific usage of some library to run into. For example, a third party library could be saving data to whatever OutputStream you provide for it, and that OutputStream might throw a documented unchecked exception for some reason - in which case your library is likely to also throw it. This is rare - you'd presumably know about it, and it comes up only if some library is 'intermediary' - you pass it some object that it, in turn, acts upon, and in that interaction, the runtime exceptions end up getting passed through. Or, the object you pass in doesn't adhere to certain rules. For example, if I hand a comparator that doesn't adhere to the spec (for example, is inconsistent: both a.compareTo(b) and b.compareTo(a) return a negative number - the Comparator spec says you should not do that) to some library, and that library ends up throwing some undocumented unchecked exception for this, I wouldn't blame the library author.
The 'first' case (code bugs) should be documented. For example, Integer.parseInt indeed documents that a NumberFormatException is thrown if you pass a string that doesn't contain something parseable to an int. List's add documents that it might not be supported in which case UnsupportedOperationException will be thrown, etcetera. If your 3rd party routine's docs don't state anything, then it does not apply (or it is badly documented).
The 'second' case (laziness) is hopefully not the case either - that would mean the programmer of it did a bad job.
The third case should also be documented.
That leaves the 4th case, which could happen and won't be documented. You have some control over this, though.
CONCLUSION: Well written libraries will not be throwing undocumented RuntimeExceptions that you didn't expect (i.e. where you aren't the direct cause of it by handing weird objects or things that don't fit clearly documented specs)
Double.parseDouble(), you may receive aNumberFormatExceptionwhich is not declared and nobody asks you to catch it. It's entirely up to you to forecast any potential issue occurring when calling your method (and handling accordingly), or to ignore it and let it flow up at your turn.