Benutzerdefinierter Klassen-Mapper in Java
In diesem Artikel erkläre ich, wie man eine benutzerdefinierte Mapper-Util-Klasse in Java implementiert, ohne Bibliotheken von Drittanbietern wie MapStruct zu verwenden.
Zunächst einmal sollten Sie über Grundkenntnisse der Programmiersprache Java und der Java Reflection API verfügen.
Lasst uns beginnen.
public static <O, Target> O map(Object instance, Class<Target> targetClass) {
if (instance.getClass().isPrimitive() || targetClass.isPrimitive()) {
throw new RuntimeException("Provide a non primitive class");
}
if (instance.getClass().isInterface() || targetClass.isInterface()) {
throw new RuntimeException("Provide a non interface class");
}
if (instance.getClass().isEnum() || targetClass.isEnum()) {
throw new RuntimeException("Provide a non enum class");
}
if (Modifier.isAbstract(instance.getClass().getModifiers()) || Modifier.isAbstract(targetClass.getModifiers())) {
throw new RuntimeException("Provide a non abstract class");
}
return doMap(instance, instance.getClass(), targetClass);
}
@SneakyThrows
private static <O, Source, Target> O doMap(Object sourceInstance, Class<Source> sourceClass, Class<Target> targetClass) {
Set<Field> declaredSourceFields = findAllFields(sourceClass);
Set<Field> declaredTargetFields = findAllFields(targetClass);
Object targetInstance = targetClass.getDeclaredConstructor().newInstance();
for (Field field : declaredTargetFields) {
Field sourceField = findSourceField(field, declaredSourceFields);
if (sourceField != null) {
field.setAccessible(true);
field.set(targetInstance, sourceField.get(sourceInstance));
}
}
return (O) targetInstance;
}
public static Set<Field> findAllFields(Class<?> inputClass) {
Set<Field> allFields = new HashSet<>();
if (inputClass == null) {
return allFields;
}
Field[] fields = inputClass.getDeclaredFields();
allFields.addAll(Set.of(fields));
allFields.addAll(findAllFields(inputClass.getSuperclass()));
return allFields;
}
private static Field findSourceField(Field targetField, Set<Field> declaredSourceFields) {
for (Field field : declaredSourceFields) {
field.setAccessible(true);
String sourceFieldName = field.getName();
if (sourceFieldName.equals(targetField.getName()) &&
field.getType().equals(targetField.getType())) {
return field;
}
}
return null;
}
Beispiele:
@Setter
@Getter
public class SourceClass {
String surname;
Integer age;
private String name;
@Override
public String toString() {
return "SourceClass{" +
"surname='" + surname + '\'' +
", age=" + age +
", name='" + name + '\'' +
'}';
}
}
@Setter
@Getter
public class TargetClass {
Integer age;
private String name;
@Override
public String toString() {
return "TargetClass{" +
"age=" + age +
", name='" + name + '\'' +
'}';
}
}
public static void main(String[] args) {
SourceClass sourceInstance = new SourceClass();
sourceInstance.setAge(27);
sourceInstance.setName("Java");
sourceInstance.setSurname("Reflection");
TargetClass targetInstance = CustomMapper.map(sourceInstance, TargetClass.class);
System.out.println(targetInstance);
}
Der Nachname ist in der Ausgabe nicht vorhanden, da er in der Zielklasse nicht verfügbar ist. Daher ignoriert die Kartenmethode dieses Feld.
Fazit:
Die meisten in Java geschriebenen Bibliotheken, Frameworks und Ideen nutzen die Java Reflection API. Diese API ist jedoch etwas langsam, da sie die Sicherheitsberechtigungen für jeden Vorgang überprüft. Für eine bessere Leistung können Sie die Java-Methodenhandles über diesen Link überprüfenhttps://docs.oracle.com/javase/8/docs/api/java/lang/invoke/MethodHandles.html.
Vielen Dank fürs Lesen.
Mit freundlichen Grüßen

![Was ist überhaupt eine verknüpfte Liste? [Teil 1]](https://post.nghiatu.com/assets/images/m/max/724/1*Xokk6XOjWyIGCBujkJsCzQ.jpeg)



































