es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Cómo obtener un hash de la estructura de una clase de Java?

Imagina que tengo las siguientes dos clases:

public class A {
    private String field1;
    private B field2;
}

public class B {
    private String field3;
}

Lo que quiero hacer es usar Reflexión en Java para obtener todos los campos y subcampos de la clase A y crear un hash a partir de ellos. En este ejemplo, obtendría, por ejemplo, una lista de cadenas que dirían ["field1", "field2", "field3"], y haría un hash de toda la lista.

Por si ayuda, la razón por la que estoy haciendo esto es porque tengo una colección de MongoDB para A. Sin embargo, de vez en cuando, añado nuevos campos a A o B, y necesito actualizar toda la colección con los nuevos campos cuando eso sucede. Para esto, necesito llevar un registro, en una colección separada, de si ya he actualizado o no la colección de A para su estructura actual. La forma más sencilla sería simplemente hacer un hash de los nombres de sus campos y subcampos.

Tags:  ,

Answer

  1. Avatar for davy.ai

    Para lograr esto utilizando Java Reflection, puedes usar el método getDeclaredFields para obtener todos los campos de una clase, y luego llamar recursivamente al método en cualquier campo no primitivo para obtener sus campos también.

    Aquí tienes un ejemplo de método que recibe una clase y devuelve una lista de todos sus campos (incluyendo subcampos):

    import java.lang.reflect.Field;
    import java.util.ArrayList;
    import java.util.List;
    
    public class ReflectionUtil {
    
        public static List<string> getAllFields(Class<?> clazz) {
            List<string> fields = new ArrayList<>();
            for (Field field : clazz.getDeclaredFields()) {
                fields.add(field.getName());
                if (!field.getType().isPrimitive()) {
                    fields.addAll(getAllFields(field.getType()));
                }
            }
            return fields;
        }
    
    }
    

    Se puede llamar a este método en la clase A para obtener una lista de todos sus campos y subcampos:

    List<string> fields = ReflectionUtil.getAllFields(A.class);
    

    Luego puedes hashear la lista completa de campos utilizando alguna función de hash estándar de Java. Por ejemplo, usando SHA-256:

    import java.nio.charset.StandardCharsets;
    import java.security.MessageDigest;
    import java.security.NoSuchAlgorithmException;
    
    public class HashUtil {
    
        public static String sha256Hash(List<string> data) throws NoSuchAlgorithmException {
            MessageDigest digest = MessageDigest.getInstance("SHA-256");
            byte[] hash = digest.digest(String.join(",", data).getBytes(StandardCharsets.UTF_8));
            StringBuilder hexString = new StringBuilder();
            for (byte b : hash) {
                String hex = Integer.toHexString(0xff & b);
                if (hex.length() == 1) hexString.append('0');
                hexString.append(hex);
            }
            return hexString.toString();
        }
    
    }
    

    Puedes llamar a este método para obtener el hash SHA-256 de la lista de campos:

    String hash = HashUtil.sha256Hash(fields);
    

    Este hash se puede almacenar en una colección separada para llevar un registro de si la colección para A ha sido actualizada o no. Cuando quieras verificar si la colección necesita actualizarse, puedes generar el hash nuevamente y compararlo con el hash almacenado. Si son diferentes, sabrás que la colección necesita actualizarse.

Comments are closed.