All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.dongliu.commons.Objects2 Maven / Gradle / Ivy

There is a newer version: 12.0.2
Show newest version
package net.dongliu.commons;


import net.dongliu.commons.reflection.Classes;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
import java.util.function.Supplier;

import static java.util.Objects.requireNonNull;

/**
 * Jdk already has one Objects class, So named as Objects2
 */
public class Objects2 {

    /**
     * Elvis operator.
     * If value1 is not null, use return value1; else return values2.
     *
     * @param  the value type
     * @return non-null value
     * @throws NullPointerException if value2 is null
     */
    @NotNull
    public static  T elvis(@Nullable T value1, T value2) {
        if (value1 != null) {
            return value1;
        }
        return requireNonNull(value2);
    }

    /**
     * Elvis operator.
     * If value1 is not null, use return value1; else use value calculate by supplier.
     *
     * @param supplier to calculate non-null value
     * @param       the value type
     * @return non-null value
     * @throws NullPointerException if supplier is null or produce null value
     */
    @NotNull
    public static  T elvis(@Nullable T value1, Supplier supplier) {
        if (value1 != null) {
            return value1;
        }
        return requireNonNull(supplier.get());
    }

    /**
     * Get a ToStringHelper to convert specific type object to string.
     */
    @NotNull
    public static ToStringHelper toStringHelper(Class cls) {
        return new ToStringHelper(requireNonNull(cls));
    }

    public static class ToStringHelper {
        private final Class cls;
        private final boolean hasToStringMethod;
        private final List memberFields;
        private final String className;

        protected ToStringHelper(Class cls) {
            this.cls = cls;
            this.hasToStringMethod = classHasStringMethod(cls);
            this.memberFields = Classes.getAllMemberFields(cls);
            String className;
            if (cls.isAnonymousClass()) {
                className = Strings.subStringAfterLast(cls.getName(), ".");
            } else {
                className = cls.getSimpleName();
            }
            this.className = className;
        }


        /**
         * Convert object to string.
         * If Object has override toString method, will can this; else, will build string by concat
         * all member fields of this object.
         * Array field of object, will convert to string using Arrays.toString;
         * otherwise, will use call field value's toString method.
         *
         * @param value the value
         * @return the string representation of this object value. If object is null, return "null"
         */
        public String toString(@Nullable Object value) {
            if (value == null) {
                return "null";
            }
            if (!this.cls.equals(value.getClass())) {
                throw new IllegalArgumentException("value type " + value.getClass().getName() + " not match with ToStringHelper");
            }

            if (hasToStringMethod) {
                return value.toString();
            }

            if (cls.isArray()) {
                return arrayToString(value);
            }

            StringBuilder sb = new StringBuilder();
            sb.append(className).append('{');
            for (Field field : memberFields) {
                field.setAccessible(true);
                sb.append(field.getName()).append('=');

                Class type = field.getType();
                if (type.isPrimitive()) {
                    try {
                        appendPrimitiveField(sb, field, value);
                    } catch (IllegalAccessException e) {
                        throw new RuntimeException(e);
                    }
                } else {
                    Object fieldValue;
                    try {
                        fieldValue = field.get(value);
                    } catch (IllegalAccessException e) {
                        throw new RuntimeException(e);
                    }
                    if (fieldValue == null) {
                        sb.append("null");
                    } else if (fieldValue.getClass().isArray()) {
                        sb.append(arrayToString(fieldValue));
                    } else {
                        sb.append(fieldValue.toString());
                    }
                }
                sb.append(", ");
            }
            if (!memberFields.isEmpty()) {
                sb.setLength(sb.length() - 2);
            }
            sb.append('}');
            return sb.toString();
        }

        private boolean classHasStringMethod(Class cls) {
            try {
                Method method = cls.getDeclaredMethod("toString");
                // may have strange generated method return different type?
                return method.getReturnType().equals(String.class);
            } catch (NoSuchMethodException e) {
                return false;
            }
        }

        private void appendPrimitiveField(StringBuilder sb, Field field, Object value) throws IllegalAccessException {
            Class type = field.getType();
            if (type == int.class) {
                sb.append(field.getInt(value));
            } else if (type == long.class) {
                sb.append(field.getLong(value));
            } else if (type == short.class) {
                sb.append(field.getShort(value));
            } else if (type == boolean.class) {
                sb.append(field.getBoolean(value));
            } else if (type == float.class) {
                sb.append(field.getFloat(value));
            } else if (type == double.class) {
                sb.append(field.getDouble(value));
            } else if (type == byte.class) {
                sb.append(field.getByte(value));
            } else if (type == char.class) {
                sb.append(field.getChar(value));
            } else {
                throw new RuntimeException("not primitive type: " + type.getName());
            }
        }

        private String arrayToString(Object value) {
            if (value instanceof boolean[]) {
                return Arrays.toString((boolean[]) value);
            } else if (value instanceof char[]) {
                return Arrays.toString((char[]) value);
            } else if (value instanceof byte[]) {
                return Arrays.toString((byte[]) value);
            } else if (value instanceof short[]) {
                return Arrays.toString((short[]) value);
            } else if (value instanceof int[]) {
                return Arrays.toString((int[]) value);
            } else if (value instanceof long[]) {
                return Arrays.toString((long[]) value);
            } else if (value instanceof float[]) {
                return Arrays.toString((float[]) value);
            } else if (value instanceof double[]) {
                return Arrays.toString((double[]) value);
            } else {
                return Arrays.toString((Object[]) value);
            }
        }
    }


}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy