Understand Clojure's core scalar values on the JVM: numbers, strings, characters, booleans, nil, truthiness, and the interop details Java engineers need to recognize early.
Java developers already think in terms of types, but Clojure changes where “type work” happens. You still run on the JVM and you still have Java classes under the hood, but most application code lets values and operations drive the design. You reach for explicit type control when interop, correctness, or performance demands it.
This section focuses on the scalar values you will see everywhere: numbers, strings, characters, booleans, nil, and JVM-backed variants such as ratios, BigInt, and BigDecimal.
Java mental model: Clojure is dynamically typed, but it’s not “typeless”—values have concrete JVM classes, and you can always inspect them at the REPL.
false and nil are falsy. Everything else is truthy.nil vs null: nil is the idiomatic “no value” in Clojure, but Java APIs may still return/accept null—interop code should be defensive.1 as a Long, 1N as a BigInt, 1M as a BigDecimal, and ratios like 1/3.1(class 1) ;; => java.lang.Long
2(class 1N) ;; => clojure.lang.BigInt
3(class 1/3) ;; => clojure.lang.Ratio
As a Java engineer, the main skill is deciding which details matter in normal Clojure code and which details matter only at boundaries. Truthiness, nil, numeric literals, and Java string interop matter immediately. Primitive specialization, unchecked math, and type hints can usually wait until profiling or interop makes them necessary.