A Java long is a 64-bit whole-number type that stores large counts and timestamps safely, with a fixed range and predictable overflow behavior.
You’ve seen it in code: long for file sizes, user IDs, time in milliseconds, and counters that can run for months. If you’re new to Java, the name can sound odd. “Long” is not a string length. It’s not a long-form object. It’s just Java’s built-in type for bigger whole numbers.
This article clears up what long really means, when you should use it, what trips people up (overflow, literals, casting), and how to write long-friendly code that won’t bite you later.
What Is A Long Java? In Plain Terms
In Java, long is a primitive type for signed whole numbers. “Signed” means it can store negative and positive values. “Primitive” means it’s a raw value, not an object wrapper.
Java gives you several integer types: byte, short, int, and long. The bigger the type, the more values it can represent. long is the widest built-in integer type you’ll use in everyday Java code.
What “64-bit signed” means
A long uses 64 bits of storage. One bit is used for the sign, so half the patterns represent negatives and half represent non-negatives. Java uses two’s-complement representation, which is the standard way modern CPUs represent signed integers.
The exact range is:
- Minimum:
-9,223,372,036,854,775,808(also written asLong.MIN_VALUE) - Maximum:
9,223,372,036,854,775,807(also written asLong.MAX_VALUE)
That range is huge. It covers timestamps in milliseconds for centuries, counters for large-scale systems, and numeric IDs that would overflow an int.
Long In Java Type Rules And Real Limits
long is still an integer type. It does not store decimals. If you need fractional values, you’ll use double, float, or BigDecimal based on the job.
Primitive long vs. Long object
Java also has Long (capital L), the wrapper class. You’ll see it in collections like List, or when a value can be missing and you want null.
long: primitive, cannot benull, fast and compactLong: object, can benull, works with generics and APIs that require objects
Autoboxing lets Java convert between them automatically in many places, but it can still surprise you with null values or extra allocations in tight loops.
Default values in fields
If a long is a field in a class, Java initializes it to 0. If it’s a local variable inside a method, you must assign a value before reading it.
Where long shows up in real code
When a value can climb past about 2.1 billion (the max int), long is the safe pick. A lot of Java APIs already use long for you.
Time and dates
Many time values are stored as a long, like “milliseconds since epoch.” Even when you use java.time types, the underlying conversions often depend on long-sized counts.
File sizes and byte counts
File sizes can exceed 2GB easily. Java’s file APIs use long for lengths and offsets so you can handle big files without overflow.
Database IDs and counters
Auto-increment primary keys often map cleanly to a long in Java. Event counters, request totals, and analytics metrics also grow large over time.
Literals: the “L” suffix you must know
One of the most common beginner mistakes is writing a number that looks fine, then getting a compiler error or a silent overflow.
In Java, an integer literal like 123 is an int by default. If the literal doesn’t fit in an int, the compiler complains unless you mark it as a long.
// Good: long literal
long n = 3000000000L;
// Won't compile: integer number too large
// long n = 3000000000;
Use uppercase L. Lowercase l is legal, yet it can look like the number 1 in some fonts and cause sloppy reviews.
Overflow: what happens when long runs out
long has a fixed maximum. When you go past it, Java does not raise an error by default. It wraps around using two’s-complement arithmetic.
long x = Long.MAX_VALUE;
long y = x + 1; // wraps to Long.MIN_VALUE
This wrap-around can break totals, billing logic, rate limits, or timestamp math if you never thought about the upper bound. When you add, subtract, or multiply values that may be near the limit, use checked methods like Math.addExact, Math.subtractExact, and Math.multiplyExact. They throw an exception on overflow, which is often better than silently corrupt data.
Integer math: why one long can change the whole expression
Java promotes smaller integer types during arithmetic. If you multiply two int values, the multiplication happens in int, even if you assign the result to a long.
int a = 50_000;
int b = 50_000;
long bad = a * b; // overflow happens in int first
long good = (long) a * b; // multiplication happens in long
If you’re doing size math, time conversions, or big counters, promote early so the calculation runs in long from the start.
Parsing and formatting long safely
User input, CSV files, and JSON payloads often arrive as text. Use Long.parseLong when you need a primitive long, and Long.valueOf when you want a Long object.
long userId = Long.parseLong("9223372036854775807");
String s = Long.toString(userId);
Parsing throws NumberFormatException when the text is not a valid long. If you’re reading external input, treat parsing as a failure-prone step and handle it where it makes sense (validation layer, import pipeline, request handler).
When long is the wrong tool
long shines for whole-number counts. It’s not a universal replacement for all numeric needs.
Money and decimal values
A long can represent money safely if you store the smallest unit (like cents) and keep your operations in integers. If your domain needs fractional precision beyond fixed units, prefer BigDecimal.
Numbers larger than 64 bits
If you need integers beyond the long range (cryptography, huge combinatorics, rare scientific workloads), use BigInteger.
Values that can be missing
If “no value” is a real state, you can’t represent it with a primitive. Use Long (or a dedicated type) and handle null carefully, or use OptionalLong when it fits your style and API boundaries.
For the official definition of primitive types and their fixed sizes, the Java language specification is the reference. See Java Language Specification: Types, Values, and Variables.
Common long tasks you’ll write again and again
Once you get comfortable with long, a few patterns keep showing up.
Time conversions
Time code often converts seconds to milliseconds or minutes to seconds. Do the math in long so large values don’t overflow.
long seconds = 86_400L; // one day
long millis = seconds * 1_000L; // 86,400,000
Byte math and file sizes
When you compute buffer sizes, offsets, or transfer totals, keep units clear and store results in long. A tiny mix-up between KB and KiB can still hurt, so name variables by unit: bytes, kib, mb.
Stable IDs
If you generate IDs as numbers, long gives you room to grow. Still, don’t treat numeric IDs as “safe to do math on.” An ID is usually an opaque label, not a quantity.
Long quick reference: range, syntax, and pitfalls
This table pulls the core facts into one place so you can sanity-check code quickly.
| What you need | Use this | What to watch for |
|---|---|---|
| Type name | long (primitive) |
Not the same as Long (object) |
| Bit width | 64-bit signed | Fixed size across platforms |
| Min and max | Long.MIN_VALUE to Long.MAX_VALUE |
Wrap-around on overflow by default |
| Long literal | 123L |
Large literals need L to compile |
| Checked arithmetic | Math.addExact, Math.multiplyExact |
Throws on overflow; handle the exception |
| Parsing text | Long.parseLong(text) |
Throws NumberFormatException |
| Collections | List |
Autoboxing can create objects and allow null |
| Shift operations | <<, >>, >>> |
Know sign extension vs zero-fill |
| Common uses | Timestamps, byte counts, IDs, counters | Promote early in expressions to avoid int overflow |
Long vs int: picking the right size without overthinking it
A lot of code can use int just fine. In-memory arrays, small loop indexes, short-lived counts, and many business values fit easily inside 32 bits.
Use long when the domain can grow past 2,147,483,647, or when an API already gives you long. File sizes, millisecond timestamps, and database IDs are common reasons.
If you’re unsure, ask one question: “Can this number ever exceed two billion?” If the honest answer is “yes,” pick long. If the answer is “no,” int is fine and may be a little lighter in memory-heavy structures.
Comparisons and sorting: avoid subtle bugs
Comparing two long values is straightforward: <, >, ==, and friends work as expected for primitives.
When you sort long values or build comparators, use Long.compare(a, b) rather than subtracting. Subtraction can overflow and flip the ordering.
// Good comparator for longs
int c = Long.compare(a, b);
// Risky: can overflow if values are far apart
// int c = (int) (a - b);
Bit operations: long as 64 raw bits
Sometimes you use a long not as a number, but as 64 bits you can pack data into. Flags, hashes, and bitmasks are common.
<<shifts left, filling with zeros on the right>>shifts right, keeping the sign bit (sign extension)>>>shifts right, filling with zeros (zero-fill)
When you store flags, keep a comment or named constants so the bit positions don’t become a guessing game later.
Data storage and APIs: JSON, databases, and external systems
When a long crosses boundaries, you want to think about how other systems represent it.
JSON number limits
Some JSON parsers in other languages store numbers as floating-point values, which can’t represent every 64-bit integer exactly. If you send very large IDs to browsers or JavaScript services, you may need to serialize IDs as strings, or use a typed protocol that preserves integers.
SQL types
A Java long usually maps to a 64-bit integer column, like BIGINT in many databases. Confirm your schema and ORM mapping so the range matches on both sides.
Nullability
If a column can be null, map it to Long, not long. A primitive can’t represent a missing value, and you don’t want “0” to silently stand in for “unknown.”
Practical checks before you ship long-heavy code
These are the spots where long-related bugs tend to hide.
| Check | Why it matters | What to do |
|---|---|---|
| Big literals compile cleanly | Large integer literals default to int |
Add L suffix to long literals |
| Arithmetic runs in long | int math can overflow before assignment |
Cast early: (long)a * b |
| Sorting uses safe compare | Subtracting can overflow and break ordering | Use Long.compare |
| Overflow is handled where needed | Wrap-around can corrupt totals | Use Math.addExact for risky ranges |
| APIs keep full precision | Other systems may not store 64-bit integers exactly | Send large IDs as strings when required |
| Null values are represented cleanly | 0 can mask “missing” state |
Use Long for nullable fields |
| Units are clear in names | Time and size bugs often come from unit mix-ups | Name variables like millis, bytes |
If you want a compact, official overview of Java’s primitive types (including long), Oracle’s Java documentation is a solid checkpoint. The Java Tutorials page on primitive data types summarizes sizes and usage patterns in plain language.
A steady mental model that makes long feel simple
Think of long as “the whole-number type with room.” It stores a 64-bit signed integer. It’s fixed-size, fast, and predictable. It doesn’t magically prevent bugs, yet it removes a common failure mode: running out of range too early.
When you choose long with intent, you also write clearer code. You can signal “this value may grow large,” and you can make arithmetic choices that keep totals correct.
So if you’re counting bytes, measuring time, storing IDs, or tracking totals that can climb for years, long is the calm choice. It gives your code breathing room, and it keeps your future self from staring at a negative number that should never be negative.
References & Sources
- Oracle.“Java Language Specification: Types, Values, and Variables.”Defines Java primitive types and their required ranges and behavior.
- Oracle.“Primitive Data Types (The Java™ Tutorials).”Summarizes Java primitive numeric types, sizes, and common usage.