Во-первых, статически загружаемые классы и динамически загружаемые классы.
-
Статически загруженный класс: new создает объект, который является статически загруженным классом и должен загружать все возможные классы во время компиляции.
-
Динамически загружаемые классы: загружаются во время выполнения
Отражение — это механизм динамической загрузки классов.
Преимущества и недостатки отражения
- Преимущества: определение типа во время выполнения, динамическая загрузка классов: повышение гибкости кода, возможность модификации функции без изменения исходного кода.
- Недостатки: есть узкое место в производительности: требуются проверки безопасности, отражение эквивалентно серии операций интерпретации, что медленнее, чем прямой код Java.
3. Понять суть дженериков через размышление
1. Обобщения вступают в силу только во время компиляции.
public class Test {
public static void main(String[] args) {
// 1、检验泛型擦除
List list1 = new ArrayList();
List<String> list2 = new ArrayList<String>();
System.out.println(list1.getClass()==list2.getClass());
}
}
Результат выполнения: правда
2. Генераторы коллекций предназначены для проверки типов и предотвращения неправильного ввода.
List<String> list2 = new ArrayList<String>();
list2.add("a");
list2.add(20);
Ошибка компиляции: int нельзя преобразовать в java.lang.String
3. Вы можете обойти общую проверку через отражение и добавить элементы разных типов
List<String> list2 = new ArrayList<String>();
list2.add("a");
Class<?> c = list2.getClass();
Method method = c.getDeclaredMethod("add",Object.class);
method.invoke(list2,20);
System.out.println(list2.size());
Результат бега: 2
Видно, что, поскольку проверка универсального типа действительна только во время компиляции, можно использовать принцип динамической загрузки отражения, чтобы обойти общую проверку и добавить в коллекцию элементы разных типов.
Применение отражения
1. Загрузите драйвер базы данных
// DriverManager.registerDriver(new com.mysql.cj.jdbc.Driver());
Class.forName("com.mysql.cj.jdbc.Driver");
2. Загрузите файлы конфигурации, такие как xml или свойства
-
Процесс загрузки bean-компонентов Spring в режиме конфигурации XML
- Загрузить все файлы конфигурации XML или свойств в программе в память
- Содержимое в xml или свойства анализируется в классе Java, и получается строка байт-кода соответствующего класса сущностей и информация о связанных атрибутах.
- Используйте механизм отражения для получения экземпляра класса класса на основе этой строки.
- Динамическая настройка свойств экземпляра
конфигурационный файл
className=com.example.reflectdemo.TestInvoke methodName=printlnState
класс сущности
public class TestInvoke { private void printlnState(){ System.out.println("I am fine"); } }
Разобрать содержимое конфигурационного файла
// 解析xml或properties里面的内容,得到对应实体类的字节码字符串以及属性信息 public static String getName(String key) throws IOException { Properties properties = new Properties(); FileInputStream in = new FileInputStream("D:\IdeaProjects\AllDemos\language-specification\src\main\resources\application.properties"); properties.load(in); in.close(); return properties.getProperty(key); }
Используйте отражение, чтобы получить экземпляр Class класса сущностей, создать экземпляр объекта класса сущностей и вызвать метод
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, IOException, ClassNotFoundException, InstantiationException { // 使用反射机制,根据这个字符串获得Class对象 Class<?> c = Class.forName(getName("className")); System.out.println(c.getSimpleName()); // 获取方法 Method method = c.getDeclaredMethod(getName("methodName")); // 绕过安全检查 method.setAccessible(true); // 创建实例对象 TestInvoke testInvoke = (TestInvoke)c.newInstance(); // 调用方法 method.invoke(testInvoke); }
результат операции: