The finite repetition syntax uses {m,n} in place of star/plus/question mark.
From java.util.regex.Pattern:
X{n} X, exactly n times
X{n,} X, at least n times
X{n,m} X, at least n but not more than m times
All repetition metacharacter have the same precedence, so just like you may need grouping for *, +, and ?, you may also for {n,m}.
ha* matches e.g. "haaaaaaaa"
ha{3} matches only "haaa"
(ha)* matches e.g. "hahahahaha"
(ha){3} matches only "hahaha"
Also, just like *, +, and ?, you can add the ? and + reluctant and possessive repetition modifiers respectively.
System.out.println(
"xxxxx".replaceAll("x{2,3}", "[x]")
); "[x][x]"
System.out.println(
"xxxxx".replaceAll("x{2,3}?", "[x]")
); "[x][x]x"
Essentially anywhere a * is a repetition metacharacter for "zero-or-more", you can use {...} repetition construct. Note that it's not true the other way around: you can use finite repetition in a lookbehind, but you can't use * because Java doesn't officially support infinite-length lookbehind.
References
Related questions