string-format: String.format/formatted/printf cheat sheet module (specifier anatomy, rounding vs C printf, locales, Indian lakh/crore grouping Formatter cannot do, format exceptions, %t dates, concat cost), 11 contract tests
Co-Authored-By: Claude Sonnet 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_017ic4b7Sr2zcoRD2watXv1G
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
# string-format
|
||||
|
||||
Companion code for the ankurm.com post *"String.format, formatted() and printf in Java: The Complete Cheat Sheet."*
|
||||
Module in `java-core-examples`, the Java-core series.
|
||||
|
||||
## Versions this was built and tested against
|
||||
|
||||
| Component | Version | Notes |
|
||||
|---|---|---|
|
||||
| JDK | 25.0.5+8 (Temurin, LTS) | `String.format` is Java 5; `String.formatted()` arrived in Java 15; `Formatter` parsing was rewritten without regex in Java 17. |
|
||||
| JUnit Jupiter | 5.11.0 | |
|
||||
| Maven | 3.9.11 | |
|
||||
|
||||
## Quickstart
|
||||
|
||||
```bash
|
||||
export JAVA_HOME=/path/to/jdk-25
|
||||
mvn compile
|
||||
scripts/run.sh IndianGroupingDemo # one demo
|
||||
scripts/run-all.sh # regenerate every file in output/
|
||||
```
|
||||
|
||||
## What's in here
|
||||
|
||||
| File | What it shows |
|
||||
|---|---|
|
||||
| `BasicsDemo.java` | Every part of `%[index$][flags][width][.precision]conversion`, changed one at a time. |
|
||||
| `ReportTableDemo.java` | Left/right alignment, zero padding, truncation with `%.Ns`, a fixed-width invoice, `printf`. |
|
||||
| `RoundingDemo.java` | `%f` rounds HALF_UP on the decimal string, so it disagrees with C `printf` and with `BigDecimal(double)`. |
|
||||
| `IndianNumberFormat.java` + `IndianGroupingDemo.java` | **The main exhibit.** Every built-in route to lakh/crore grouping tried and shown to fail, then a 60-line formatter that works. |
|
||||
| `LocaleDemo.java` | The same `%,.2f` under six locales; the default-locale trap; what is *not* localized. |
|
||||
| `FormatErrorsDemo.java` | Twelve format strings that compile and then throw (or, for `"50% off"`, throw something surprising), with the real exception text. |
|
||||
| `FormattedAndPrintfDemo.java` | `format` / `formatted` / `printf` / `Formatter` are one engine; text-block pairing; varargs and arrays. |
|
||||
| `DateTimeDemo.java` | `%tF`, `%tT`, `%tA` on `java.time` values, localized names, and why `%tH` on a `LocalDate` throws. |
|
||||
| `ConcatBenchmarkDemo.java` | Indicative cost of `+`, `StringBuilder`, `formatted`, `format`. A warmed plain loop, not JMH. |
|
||||
| `StringFormatTest.java` | Pins every claim above as an assertion, 11/11 passing. |
|
||||
| `scripts/printf_compare.c` | The same values through C `printf`, for the rounding comparison. |
|
||||
| `output/01-11` | Captured runs of everything above. Timing in `08` drifts between runs. |
|
||||
|
||||
## Notes worth knowing before reading the post
|
||||
|
||||
- **`%,d` cannot produce lakh/crore grouping in any locale.** `en_IN` and `hi_IN` both print `123,456,789`
|
||||
(`output/04`). The `,` flag takes one grouping size from `DecimalFormat.getGroupingSize()`, and a
|
||||
`DecimalFormat` built from `#,##,##0` reports a grouping size of 3.
|
||||
- **`"Discount 50% off"` throws `MissingFormatArgumentException`**, not an unknown-conversion error:
|
||||
`% o` parses as the space flag plus the octal conversion (`output/06`).
|
||||
- **`%f` on a `double` rounds the decimal string, `%f` on a `BigDecimal` rounds the exact value**, so
|
||||
`2.675` formats as `2.68` one way and `2.67` the other (`output/03`).
|
||||
|
||||
## License
|
||||
|
||||
MIT - see the [repo-wide LICENSE](../LICENSE).
|
||||
Reference in New Issue
Block a user