7

I would like to inherit from java.net.URL but I can not because it is final. I get the error:

cannot inherit from final java.net.URL

Why is it final?

Some answers for the questions why String is final state, that the JVM relies on String because it is a very basic data type. I can not see how this would apply to the URL type.

Update

Many answers and comments are giving reasons, why it is good practice to avoid inheritance. Some even think that everything should be final. But the reality is something different. Most classes in the JDK are not final. Being good practice is a reason why one should not inherit from java.net.URL. This might even apply to any class of the JDK. But when something is defined as final one can not inherit. This applies only to some very few classes as String or URL.

So there must be something different between URL and all the other non final classes. The question is: what is this difference, that makes it necessary, that URL is final?

Stating that I should not care about this question, because I should not inherit anyway is no answer to the question.

Community
  • 1
  • 1
ceving
  • 21,900
  • 13
  • 104
  • 178

3 Answers3

7

It's final specifically to prevent you from extending it. However it works internally, it was not designed for inheritance, so the authors prevent you from doing so.

Remember Effective Java:

  • Item 17: "Design and document for inheritance or else prohibit it."
  • Item 16: "Favor composition over inheritance."

So instead of extending URL, create a class which has a URL field.

Matt Ball
  • 354,903
  • 100
  • 647
  • 710
  • 1
    For clarification, String is final for security reasons. I'd imagine URL is final for the same reason. – Wug Sep 12 '12 at 15:55
  • 3
    "Security reasons" paints a pretty wide brush stroke for why `String` is final. Immutability can also help performance and make code simpler to reason about. – Matt Ball Sep 12 '12 at 15:58
  • Yeah, there's a pretty wide range of malicious things you could do with a subclass of string. – Wug Sep 12 '12 at 15:59
  • If I would favor composition over inheritance I would write [Go code](http://golang.org). ;-) – ceving Sep 12 '12 at 16:03
  • @ceving so you know better than Josh Bloch, then? Seriously, read those two Effective Java items if you haven't already. – Matt Ball Sep 12 '12 at 16:15
  • @MattBall: I have asked for a reason. Quoting someone else ideas about good programming style is not a reason. It explains why it might be good idea to be final. But it does not explain why it is so, because many other classes are not. What makes java.net.URL different to java.io.BufferedInputStream? – ceving Sep 12 '12 at 16:23
  • @MattBall "Security reasons" is something that keeps programmers honest. – Tom Hawtin - tackline Sep 12 '12 at 17:21
  • 1
    @ceving Citing Effective Java (depsite its defects) is usually an effective way of presenting a well presented argument that few stack overflowers could approach in quality. – Tom Hawtin - tackline Sep 12 '12 at 17:24
  • @TomHawtin-tackline not sure I follow what you mean about keeping programmers honest. Is it worth elaborating on? – Matt Ball Sep 12 '12 at 17:42
  • 1
    @MattBall In the sense that it blocks off ill-advised shortcuts, such as unnecessarily sharing mutable objects. – Tom Hawtin - tackline Sep 12 '12 at 18:00
2

My guess is that this is for security reason. If a method required URL object as a parameter and you could extend the URL class to do something that the URL class shouldn't do then it could have a security problem.

gigadot
  • 8,879
  • 7
  • 35
  • 51
  • If this would be correct, java.io.BufferedInputStream must also be final, because it is typically used to read the contents of a HTTPS reply. If you suffer from malicious code injection Javas "final" is not able to solve you problem. – ceving Sep 12 '12 at 16:40
  • 1
    @ceving `URL` and `BufferedInputStream` classes are as about as different in nature as it is possible in Java. `URL` is a *value object* and `BufferedInputStream` is *reference object*. A `URL` you can store and trust. For, say, `URL[]` and `File` you need to copy - which is dodgy and poor design. `InputStream`s are *object capabilities*. You don't want to be careful 'who' you let have specific *instances* of them. – Tom Hawtin - tackline Sep 12 '12 at 17:17
  • @ceving I think they want something that they can trust when they design the API. If URL is safe, they can make the codes to internally get the input stream safely. I wound't expect that someone would make an API which takes BufferedInputStream when they know that it can be extended to do something malicious. If no classes were final except string, then all the APIs would take only string as their parameter. For example, File class isn't final, it is unusual to see that the servlet API will take a File object as its arguments. – gigadot Sep 12 '12 at 17:40
  • @gigadot Actually `InputStream` can be overridden to do something malicious - typically grab the `byte[]` passed to the `read` methods and read/modify it when it is being used for something else. `File` is passed through Java SE APIs (too much), and has been the subject of vulnerabilities (TOCTOU/TOC2TOU - Time Of Check to Time Of Use on different values returned by overridden `File.getPath`). – Tom Hawtin - tackline Sep 12 '12 at 18:05
0

AFAIK the URL is the full implementation of the IETF RFC standards so it is not expected you would want to change or extend it.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • 1
    RFCs are not for eternity. If you take a look at RFC 3986, you will find the following tags: Updates: 1738; Obsoletes: 2732, 2396, 1808. – ceving Sep 12 '12 at 16:32
  • `InetAddress` is an example of an RFC thing that has been extended (for IPv6), although you still can't extend it. – Tom Hawtin - tackline Sep 12 '12 at 18:06