Memra

The URL class: construct, split, read

◈ 5 cards

The four URL constructors and MalformedURLException, the nine getters (including getPath versus getFile and the -1 port), and choosing among openStream, openConnection and getContent.

Four constructors, one checked exception

java.net.URL is final and immutable: build it, then only ask it questions. Immutability is also why it is thread safe. Four constructors matter:

new URL("http://data.example.org:8080/comp348/week3.html");
new URL("http", "data.example.org", "/comp348/week3.html");
new URL("http", "data.example.org", 8080, "/comp348/week3.html");
new URL(base, "week4.html");

All four throw the checked MalformedURLException. It extends IOException, so a single catch (IOException ex) around a fetch already covers construction and transfer together. The three-argument form leaves the port at -1, meaning use the scheme's default. Its file argument must begin with a slash — omitting it is a classic bug that produces a URL that looks almost right and resolves to the wrong place.

What Java checks, and what it does not

The constructor verifies exactly one thing: that a protocol handler exists for the scheme. Every JVM has http and file; current ones add https, jar and ftp. Anything else — urn:, tel:, an experimental scheme of your own — throws MalformedURLException even though the string is perfectly legal as a URI. Beyond the scheme, Java validates nothing: a space in a hostname, an unencoded query, a host that does not exist and a host you will never be allowed to reach all construct happily. A URL object is a well-formed parse, never a promise that anything is on the other end.

Splitting it apart

Nine read-only getters expose the pieces: getProtocol, getAuthority, getUserInfo, getHost, getPort, getPath, getFile, getQuery, getRef. Three of them have edges worth memorising.

  • getPort() returns -1 when the URL did not state a port. It is not 80. getDefaultPort() supplies the scheme's default (80 for http, 443 for https, 21 for ftp) and returns -1 when the protocol has none.
  • getPath() and getFile() both return the whole path, not a directory and not a filename. The single difference is that getFile() also appends the query string.
  • getQuery() and getRef() return null, not the empty string, when the component is absent.

Three ways to read

openStream() connects and hands back an InputStream of the raw body — no headers, no status, no decoding. It is a shorthand for openConnection().getInputStream(), which tells you exactly what it costs: you gave up the metadata. openConnection() returns a URLConnection that has not connected yet, so you can set timeouts and request headers, and afterwards read the response headers — this is the form A1 #2 needs, and it is Module 4.4. getContent() asks the installed content handlers to turn the body into an object (a String, an Image, or — very often — just an InputStream again); the return type depends on what handlers exist, so production code rarely uses it.

Worked example — a URL splitter

One argument in, seven facts out. Running it on the module's reference:

$ java UrlParts "http://data.example.org:8080/comp348/week3.html?topic=urls#refs"
protocol : http
host     : data.example.org
port     : 8080  (default 80)
path     : /comp348/week3.html
file     : /comp348/week3.html?topic=urls
query    : topic=urls
ref      : refs

The path/file pair is the line to stare at: identical text except for ?topic=urls. Now drop the port from the argument and run it again — port prints -1 while default 80 is unchanged, which is precisely why a server that wants the effective port must ask both getters and not just one.

methodhands youheaders?use it whenopenStream()InputStream of thebodynoyou already knowthe typeopenConnection()URLConnection, notyet connectedyesyou need charset,status or timeoutsgetContent()Object: String,Image orInputStreamnoalmost never; thetype depends onhandlersopenStream = openConnection().getInputStream().
One URL, three doors. openStream is the shortest and throws the metadata away; openConnection is the only one that lets you configure the request before it goes out and read the headers after; getContent depends on which content handlers the JVM happens to have.
NORMAL ~/memra/learn/comp-348/url-class-construct-split-read utf-8 LF