Получение "последнего посещенного поля" в Java Bean - PullRequest
0 голосов
/ 17 октября 2019

Для обработки исключений я хочу знать, какой геттер / поле в данном Бине породил Исключение. Чего я не хочу, так это пытаться / ловить каждый вызов getter или необходимость вручную отслеживать переменную String.

Могу ли я использовать для этого Java Reflections? Как я могу спроектировать Интерфейс, который реализует Бин?

Псевдокод, где я хочу, чтобы произошла обработка Исключения:

try {
            step.setNo(Long.parseLong(stepElement.getChildText("no", nameSpace)));
            step.setName(stepElement.getChildText("name", nameSpace));
            step.setDetail(stepElement.getChildText("detail", nameSpace));
            step.setEcuName(stepElement.getChildText("ecu-name", nameSpace));
}catch(Exception e){
            String fieldname = /*which field did throw? */
}

Часть фактического Бина:

public class CupProcStep {
    private long no;
    private String name;
    private String detail;
    private String ecuName;
    private String ecuVariant;
    private String diagnosticsId;
    private String errorText;
    private String stepResult;

public long getNo() {
        return no;
    }

    public void setNo(long no) {
        this.no = no;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getDetail() {
        return detail;
    }

    public void setDetail(String detail) {
        this.detail = detail;
    }

    public String getEcuName() {
        return ecuName;
    }

Имя поля, которое выдало исключение, например, "нет", "имя", "ecuName" и т. Д.

1 Ответ

1 голос
/ 17 октября 2019

Отражение - почти всегда неправильное решение.

Довольно просто сохранить имя соответствующего поля во время выполнения кода, который может выдать.

String fieldName = "no";
try {
    step.setNo(Long.parseLong(stepElement.getChildText("no", nameSpace)));
    fieldName = "name";
    step.setName(stepElement.getChildText("name", nameSpace));
    fieldName = "detail";
    step.setDetail(stepElement.getChildText("detail", nameSpace));
    fieldName = "ecu-name";
    step.setEcuName(stepElement.getChildText("ecu-name", nameSpace));
} catch (Exception exc) { // Be more specific!
    // fieldName available here
}

В этом случае мы можемЛучше убедиться, что мы не делаем ошибку копирования и вставки, просто записывая имя поля один раз.

String fieldName = "no";
try {
    step.setNo(Long.parseLong(stepElement.getChildText(fieldName, nameSpace)));
    fieldName = "name";
    step.setName(stepElement.getChildText(fieldName, nameSpace));
    fieldName = "detail";
    step.setDetail(stepElement.getChildText(fieldName, nameSpace));
    fieldName = "ecu-name";
    step.setEcuName(stepElement.getChildText(fieldName, nameSpace));
} catch (Exception exc) { // Be more specific!
    // fieldName available here
}

Некоторые помещают присваивание в вызов метода (getChildText(fieldName = "ecu-name",), но я 'Я не фанат побочных эффектов в подвыражениях.

Весь stepElement.getChildText(fieldName, nameSpace) является повторяющимся кодом и, вероятно, повторяется для других типов. Факторинг этого в классе оставлен как упражнение. Часть try-catch может быть разобрана с помощью идиомы Execute Around. В результате код клиента будет выглядеть следующим образом:

someObject.someFunction(element -> {
    step.setNo(Long.parseLong(element.get("no")));
    step.setName(element.get("name"));
    step.setDetail(element.get("detail"));
    step.setEcuName(element.get("ecu-name"));
});

Или, я думаю:

someObject
    .get("no",       step::setNo, Long::parseLong)
    .get("name",     step::setName)
    .get("detail",   step::setDetail)
    .get("ecu-name", step::setEcuName);

Существуют библиотеки ORM (Object-Relational Mapping), такие как JAXB, доступные длянекоторые типы форматов, но они становятся удивительно большими проектами - используйте существующую реализацию, если можете (если только вы не хотите брить этого яка).

...