Наскільки це варте, більшість мов сценаріїв (наприклад, Perl) та нестатичних мов компіляції (як Pick) підтримують автоматичне виконання часу динамічного рядка до (відносно довільних) перетворень об'єктів. Це МОЖЕ бути здійснено і на Java, не втрачаючи безпеки типу, а хороші речі, які набирають статично набрані мови, забезпечують БЕЗ неприємних побічних ефектів деяких інших мов, які роблять зло за допомогою динамічного кастингу. Приклад Perl, який дає деяку сумнівну математику:
print ++($foo = '99'); # prints '100'
print ++($foo = 'a0'); # prints 'a1'
У Java це краще досягається (IMHO) за допомогою методу, який я називаю "перехресне лиття". При перехресному литті відбиття використовується в кеш-пам'яті конструкторів та методів, які динамічно виявляються за допомогою наступного статичного методу:
Object fromString (String value, Class targetClass)
На жаль, жоден вбудований метод Java, такий як Class.cast (), не зробить цього для String to BigDecimal або String to Integer або будь-яке інше перетворення, де немає ієрархії підтримуваних класів. Зі свого боку, суть полягає в тому, щоб надати повністю динамічний спосіб досягти цього - для чого я не думаю, що попереднє посилання є правильним підходом - необхідність кодування кожного перетворення. Простіше кажучи, реалізація полягає в простому відкиданні від струни, якщо це легально / можливо.
Отже, рішення полягає в простому роздумі, який шукає публічних Членів:
STRING_CLASS_ARRAY = (новий клас [] {String.class});
а) Член-член = targetClass.getMethod (method.getName (), STRING_CLASS_ARRAY); б) Член учасника = targetClass.getConstructor (STRING_CLASS_ARRAY);
Ви виявите, що всі примітиви (Integer, Long тощо) та всі основи (BigInteger, BigDecimal тощо) та навіть java.regex.Pattern охоплюються цим підходом. Я використовував це із значним успіхом у виробничих проектах, де існує величезна кількість довільних вводів значення рядка, де потрібна була більш сувора перевірка. У цьому підході, якщо немає методу або коли метод викликається, викидається виняток (оскільки це нелегальне значення, таке як нечислове введення у BigDecimal або нелегальний RegEx для шаблону), що забезпечує перевірку, специфічну для цільовому класу властива логіка.
У цьому є деякі мінуси:
1) Потрібно добре розуміти рефлексію (це трохи складно і не для початківців). 2) Деякі класи Java та, власне, сторонні бібліотеки (несподівано) не закодовані належним чином. Тобто, існують методи, які беруть один рядовий аргумент як вхід і повертають екземпляр цільового класу, але це не те, що ви думаєте ... Розглянемо клас Integer:
static Integer getInteger(String nm)
Determines the integer value of the system property with the specified name.
Наведений вище метод насправді не має нічого спільного з цілими числами як об’єктами, що обертають примітиви ints. Відображення виявить це можливим кандидатом для створення цілого числа з рядка неправильно порівняно з декодом, значенням та членами конструктора - які всі підходять для більшості довільних перетворень рядків, коли ви дійсно не маєте контролю над введеними даними, а просто хочете знати, чи можна ціле число.
Щоб виправити вищезазначене, пошук методів, що викидають винятки, є гарним початком, оскільки недійсні вхідні значення, які створюють екземпляри таких об’єктів, повинні викидати виняток. На жаль, реалізації різняться залежно від того, оголошено винятки перевіреними чи ні. Integer.valueOf (String) викидає перевірений NumberFormatException, наприклад, але винятків Pattern.compile () не знайдено під час пошуку відбиття. Знову ж таки, не помилка цього динамічного підходу "перехресного лиття", я думаю, настільки ж, як дуже нестандартна реалізація оголошень про винятки в методах створення об'єктів.
Якщо хтось хоче отримати докладнішу інформацію про те, як було впроваджено вищезазначене, дайте мені знати, але я думаю, що це рішення набагато гнучкіше / розширюваніше і з меншим кодом, не втрачаючи при цьому хороших частин типової безпеки. Звичайно, завжди найкраще "знати свої дані", але, як багато хто з нас виявляє, ми іноді отримуємо лише некерований вміст і маємо зробити все можливе, щоб правильно його використовувати.
Ура.