📄 objects.java
字号:
} /** * Makes a deep clone of an object by serializing and deserializing it. The object must be fully * serializable to be cloned. This method will not clone wicket Components, it will just reuse * those instances so that the complete component tree is not copied over only the model data. * * @param object * The object to clone * @return A deep copy of the object */ public static Object cloneModel(final Object object) { if (object == null) { return null; } else { try { final ByteArrayOutputStream out = new ByteArrayOutputStream(256); final HashMap replacedObjects = new HashMap(); ObjectOutputStream oos = new ReplaceObjectOutputStream(out, replacedObjects); oos.writeObject(object); ObjectInputStream ois = new ReplaceObjectInputStream(new ByteArrayInputStream(out .toByteArray()), replacedObjects, object.getClass().getClassLoader()); return ois.readObject(); } catch (ClassNotFoundException e) { throw new WicketRuntimeException("Internal error cloning object", e); } catch (IOException e) { throw new WicketRuntimeException("Internal error cloning object", e); } } } /** * Makes a deep clone of an object by serializing and deserializing it. The object must be fully * serializable to be cloned. No extra debug info is gathered. * * @param object * The object to clone * @return A deep copy of the object * @see #cloneModel(Object) */ public static Object cloneObject(final Object object) { if (object == null) { return null; } else { try { final ByteArrayOutputStream out = new ByteArrayOutputStream(256); ObjectOutputStream oos = new ObjectOutputStream(out); oos.writeObject(object); ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(out .toByteArray())) { // This override is required to resolve classes inside in different bundle, i.e. // The classes can be resolved by OSGI classresolver implementation protected Class resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException { String className = desc.getName(); try { return Class.forName(className, true, object.getClass() .getClassLoader()); } catch (ClassNotFoundException ex1) { // ignore this exception. log .debug("Class not found by using objects own classloader, trying the IClassResolver"); } Application application = Application.get(); IApplicationSettings applicationSettings = application .getApplicationSettings(); IClassResolver classResolver = applicationSettings.getClassResolver(); Class candidate = null; try { candidate = classResolver.resolveClass(className); if (candidate == null) { candidate = super.resolveClass(desc); } } catch (WicketRuntimeException ex) { if (ex.getCause() instanceof ClassNotFoundException) { throw (ClassNotFoundException)ex.getCause(); } } return candidate; } }; return ois.readObject(); } catch (ClassNotFoundException e) { throw new WicketRuntimeException("Internal error cloning object", e); } catch (IOException e) { throw new WicketRuntimeException("Internal error cloning object", e); } } } /** * Compares two objects for equality, even if it has to convert one of them to the other type. * If both objects are numeric they are converted to the widest type and compared. If one is * non-numeric and one is numeric the non-numeric is converted to double and compared to the * double numeric value. If both are non-numeric and Comparable and the types are compatible * (i.e. v1 is of the same or superclass of v2's type) they are compared with * Comparable.compareTo(). If both values are non-numeric and not Comparable or of incompatible * classes this will throw and IllegalArgumentException. * * @param v1 * First value to compare * @param v2 * second value to compare * * @return integer describing the comparison between the two objects. A negative number * indicates that v1 < v2. Positive indicates that v1 > v2. Zero indicates v1 == v2. * * @throws IllegalArgumentException * if the objects are both non-numeric yet of incompatible types or do not implement * Comparable. */ public static int compareWithConversion(Object v1, Object v2) { int result; if (v1 == v2) { result = 0; } else { int t1 = getNumericType(v1), t2 = getNumericType(v2), type = getNumericType(t1, t2, true); switch (type) { case BIGINT : result = bigIntValue(v1).compareTo(bigIntValue(v2)); break; case BIGDEC : result = bigDecValue(v1).compareTo(bigDecValue(v2)); break; case NONNUMERIC : if ((t1 == NONNUMERIC) && (t2 == NONNUMERIC)) { if ((v1 instanceof Comparable) && v1.getClass().isAssignableFrom(v2.getClass())) { result = ((Comparable)v1).compareTo(v2); break; } else { throw new IllegalArgumentException("invalid comparison: " + v1.getClass().getName() + " and " + v2.getClass().getName()); } } // else fall through case FLOAT : case DOUBLE : double dv1 = doubleValue(v1), dv2 = doubleValue(v2); return (dv1 == dv2) ? 0 : ((dv1 < dv2) ? -1 : 1); default : long lv1 = longValue(v1), lv2 = longValue(v2); return (lv1 == lv2) ? 0 : ((lv1 < lv2) ? -1 : 1); } } return result; } /** * Returns the value converted numerically to the given class type * * This method also detects when arrays are being converted and converts the components of one * array to the type of the other. * * @param value * an object to be converted to the given type * @param toType * class type to be converted to * @return converted value of the type given, or value if the value cannot be converted to the * given type. */ public static Object convertValue(Object value, Class toType) { Object result = null; if (value != null) { /* If array -> array then convert components of array individually */ if (value.getClass().isArray() && toType.isArray()) { Class componentType = toType.getComponentType(); result = Array.newInstance(componentType, Array.getLength(value)); for (int i = 0, icount = Array.getLength(value); i < icount; i++) { Array.set(result, i, convertValue(Array.get(value, i), componentType)); } } else { if ((toType == Integer.class) || (toType == Integer.TYPE)) { result = new Integer((int)longValue(value)); } if ((toType == Double.class) || (toType == Double.TYPE)) { result = new Double(doubleValue(value)); } if ((toType == Boolean.class) || (toType == Boolean.TYPE)) { result = booleanValue(value) ? Boolean.TRUE : Boolean.FALSE; } if ((toType == Byte.class) || (toType == Byte.TYPE)) { result = new Byte((byte)longValue(value)); } if ((toType == Character.class) || (toType == Character.TYPE)) { result = new Character((char)longValue(value)); } if ((toType == Short.class) || (toType == Short.TYPE)) { result = new Short((short)longValue(value)); } if ((toType == Long.class) || (toType == Long.TYPE)) { result = new Long(longValue(value)); } if ((toType == Float.class) || (toType == Float.TYPE)) { result = new Float(doubleValue(value)); } if (toType == BigInteger.class) { result = bigIntValue(value); } if (toType == BigDecimal.class) { result = bigDecValue(value); } if (toType == String.class) { result = stringValue(value); } } } else { if (toType.isPrimitive()) { result = primitiveDefaults.get(toType); } } return result; } /** * Evaluates the given object as a double-precision floating-point number. * * @param value * an object to interpret as a double * @return the double value implied by the given object * @throws NumberFormatException * if the given object can't be understood as a double */ public static double doubleValue(Object value) throws NumberFormatException { if (value == null) { return 0.0; } Class c = value.getClass(); if (c.getSuperclass() == Number.class) { return ((Number)value).doubleValue(); } if (c == Boolean.class) { return ((Boolean)value).booleanValue() ? 1 : 0; } if (c == Character.class) { return ((Character)value).charValue(); } String s = stringValue(value, true); return (s.length() == 0) ? 0.0 : Double.parseDouble(s); } /** * Returns true if a and b are equal. Either object may be null. * * @param a * Object a * @param b * Object b * @return True if the objects are equal */ public static boolean equal(final Object a, final Object b) { if (a == b) { return true; } if ((a != null) && (b != null) && a.equals(b)) { return true; } return false; } /** * Returns the constant from the NumericTypes interface that best expresses the type of an * operation, which can be either numeric or not, on the two given types. * * @param t1 * type of one argument to an operator * @param t2 * type of the other argument * @param canBeNonNumeric * whether the operator can be interpreted as non-numeric * @return the appropriate constant from the NumericTypes interface */ public static int getNumericType(int t1, int t2, boolean canBeNonNumeric) { if (t1 == t2) { return t1; } if (canBeNonNumeric && (t1 == NONNUMERIC || t2 == NONNUMERIC || t1 == CHAR || t2 == CHAR)) { return NONNUMERIC; } if (t1 == NONNUMERIC) { t1 = DOUBLE; // Try to interpret strings as doubles... } if (t2 == NONNUMERIC) { t2 = DOUBLE; // Try to interpret strings as doubles... } if (t1 >= MIN_REAL_TYPE) { if (t2 >= MIN_REAL_TYPE) { return Math.max(t1, t2); } if (t2 < INT) { return t1; } if (t2 == BIGINT) { return BIGDEC; } return Math.max(DOUBLE, t1); } else if (t2 >= MIN_REAL_TYPE) { if (t1 < INT) { return t2; } if (t1 == BIGINT) { return BIGDEC; } return Math.max(DOUBLE, t2); } else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -