Библиотека нуклидов перечисление


Я в настоящее время разрабатывает программу в области ядерной физики и я хотел бы иметь простой доступ ко всем нуклидов.

Технические данные :

  • Поскольку данные являются статическими, я хочу, чтобы они были жестко. (значит, без внешнего файла для чтения) -> перечисление представляется хорошей отправной точкой, затем.
  • Каждого нуклида должны нести :
    1. Атомным номером один
    2. Массовое число Z
    3. Число изомерных я
    4. Половину времени распада
    5. Режим естественного распада
  • Доступ через API должен быть очень простой, что-то вроде Nuclides.get(Z,A,I) / Nuclide.get("C14") или эквивалент рекомендуется.
  • Количество нуклидов почти 3000.

Я попробовал это, но он использует отражение для метода GET (Пример Nuclide.get("Li10"))и это, кажется, перебор :

public class Nuclide {
    public static String[] Symbols = {"H", "He", "Li", "Be", "B", "C", "N", "O", "F", "Ne", "Na", "Mg", "Al", "Si", "P", "S", "Cl", "Ar", "K", "Ca", "Sc", "Ti", "V", "Cr", "Mn", "Fe", "Co", "Ni", "Cu", "Zn", "Ga", "Ge", "As", "Se", "Br", "Kr", "Rb", "Sr", "Y", "Zr", "Nb", "Mo", "Tc", "Ru", "Rh", "Pd", "Ag", "Cd", "In", "Sn", "Sb", "Te", "I", "Xe", "Cs", "Ba", "La", "Ce", "Pr", "Nd", "Pm", "Sm", "Eu", "Gd", "Tb", "Dy", "Ho", "Er", "Tm", "Yb", "Lu", "Hf", "Ta", "W", "Re", "Os", "Ir", "Pt", "Au", "Hg", "Tl", "Pb", "Bi", "Po", "At", "Rn", "Fr", "Ra", "Ac", "Th", "Pa", "U", "Np", "Pu", "Am", "Cm", "Bk", "Cf", "Es", "Fm", "Md", "No", "Lr", "Rf", "Ha", "Sg", "Ns", "Hs", "Mt", "Ds","Rg"};
    private String symbol;
    private int Z;
    private int A;
    private int isomericState;
    private String reactions;
    private double decayTime;

    private Nuclide() {}
    private Nuclide(String symbol, int A, String isomericState, double decayTime, String reactions) {
        this.symbol = symbol;
        this.A = A;
        this.isomericState = determineIsomericState(isomericState);
        this.Z = determineZ(symbol);

    }

    private static int determineZ(String symbol) {
        for (int i = 0; i < Symbols.length; i++) {
            if (symbol.equals(Symbols[i])) return i + 1;
        }
        return -1;
    }
    private int determineIsomericState(String isomericState) {
        if (isomericState.equals("gs")) this.isomericState = 0;
        else if (isomericState.equals("m")) this.isomericState = 1;
        else if (isomericState.equals("m2")) this.isomericState = 2;
        else if (isomericState.equals("m3")) this.isomericState = 3;
        else {
            System.out.println(isomericState + " isomere inconu");
            this.isomericState = -1;
        }
        return this.isomericState;
    }
    public static Nuclide get(String name) {
        char[] nameArray = name.toCharArray();
        String symbol = "";
        String A = "";
        String I = "";
        boolean isSymbolRead = false, isARead = false;
        for (char c : nameArray) {
            if (Character.isLetter(c) && !isSymbolRead) {symbol += c;}
            if (Character.isDigit(c) && !symbol.equals("") && !isARead) {
                isSymbolRead = true;
                A += c;
            }
            if (c == 'm' && isSymbolRead) {isARead = true;}
            if (Character.isDigit(c) && isSymbolRead && isARead) {I += c;}
        }
        String classPath = Nuclide.class.getCanonicalName();
        try {
            Class<?> c = Class.forName(classPath + "$" + symbol);
            Object[] objects = c.getEnumConstants();
            for (Object obj : objects) {
                if (obj.toString().equals(symbol + A + I)) {
                    Method method = obj.getClass().getDeclaredMethod("getNuclide");
                    Nuclide nuclide = (Nuclide) (method.invoke(obj));
                    return nuclide;
                }
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        return null;
    }


//Then all enums

public enum n {
        n1(1, "gs", 6.146000e+02, "b-:1.000000e+02");
        private Nuclide nuclide;
        n(int A, String isomericState, double decayTime, String reactions) {this.nuclide = new Nuclide("n", A, isomericState, decayTime, reactions);}
        public Nuclide getNuclide() {return nuclide;}
    }
    public enum H {
        H1(1, "gs", 0.000000e+00, "s"),
        H2(2, "gs", 0.000000e+00, "s"),
        H3(3, "gs", 3.891050e+08, "b-:1.000000e+02"),
        H4(4, "gs", 1.000000e-22, "n:1.000000e+02"),
        H5(5, "gs", 8.000000e-23, "n:1.000000e+02"),
        H6(6, "gs", 3.200000e-22, "nn:1.000000e+02");
        private Nuclide nuclide;
        H(int A, String isomericState, double decayTime, String reactions) {this.nuclide = new Nuclide("H", A, isomericState, decayTime, reactions);}
        public Nuclide getNuclide() {return nuclide;}
    }
    public enum He {
        He3(3, "gs", 0.000000e+00, "s"),
        He4(4, "gs", 0.000000e+00, "s"),
        He5(5, "gs", 7.600000e-22, "n:1.000000e+02"),
        He6(6, "gs", 8.081000e-01, "b-:1.000000e+02"),
        He7(7, "gs", 2.900000e-21, "n:1.000000e+02"),
        He8(8, "gs", 1.220000e-01, "b-:8.800000e+01,b-n:1.200000e+01"),
        He9(9, "gs", 7.000000e-21, "n:1.000000e+02"),
        He10(10, "gs", 2.700000e-21, "nn:1.000000e+02");
        private Nuclide nuclide;
        He(int A, String isomericState, double decayTime, String reactions) {this.nuclide = new Nuclide("He", A, isomericState, decayTime, reactions);}
        public Nuclide getNuclide() {return nuclide;}
    }
    public enum Li {
        Li4(4, "gs", 9.100000e-23, "p:1.000000e+02"),
        Li5(5, "gs", 3.000000e-22, "p:1.000000e+02"),
        Li6(6, "gs", 0.000000e+00, "s"),
        Li7(7, "gs", 0.000000e+00, "s"),
        Li8(8, "gs", 8.380000e-01, "b-a:1.000000e+02"),
        Li9(9, "gs", 1.783000e-01, "b-:5.050000e+01,b-n:4.950000e+01"),
        Li10(10, "gs", 2.000000e-21, "n:1.000000e+02"),
        Li11(11, "gs", 8.590000e-03, "b-:9.100000e+00,b-n:8.490000e+01,b-n:4.100000e+00,b-n:1.900000e+00"),
        Li12(12, "gs", 1.000000e-08, "n:1.000000e+02");
        private Nuclide nuclide;
        Li(int A, String isomericState, double decayTime, String reactions) {this.nuclide = new Nuclide("Li", A, isomericState, decayTime, reactions);}
        public Nuclide getNuclide() {return nuclide;}
    }

// ...
}

Я нашел еще один пост, который только для элемента table. Я не поняла смысла в отдельный статический класс держатель !?

Есть ли лучший способ для определения Нуклидного класса (без рефлексии) или я должен придерживаться этого определения ? Спасибо



115
1
задан 8 февраля 2018 в 05:02 Источник Поделиться
Комментарии
1 ответ

Жаль, что есть ограничения, чтобы избежать использования внешнего файла ресурсов. Это будет более гибким для чтения данных из других источников, таким образом отделяя бетон от его абстрактное представление в коде. И в случае исправления/обновление не перестроить приложение будет необходимо.

Ок, давайте оставаться на требование, согласно которому данные должны быть жестко заданы.

Прежде чем замечания по поводу выбора дизайна, вот некоторые замечания об улучшения текущего кода.

Частные Поля

Поскольку информация, завернутый в Nuclide в основном prepresents константы, все поля должны быть окончательными.

private final String symbol;
private final int z; // lower case and should better be called "massNumber"
private final int a; // lower case and should better be called "atomicNumber"
private final int isomericState;
private final String reactions;
private final double decayTime;

Кстати, static Sympols должны быть в верхнем регистре.

determineZ

Это нормально для цикла, но оператор return должен быть заменен

throw new IllegalArgumentException("Failed to determine Z, invalid symbol: " + symbol);

Это предотвращает от необходимости неверные данные, так как все предполагаемые символы, как правило, объявляются в SYMBOLS.

determineIsomericState


  • Несколько if-else-if оверкиль, этот случай можно рассматривать по аналогии с determineZ способ: объявить константный массив с ожидаемыми изометрические государства и вернуть i + 1 той, что согласована в петлю.

  • isomericState Реф должен не назначаться внутрь этот метод, только int значение должно быть возвращено.

Nuclide get(String)

Ну, содержание этого метода действительно слишком сложны, и в первую очередь должна быть разделена на две части (специальные методы): 1) Разбираем name ARG в целях извлечения symbol, a и i; 2) вызвать getNuclide метод целевого объекта.

nameпарсинг

Такой подход с какой-то специальной парсер особенно трудно проверить, из-за высокой сложности if условия.

Существует намного более простой способ реализовать это: регулярные выражения! Похоже name арг, как ожидается, будет что-то вроде "He7m2". Соответствующее регулярное выражение будет ^([A-Za-z]+)(\d+)m(\d+)$. Значения в сопоставляемых группах соответственно symbol, a и i. Если name не соответствует выражению, это хороший повод, чтобы бросить еще один ИАЭ.

getNuclideвызов

Использование отражения-это недостаток выбора enums, чтобы обернуть данные.

Если вы должны держать enumы, возможно, упрощение, избегая жестокой вызова метода по имени. Он состоит в следующем:

1) создать интерфейс, который обеспечивает доступ к целевым методом:

interface NuclideAware {
Nuclide getNuclide();
}

2) Сделать каждого перечислимого реализовать этот интерфейс, добавив implements NuclideAware к заголовкам. Этот метод уже реализован в каждой из них.

3) уменьшить отраженный вызов на следующее:

final String targetNuclide = symbol + A + I;
try {
Class<?> c = Class.forName(classPath + "$" + symbol);
Object[] objects = c.getEnumConstants();
for (Object obj : objects) {
if (obj.toString().equals(targetNuclide)) {
return ((NuclideAware) obj).getNuclide();
}
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}

Но это по-прежнему остается довольно жестокой и жесткой. Там должен быть гораздо более гибким способом, чтобы реализовать все это, используя больше возможностей ООП.

Поскольку этот ответ будет гораздо дольше, чем вопрос, я предлагаю делать работу в два этапа. Если вы найдете полезные замечания, я писал здесь, пожалуйста, приложите их и публикуем следующий вопрос, где мы будем обсуждать дальнейшие улучшения.

1
ответ дан 9 февраля 2018 в 12:02 Источник Поделиться