The URL class: construct, split, read
◈ 5 cardsThe 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-1when the URL did not state a port. It is not80.getDefaultPort()supplies the scheme's default (80 for http, 443 for https, 21 for ftp) and returns-1when the protocol has none.getPath()andgetFile()both return the whole path, not a directory and not a filename. The single difference is thatgetFile()also appends the query string.getQuery()andgetRef()returnnull, 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.