Inspecting an address, and every address this host has
◈ 6 cardsThe four getters and what equality actually compares, why immutability makes an InetAddress free to share across threads, the scope predicates, isReachable as a hint, and enumerating a host with NetworkInterface.
Four getters, no setters, and equality by address
Once you hold an InetAddress there are four questions you can ask it. getHostName() returns the hostname, performing a reverse lookup if the object does not already carry one. getCanonicalHostName() is the aggressive form — it goes to DNS even when a name is already sitting in the object, which is how an alias becomes the machine's real name. getHostAddress() returns the textual address, 199.1.32.90 or the colon form. getAddress() returns the raw bytes, four of them or sixteen.
There are no setters, so InetAddress is immutable, and immutable means thread-safe: you can hand one object to a pool of workers and to the thread collecting their results with no lock, no copy and no thought. That is not a nicety — A1's thread pool leans on it directly.
Immutability also explains equality. Two InetAddress objects are equal when their address bytes match; the hostnames are not consulted at all. An object built from "www.example.com" and one built from the literal address that name resolved to are equal. That is usually what you want, and occasionally a surprise: equals answers "same host", never "same name".
Ten predicates, five worth memorising
InetAddress carries ten is…Address() predicates. Five classify scope — loopback, wildcard, link-local, site-local, multicast — and those are the ones in the figure below. The other five subdivide multicast scope (node, link, site, organisation, global) and belong with module 13.
They all answer one question at five grains: how far can this address travel? A loopback address never leaves the host. A link-local one never crosses a router. A site-local one never reaches the public internet. It is the same ladder module 1.4 climbed in dotted-quad form, now available as a method call instead of a string comparison you would have written slightly wrong.
Inet4Address and Inet6Address are the two concrete subclasses, and you almost never name them. To ask which version you hold, take getAddress().length and compare it to 4 or 16. It is faster than instanceof, it reads better, and it works on an address you built from raw bytes.
isReachable is a probe, not a promise
isReachable(int timeout) returns a boolean within the timeout you give it in milliseconds. It attempts an ICMP echo — what ping sends — and falls back to a TCP probe where the JVM lacks the privilege to send ICMP or the network forbids it.
Read a false carefully. It means nothing came back inside the timeout, which is equally what you get from a host that is down, a firewall that drops ICMP as policy, a router in the way, or a timeout that was simply too short. Most serious networks drop ICMP from strangers, so a perfectly healthy server answers false all day. Use it to prefer one address when several resolve; never use it to conclude that a service is unavailable.
One host, many addresses: NetworkInterface
NetworkInterface represents a local interface — a physical card or a virtual one — and is the only way to see all of a machine's addresses. Its factories mirror InetAddress: getByName("eth0"), getByInetAddress(addr) (both return null rather than throwing when there is no match), and networkInterfaces(), which returns a Stream<NetworkInterface> in Java 9 and later. Each interface offers inetAddresses(), and every address you pull out is a normal InetAddress you can bind a socket to.
Worked example — classify one address, then list every address this host owns
public static void main(String[] args) throws IOException {
InetAddress a = InetAddress.getByName("192.168.1.5");
System.out.println(a.getHostAddress()
+ " bytes=" + a.getAddress().length
+ " siteLocal=" + a.isSiteLocalAddress()
+ " loopback=" + a.isLoopbackAddress());
NetworkInterface.networkInterfaces().forEach(ni ->
ni.inetAddresses().forEach(addr ->
System.out.println(ni.getName() + " " + addr.getHostAddress())));
}
The first statement prints 192.168.1.5 bytes=4 siteLocal=true loopback=false without sending a single packet: the argument was a literal, so nothing was resolved, and every predicate is a test on those four bytes.
The second is the part worth running on your own machine. You will see lo carrying 127.0.0.1, at least one real interface carrying a 192.168.x.x or 10.x.x.x address, and quite possibly an fe80:: link-local alongside it. That output is the whole point of the lesson: getLocalHost() picks one of those and calls it "this machine", which is a convenient lie. A host is a set of interfaces, each with a set of addresses, and a server bound to one of them is reachable on exactly that one — which is why the wildcard 0.0.0.0 in the figure exists at all.
source Harold 4e ch4 §Address Types; JDK javadoc java.net.Inet4Address (IPv4 site- and link-local ranges)
source JDK javadoc java.net.NetworkInterface (Java 9 stream forms)