Skip to content

Subnet / CIDR Calculator — Java source

Compute IPv4 subnet details from a CIDR block - network, broadcast, host range, netmask, wildcard, host count, IP class, and private-range detection. Split a block into smaller subnets, all in your browser.

This is the Java implementation — the same logic the interactive tool runs, in a shareable, citable form.

// subnet-cidr — Java port: IPv4 subnet/CIDR math (dotted-quad ⇄ uint32-as-long, subnet details, CIDR splitting). Language: Java (17+). Port of src/lib/subnet-cidr.ts — same logic as this dir's python.py / go.go; invalid input yields null rather than throwing.
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

public final class SubnetCidr {

    /** Computed properties of a CIDR block — mirrors SubnetInfo in the TS lib. */
    public record SubnetInfo(String network, String broadcast, String firstHost, String lastHost,
                             long hostCount, int prefix, char ipClass, boolean isPrivate) {}

    /** The TS /^\d+$/ check — rejects signs, hex, whitespace, and the empty string. */
    static boolean allDigits(String s) {
        if (s.isEmpty()) return false;
        for (int i = 0; i < s.length(); i++) if (s.charAt(i) < '0' || s.charAt(i) > '9') return false;
        return true;
    }
    /** "a.b.c.d" → unsigned 32-bit value carried in a long. null for malformed input. */
    static Long ipToInt(String ip) {
        String[] parts = ip.split("\\.", -1);
        if (parts.length != 4) return null;
        long result = 0;
        for (String part : parts) {
            if (!allDigits(part) || part.length() > 3) return null;
            long octet = Long.parseLong(part);
            if (octet > 255) return null;
            result = result * 256 + octet;
        }
        return result & 0xFFFFFFFFL;
    }
    static String intToIp(long n) {
        long v = n & 0xFFFFFFFFL;
        return String.format(Locale.ROOT, "%d.%d.%d.%d", v >> 24, (v >> 16) & 255, (v >> 8) & 255, v & 255);
    }
    static long maskFromPrefix(int p) { return p == 0 ? 0 : (0xFFFFFFFFL << (32 - p)) & 0xFFFFFFFFL; }

    /** "ip/prefix" → full block details; null for an invalid CIDR. */
    public static SubnetInfo subnetDetails(String cidr) {
        int slash = cidr.indexOf('/');
        if (slash < 0) return null;
        String prefixPart = cidr.substring(slash + 1);
        if (prefixPart.indexOf('/') >= 0 || !allDigits(prefixPart) || prefixPart.length() > 2) return null;
        int prefix = Integer.parseInt(prefixPart);
        Long ip = ipToInt(cidr.substring(0, slash));
        if (prefix > 32 || ip == null) return null;

        long mask = maskFromPrefix(prefix), network = ip & mask, broadcast = network | ~mask & 0xFFFFFFFFL;
        // /31 (point-to-point) and /32 (single host) have no host/broadcast split.
        long first = prefix >= 31 ? network : network + 1;
        long last = prefix >= 31 ? broadcast : broadcast - 1;
        long hosts = prefix >= 32 ? 1 : prefix == 31 ? 2 : (1L << (32 - prefix)) - 2;
        long o1 = network >>> 24, o2 = (network >>> 16) & 255;
        char klass = o1 < 128 ? 'A' : o1 < 192 ? 'B' : o1 < 224 ? 'C' : '-'; // D/E → '-'
        boolean priv = o1 == 10 || (o1 == 172 && o2 >= 16 && o2 <= 31) || (o1 == 192 && o2 == 168);
        return new SubnetInfo(intToIp(network), intToIp(broadcast), intToIp(first), intToIp(last),
                hosts, prefix, klass, priv);
    }

    /** Split into 2^(newPrefix-prefix) children; empty list for invalid input or range. */
    public static List<String> splitSubnet(String cidr, int newPrefix) {
        SubnetInfo base = subnetDetails(cidr);
        if (base == null || newPrefix < base.prefix() || newPrefix > 32) return List.of();
        long network = ipToInt(base.network()) & maskFromPrefix(base.prefix());
        long block = 1L << (32 - newPrefix);
        List<String> out = new ArrayList<>(1 << (newPrefix - base.prefix()));
        for (int i = 0; i < (1 << (newPrefix - base.prefix())); i++)
            out.add(intToIp(network + i * block) + "/" + newPrefix);
        return out;
    }

    public static void main(String[] args) {
        SubnetInfo d = subnetDetails("192.168.1.100/24");
        System.out.printf("192.168.1.100/24 net=%s bcast=%s first=%s last=%s hosts=%d class=%s private=%s%n",
                d.network(), d.broadcast(), d.firstHost(), d.lastHost(), d.hostCount(), d.ipClass(), d.isPrivate());
        for (String kid : splitSubnet("192.168.1.0/24", 26)) System.out.println("  split /26 → " + kid);
    }
}

Also available in 13 other languages

Every CosmoDev tool ships its pure logic in TypeScript (web) and Go (CLI), with authored implementations in a dozen-plus languages — the same contract, ported. Compare all languages side by side →