T isInstanceOf(Class> type, T obj, String errorMsgTemplate, Object... params)
+ throws IllegalArgumentException {
+ notNull(type, "Type to check against must not be null");
+ if (!type.isInstance(obj)) {
+ throw new IllegalArgumentException(format(errorMsgTemplate, params));
+ }
+ return obj;
+ }
+
+ /**
+ * 断言 {@code superType.isAssignableFrom(subType)} 是否为 {@code true}.
+ *
+ *
+ * Assert.isAssignable(Number.class, myClass);
+ *
+ * @param superType 需要检查的父类或接口
+ * @param subType 需要检查的子类
+ * @throws IllegalArgumentException 如果子类非继承父类,抛出此异常
+ */
+ public static void isAssignable(Class> superType, Class> subType) throws IllegalArgumentException {
+ isAssignable(superType, subType, "{} is not assignable to {})", subType, superType);
+ }
+
+ /**
+ * 断言 {@code superType.isAssignableFrom(subType)} 是否为 {@code true}.
+ *
+ *
+ * Assert.isAssignable(Number.class, myClass, "myClass must can be assignable to class Number");
+ *
+ * @param superType 需要检查的父类或接口
+ * @param subType 需要检查的子类
+ * @param errorMsgTemplate 异常时的消息模板
+ * @param params 参数列表
+ * @throws IllegalArgumentException 如果子类非继承父类,抛出此异常
+ */
+ public static void isAssignable(Class> superType, Class> subType, String errorMsgTemplate, Object... params)
+ throws IllegalArgumentException {
+ notNull(superType, "Type to check against must not be null");
+ if (subType == null || !superType.isAssignableFrom(subType)) {
+ throw new IllegalArgumentException(format(errorMsgTemplate, params));
+ }
+ }
+
+ /**
+ * 检查boolean表达式,当检查结果为false时抛出 {@code IllegalStateException}。 并使用指定的函数获取错误信息返回
+ *
+ * Assert.state(id == null, ()->{
+ * // to query relation message
+ * return "relation message to return ";
+ * });
+ *
+ * @param expression boolean 表达式
+ * @param errorMsgSupplier 错误抛出异常附带的消息生产接口
+ * @throws IllegalStateException 表达式为 {@code false} 抛出此异常
+ */
+ public static void state(boolean expression, Supplier errorMsgSupplier) throws IllegalStateException {
+ if (!expression) {
+ throw new IllegalStateException(errorMsgSupplier.get());
+ }
+ }
+
+ /**
+ * 检查boolean表达式,当检查结果为false时抛出 {@code IllegalStateException}。
+ *
+ *
+ * Assert.state(id == null, "The id property must not already be initialized");
+ *
+ * @param expression boolean 表达式
+ * @param errorMsgTemplate 异常时的消息模板
+ * @param params 参数列表
+ * @throws IllegalStateException 表达式为 {@code false} 抛出此异常
+ */
+ public static void state(boolean expression, String errorMsgTemplate, Object... params)
+ throws IllegalStateException {
+ if (!expression) {
+ throw new IllegalStateException(format(errorMsgTemplate, params));
+ }
+ }
+
+ /**
+ * 检查boolean表达式,当检查结果为false时抛出 {@code IllegalStateException}。
+ *
+ *
+ * Assert.state(id == null);
+ *
+ * @param expression boolean 表达式
+ * @throws IllegalStateException 表达式为 {@code false} 抛出此异常
+ */
+ public static void state(boolean expression) throws IllegalStateException {
+ state(expression, "[Assertion failed] - this state invariant must be true");
+ }
+
+ /**
+ * 检查下标(数组、集合、字符串)是否符合要求,下标必须满足:
+ *
+ *
+ * 0 ≤ index < size
+ *
+ * @param index 下标
+ * @param size 长度
+ * @return 检查后的下标
+ * @throws IllegalArgumentException 如果size < 0 抛出此异常
+ * @throws IndexOutOfBoundsException 如果index < 0或者 index ≥ size 抛出此异常
+ */
+ public static int checkIndex(int index, int size) throws IllegalArgumentException, IndexOutOfBoundsException {
+ return checkIndex(index, size, "[Assertion failed]");
+ }
+
+ /**
+ * 检查下标(数组、集合、字符串)是否符合要求,下标必须满足:
+ *
+ *
+ * 0 ≤ index < size
+ *
+ * @param index 下标
+ * @param size 长度
+ * @param errorMsgTemplate 异常时的消息模板
+ * @param params 参数列表
+ * @return 检查后的下标
+ * @throws IllegalArgumentException 如果size < 0 抛出此异常
+ * @throws IndexOutOfBoundsException 如果index < 0或者 index ≥ size 抛出此异常
+ */
+ public static int checkIndex(int index, int size, String errorMsgTemplate, Object... params)
+ throws IllegalArgumentException, IndexOutOfBoundsException {
+ if (index < 0 || index >= size) {
+ throw new IndexOutOfBoundsException(badIndexMsg(index, size, errorMsgTemplate, params));
+ }
+ return index;
+ }
+
+ /**
+ * 检查值是否在指定范围内
+ * @param 异常类型
+ * @param value 值
+ * @param min 最小值(包含)
+ * @param max 最大值(包含)
+ * @param errorSupplier 错误抛出异常附带的消息生产接口
+ * @return 经过检查后的值
+ * @throws X if value is out of bound
+ */
+ public static int checkBetween(int value, int min, int max,
+ Supplier extends X> errorSupplier) throws X {
+ if (value < min || value > max) {
+ throw errorSupplier.get();
+ }
+
+ return value;
+ }
+
+ /**
+ * 检查值是否在指定范围内
+ * @param value 值
+ * @param min 最小值(包含)
+ * @param max 最大值(包含)
+ * @param errorMsgTemplate 异常信息模板,类似于"aa{}bb{}cc"
+ * @param params 异常信息参数,用于替换"{}"占位符
+ * @return 经过检查后的值
+ */
+ public static int checkBetween(int value, int min, int max, String errorMsgTemplate, Object... params) {
+ return checkBetween(value, min, max, () -> new IllegalArgumentException(format(errorMsgTemplate, params)));
+ }
+
+ /**
+ * 检查值是否在指定范围内
+ * @param value 值
+ * @param min 最小值(包含)
+ * @param max 最大值(包含)
+ * @return 检查后的长度值
+ */
+ public static int checkBetween(int value, int min, int max) {
+ return checkBetween(value, min, max, TEMPLATE_VALUE_MUST_BE_BETWEEN_AND, min, max);
+ }
+
+ /**
+ * 检查值是否在指定范围内
+ * @param 异常类型
+ * @param value 值
+ * @param min 最小值(包含)
+ * @param max 最大值(包含)
+ * @param errorSupplier 错误抛出异常附带的消息生产接口
+ * @return 经过检查后的值
+ * @throws X if value is out of bound
+ */
+ public static long checkBetween(long value, long min, long max,
+ Supplier extends X> errorSupplier) throws X {
+ if (value < min || value > max) {
+ throw errorSupplier.get();
+ }
+
+ return value;
+ }
+
+ /**
+ * 检查值是否在指定范围内
+ * @param value 值
+ * @param min 最小值(包含)
+ * @param max 最大值(包含)
+ * @param errorMsgTemplate 异常信息模板,类似于"aa{}bb{}cc"
+ * @param params 异常信息参数,用于替换"{}"占位符
+ * @return 经过检查后的值
+ */
+ public static long checkBetween(long value, long min, long max, String errorMsgTemplate, Object... params) {
+ return checkBetween(value, min, max, () -> new IllegalArgumentException(format(errorMsgTemplate, params)));
+ }
+
+ /**
+ * 检查值是否在指定范围内
+ * @param value 值
+ * @param min 最小值(包含)
+ * @param max 最大值(包含)
+ * @return 检查后的长度值
+ */
+ public static long checkBetween(long value, long min, long max) {
+ return checkBetween(value, min, max, TEMPLATE_VALUE_MUST_BE_BETWEEN_AND, min, max);
+ }
+
+ /**
+ * 检查值是否在指定范围内
+ * @param 异常类型
+ * @param value 值
+ * @param min 最小值(包含)
+ * @param max 最大值(包含)
+ * @param errorSupplier 错误抛出异常附带的消息生产接口
+ * @return 经过检查后的值
+ * @throws X if value is out of bound
+ */
+ public static double checkBetween(double value, double min, double max,
+ Supplier extends X> errorSupplier) throws X {
+ if (value < min || value > max) {
+ throw errorSupplier.get();
+ }
+
+ return value;
+ }
+
+ /**
+ * 检查值是否在指定范围内
+ * @param value 值
+ * @param min 最小值(包含)
+ * @param max 最大值(包含)
+ * @param errorMsgTemplate 异常信息模板,类似于"aa{}bb{}cc"
+ * @param params 异常信息参数,用于替换"{}"占位符
+ * @return 经过检查后的值
+ */
+ public static double checkBetween(double value, double min, double max, String errorMsgTemplate, Object... params) {
+ return checkBetween(value, min, max, () -> new IllegalArgumentException(format(errorMsgTemplate, params)));
+ }
+
+ /**
+ * 检查值是否在指定范围内
+ * @param value 值
+ * @param min 最小值(包含)
+ * @param max 最大值(包含)
+ * @return 检查后的长度值
+ */
+ public static double checkBetween(double value, double min, double max) {
+ return checkBetween(value, min, max, TEMPLATE_VALUE_MUST_BE_BETWEEN_AND, min, max);
+ }
+
+ /**
+ * 检查值是否在指定范围内
+ * @param value 值
+ * @param min 最小值(包含)
+ * @param max 最大值(包含)
+ * @return 检查后的长度值
+ */
+ public static Number checkBetween(Number value, Number min, Number max) {
+ notNull(value);
+ notNull(min);
+ notNull(max);
+ double valueDouble = value.doubleValue();
+ double minDouble = min.doubleValue();
+ double maxDouble = max.doubleValue();
+ if (valueDouble < minDouble || valueDouble > maxDouble) {
+ throw new IllegalArgumentException(format(TEMPLATE_VALUE_MUST_BE_BETWEEN_AND, min, max));
+ }
+ return value;
+ }
+
+ /**
+ * 断言两个对象是否不相等,如果两个对象相等 抛出IllegalArgumentException 异常
+ * Assert.notEquals(obj1,obj2);
+ *
+ * @param obj1 对象1
+ * @param obj2 对象2
+ * @throws IllegalArgumentException obj1 must be not equals obj2
+ */
+ public static void notEquals(Object obj1, Object obj2) {
+ notEquals(obj1, obj2, "({}) must be not equals ({})", obj1, obj2);
+ }
+
+ /**
+ * 断言两个对象是否不相等,如果两个对象相等 抛出IllegalArgumentException 异常
+ * Assert.notEquals(obj1,obj2,"obj1 must be not equals obj2");
+ *
+ * @param obj1 对象1
+ * @param obj2 对象2
+ * @param errorMsgTemplate 异常信息模板,类似于"aa{}bb{}cc"
+ * @param params 异常信息参数,用于替换"{}"占位符
+ * @throws IllegalArgumentException obj1 must be not equals obj2
+ */
+ public static void notEquals(Object obj1, Object obj2, String errorMsgTemplate, Object... params)
+ throws IllegalArgumentException {
+ notEquals(obj1, obj2, () -> new IllegalArgumentException(format(errorMsgTemplate, params)));
+ }
+
+ /**
+ * 断言两个对象是否不相等,如果两个对象相等,抛出指定类型异常,并使用指定的函数获取错误信息返回
+ * @param obj1 对象1
+ * @param obj2 对象2
+ * @param errorSupplier 错误抛出异常附带的消息生产接口
+ * @param 异常类型
+ * @throws X obj1 must be not equals obj2
+ */
+ public static void notEquals(Object obj1, Object obj2, Supplier errorSupplier) throws X {
+ if (objectEquals(obj1, obj2)) {
+ throw errorSupplier.get();
+ }
+ }
+ // -----------------------------------------------------------------------------------------------------------
+ // Check not equals
+
+ /**
+ * 断言两个对象是否相等,如果两个对象不相等 抛出IllegalArgumentException 异常
+ * Assert.isEquals(obj1,obj2);
+ *
+ * @param obj1 对象1
+ * @param obj2 对象2
+ * @throws IllegalArgumentException obj1 must be equals obj2
+ */
+ public static void equals(Object obj1, Object obj2) {
+ equals(obj1, obj2, "({}) must be equals ({})", obj1, obj2);
+ }
+
+ /**
+ * 断言两个对象是否相等,如果两个对象不相等 抛出IllegalArgumentException 异常
+ * Assert.isEquals(obj1,obj2,"obj1 must be equals obj2");
+ *
+ * @param obj1 对象1
+ * @param obj2 对象2
+ * @param errorMsgTemplate 异常信息模板,类似于"aa{}bb{}cc"
+ * @param params 异常信息参数,用于替换"{}"占位符
+ * @throws IllegalArgumentException obj1 must be equals obj2
+ */
+ public static void equals(Object obj1, Object obj2, String errorMsgTemplate, Object... params)
+ throws IllegalArgumentException {
+ equals(obj1, obj2, () -> new IllegalArgumentException(format(errorMsgTemplate, params)));
+ }
+
+ /**
+ * 断言两个对象是否相等,如果两个对象不相等,抛出指定类型异常,并使用指定的函数获取错误信息返回
+ * @param obj1 对象1
+ * @param obj2 对象2
+ * @param errorSupplier 错误抛出异常附带的消息生产接口
+ * @param 异常类型
+ * @throws X obj1 must be equals obj2
+ */
+ public static void equals(Object obj1, Object obj2, Supplier errorSupplier) throws X {
+ if (!objectEquals(obj1, obj2)) {
+ throw errorSupplier.get();
+ }
+ }
+
+ // -----------------------------------------------------------------------------------------------------------
+ // Check is equals
+
+ // --------------------------------------------------------------------------------------------------------------------------------------------
+ // Private method start
+
+ /**
+ * 错误的下标时显示的消息
+ * @param index 下标
+ * @param size 长度
+ * @param desc 异常时的消息模板
+ * @param params 参数列表
+ * @return 消息
+ */
+ private static String badIndexMsg(int index, int size, String desc, Object... params) {
+ if (index < 0) {
+ return format("{} ({}) must not be negative", format(desc, params), index);
+ }
+ else if (size < 0) {
+ throw new IllegalArgumentException("negative size: " + size);
+ }
+ else { // index >= size
+ return format("{} ({}) must be less than size ({})", format(desc, params), index, size);
+ }
+
+ }
+
+ /**
+ * 对象相等判断
+ * @param obj1 对象1
+ * @param obj2 对象2
+ * @return 是否相等
+ */
+ private static boolean objectEquals(Object obj1, Object obj2) {
+ if (obj1 instanceof BigDecimal && obj2 instanceof BigDecimal) {
+ if (obj1 == obj2) {
+ return true;
+ }
+ if (obj1 == null || obj2 == null) {
+ return false;
+ }
+ return 0 == ((BigDecimal) obj1).compareTo((BigDecimal) obj2);
+ }
+ return Objects.equals(obj1, obj2);
+ }
+
+ /**
+ * 根据占位符模版+参数输出字符串
+ * @param template 占位符模版
+ * @param args 参数
+ * @return 字符串
+ */
+ private static String format(String template, Object... args) {
+ int i = 0;
+ while (template.contains("{}")) {
+ template = template.replaceFirst(Pattern.quote("{}"), "{" + i++ + "}");
+ }
+ return MessageFormat.format(template, args);
+ }
+ // --------------------------------------------------------------------------------------------------------------------------------------------
+ // Private method end
+
}