Creo que tengo la idea de la pregunta y desde que busqué la forma de comparar Pattern
s termino aquí (dos años demasiado tarde, probablemente, bueno, lo siento ...).
Estoy escribiendo pruebas y necesito saber si un método mío devuelve el patrón esperado. Si bien el texto a través de toString()
o pattern()
podría ser el mismo, los indicadores pueden ser diferentes y el resultado al usar el patrón sería inesperado.
Hace un tiempo escribí mi propia implementación general de toString()
. Recoge todos los campos, incluidos los private
, y construye una cadena que se puede usar para iniciar sesión y aparentemente para realizar pruebas. Mostró que los campos root
y matchRoot
eran diferentes al compilar dos patrones iguales. Suponiendo que esos dos no son tan relevantes para la igualdad y dado que hay un campo flag
, mi solución es bastante buena si no perfecta.
/**
* Don't call this method from a <code>toString()</code> method with
* <code>useExistingToString</code> set to <code>true</code>!!!
*/
public static String toString(Object object, boolean useExistingToString, String... ignoreFieldNames) {
if (object == null) {
return null;
}
Class<? extends Object> clazz = object.getClass();
if (useExistingToString) {
try {
// avoid the default implementation Object.toString()
Method methodToString = clazz.getMethod("toString");
if (!methodToString.getDeclaringClass().isAssignableFrom(Object.class)) {
return object.toString();
}
} catch (Exception e) {
}
}
List<String> ignoreFieldNameList = Arrays.asList(ignoreFieldNames);
Map<String, Object> fields = new HashMap<String, Object>();
while (clazz != null) {
for (Field field : clazz.getDeclaredFields()) {
String fieldName = field.getName();
if (ignoreFieldNameList.contains(fieldName) || fields.containsKey(fieldName)) {
continue;
}
boolean accessible = field.isAccessible();
if (!accessible) {
field.setAccessible(true);
}
try {
Object fieldValue = field.get(object);
if (fieldValue instanceof String) {
fieldValue = stringifyValue(fieldValue);
}
fields.put(fieldName, fieldValue);
} catch (Exception e) {
fields.put(fieldName, "-inaccessible- " + e.getMessage());
}
if (!accessible) {
field.setAccessible(false);
}
}
// travel upwards in the class hierarchy
clazz = clazz.getSuperclass();
}
return object.getClass().getName() + ": " + fields;
}
public static String stringifyValue(Object value) {
if (value == null) {
return "null";
}
return "'" + value.toString() + "'";
}
Y la prueba es de color verde:
String toString1 = Utility.toString(Pattern.compile("test", Pattern.CASE_INSENSITIVE), false, "root", "matchRoot");
String toString2 = Utility.toString(Pattern.compile("test", Pattern.CASE_INSENSITIVE), false, "root", "matchRoot");
assertEquals(toString1, toString2);
Si se compara 'pattern' se perderá las banderas. –
@MarkusMalkusch - Sí, esa es otra razón por la que comparar objetos 'Pattern' con' pattern() 'podría ser problemático. –
Los objetos de patrón nunca se han guardado automáticamente en caché. Como evidencia, los documentos API advierten que 'Pattern.matches()' y 'String # matches()' no permiten que el objeto Pattern se reutilice, por lo que no deberían usarse para llamadas repetidas, como en un bucle. (La clase Scanner * does * almacena en caché todos los patrones que utiliza, pero eso se maneja internamente). –