NumFormatter.java
package space.sunqian.fs.base.number;
import space.sunqian.annotation.Nonnull;
import space.sunqian.annotation.Nullable;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.function.Supplier;
/**
* Formatter for number. The implementation of this interface is immutable and thread-safe.
*
* @author sunqian
*/
public interface NumFormatter {
/**
* Returns a common {@link NumFormatter} which uses {@link Number#toString()} to format the number and
* {@link NumKit#toNumber(CharSequence, Class)} to parse the string. Note the returned instance is singleton.
*
* @return a common {@link NumFormatter} which uses {@link Number#toString()} to format the number and
* {@link NumKit#toNumber(CharSequence, Class)} to parse the string
*/
static @Nonnull NumFormatter common() {
return NumFormatterImpl.Common.INST;
}
/**
* Returns a new {@link NumFormatter} with the given number format supplier.
*
* @param supplier the number format supplier
* @return a new {@link NumFormatter} with the given number format supplier
*/
static @Nonnull NumFormatter ofSupplier(@Nonnull Supplier<? extends @Nonnull NumberFormat> supplier) {
return new NumFormatterImpl(supplier);
}
/**
* Returns a new {@link NumFormatter} with the given number format pattern.
* <p>
* By default, this method uses {@link DecimalFormat} and {@link ThreadLocal} to support multi-threading.
*
* @param pattern the number format pattern
* @return a new {@link NumFormatter} with the given number format pattern
*/
static @Nonnull NumFormatter ofPattern(@Nonnull String pattern) {
ThreadLocal<DecimalFormat> format = ThreadLocal.withInitial(() -> new DecimalFormat(pattern));
return ofSupplier(format::get);
}
/**
* Formats the given number.
*
* @param num the given number to format
* @return the formatted string
* @throws NumException if any error occurs
*/
@Nonnull
String format(@Nonnull Number num) throws NumException;
/**
* Formats the given number. If the given number is {@code null}, or an exception thrown during formating, returns
* {@code null}.
*
* @param num the given number to format, can be {@code null}
* @return the formatted string, or {@code null} if the given number is {@code null} or an exception thrown
* @throws NumException if any error occurs
*/
default @Nullable String formatSafe(@Nullable Number num) throws NumException {
if (num == null) {
return null;
}
try {
return format(num);
} catch (Exception e) {
return null;
}
}
/**
* Parses the given number string to an instance of the specified number type.
*
* @param numStr the given number string to parse
* @param numType the specified number type
* @param <T> the number type
* @return the parsed number instance
* @throws NumException if any error occurs
*/
<T> @Nonnull T parse(@Nonnull CharSequence numStr, @Nonnull Class<T> numType) throws NumException;
/**
* Parses the given number string to an instance of the specified number type. If the given number string is
* {@code null}, or an exception thrown during parsing, returns {@code null}.
*
* @param numStr the given number string to parse, can be {@code null}
* @param numType the specified number type
* @param <T> the number type
* @return the parsed number instance, or {@code null} if the given number string is {@code null} or an exception
* thrown
* @throws NumException if any error occurs
*/
default <T> @Nullable T parseSafe(
@Nullable CharSequence numStr, @Nonnull Class<T> numType
) throws NumException {
if (numStr == null) {
return null;
}
try {
return parse(numStr, numType);
} catch (Exception e) {
return null;
}
}
}