Отличные боевые искусства Явы, размышления, хорошо провести время, это определенно стоит коллекционировать

Java задняя часть
Отличные боевые искусства Явы, размышления, хорошо провести время, это определенно стоит коллекционировать

предисловие

Ребята, вы знаете, что такое отражение в Java? Это не наоборот.

Отражение — это механизм Java, обычно также называемый механизмом отражения.В этой статье будет рассказано о том, что такое механизм отражения и как его использовать.

Пожалуйста, дайте сначала третью роту второму мастеру, а потом читайте дальше, спасибо.


Давайте посмотрим немного волшебства

public class Test {
    private static void changeStrValue(String str, char[] value) {
    	// 只要执行魔法代码就可以达到下面的效果
        // 施展魔法的代码稍后揭秘
    }

    public static void main(String[] args) {
        changeStrValue("abc", new char[]{'d','e','f'});

        String abc = "abc";
        System.out.println("abc");
        System.out.println(abc);
        System.out.println("abc".equals(abc));
    }
}

在这里插入图片描述

在这里插入图片描述

Это был первый раз, когда второй мастер увидел этот результат выполнения и подумал, что это очень интересно. Должно быть "abc", как оно может стать "def"?那是因为有一段神奇的代码,下文将会揭秘,只要接着读下去你就会明白了。

Каков рефлекторный механизм?

Механизм отражения Java означает, что в рабочем состоянии программы может быть сконструирован объект любого класса, класс, которому принадлежит любой объект, переменные-члены и методы любого класса, а также вызов любого объекта, свойства и методы. Эта функция динамического получения программной информации и динамического вызова объектов называется механизмом отражения языка Java. Отражение рассматривается как ключ к динамическим языкам.

Выше приведено объяснение энциклопедии. Это может быть немного абстрактно, а затем увидеть второй мастер для васобъявитьсяобъяснять.


Построить объект любого класса

В общем, если мы хотим создать объект класса, мы должны использовать ключевое слово new. Но в таких средах, как Spring, нам нужно только настроить имя класса, чтобы получить экземпляр класса. Как он это сделал?

import java.util.List;

public class Test {
    /**
     * 根据类名取得类实例
     * @author 二当家的白帽子 https://le-yi.blog.csdn.net/
     * @param className
     * @param <T>
     * @return
     * @throws InstantiationException
     * @throws IllegalAccessException
     * @throws ClassNotFoundException
     */
    public static <T> T getInstance(String className) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
        Class<T> clazz = (Class<T>) Class.forName(className);
        return clazz.newInstance();
    }

    public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
        List<String> list = getInstance("java.util.ArrayList");
        list.add("abc");
        list.add("def");

        for (String v : list) {
            System.out.println(v);
        }
    }
}

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


Знать, к какому классу принадлежит любой объект

import java.util.ArrayList;

public class Test {
     /**
     * 打印对象的类名
     * @author 二当家的白帽子 https://le-yi.blog.csdn.net/
     * @param o
     */
    public static void printClass(Object o) {
        System.out.printf(o.getClass().getName());
    }

    public static void main(String[] args) {
        printClass(new ArrayList<>());
    }
}

在这里插入图片描述


Понимать переменные-члены и методы любого класса

Мы вообще хотим использовать класс, мы должны сначала узнать какие там методы и свойства, сначала понять, а потом использовать. Но почему такой фреймворк, как Spring, может автоматически внедрить его для нас? Откуда он знает, какие свойства у нас есть в объекте?

import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class Test {
    /**
     * 打印类的属性
     * @author 二当家的白帽子 https://le-yi.blog.csdn.net/
     * @param clazz
     */
    public static void printFields(Class clazz) {
        System.out.println(clazz.getName() + "包含如下属性:");
        for (Field f : clazz.getDeclaredFields()) {
            System.out.println(f);
        }
    }

    /**
     * 打印类的方法
     * @author 二当家的白帽子 https://le-yi.blog.csdn.net/
     * @param clazz
     */
    public static void printMethods(Class clazz) {
        System.out.println(clazz.getName() + "包含如下方法:");
        for (Method m : clazz.getDeclaredMethods()) {
            System.out.println(m);
        }
    }

    public static void main(String[] args) {
        printFields(MyClass.class);
        printMethods(MyClass.class);
    }
}

class MyClass {
    private String name;

    public String getName() {
        return name;
    }

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

在这里插入图片描述


Вызов свойств и методов любого объекта

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

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class Test {
    /**
     * 调用一个对象的方法
     * @author 二当家的白帽子 https://le-yi.blog.csdn.net/
     * @param o
     * @param methodName
     * @throws NoSuchMethodException
     * @throws InvocationTargetException
     * @throws IllegalAccessException
     */
    public static void callMethod(Object o, String methodName) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        Method m = o.getClass().getDeclaredMethod(methodName);
        m.setAccessible(true);
        m.invoke(o);
    }

    /**
     * 修改一个对象的属性
     * @author 二当家的白帽子 https://le-yi.blog.csdn.net/
     * @param o
     * @param fieldName
     * @param value
     * @throws IllegalAccessException
     */
    public static void changeFieldValue(Object o, String fieldName, Object value) throws NoSuchFieldException, IllegalAccessException {
        Field f = o.getClass().getDeclaredField(fieldName);
        f.setAccessible(true);
        f.set(o, value);
    }

    public static void main(String[] args) throws InvocationTargetException, NoSuchMethodException, IllegalAccessException, NoSuchFieldException {
        MyClass o = new MyClass();

        // 修改任意属性,即使是私有的
        changeFieldValue(o, "name", "二当家的白帽子");

        // 调用任意方法,即使是私有的
        callMethod(o, "printName");
    }
}

class MyClass {
	// 私有属性,只可以调用set方法修改
    private String name;

    private void printName() {
        // 私有方法,只有本类自己的实例可以调用
        System.out.println("My name is " + name);
    }

    public String getName() {
        return name;
    }

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

在这里插入图片描述


Магия раскрыта

Пришло время разгадать, что такое магия на самом деле, и да, использование рефлексов тоже.

import java.lang.reflect.Field;

public class Test {
    /**
     * 修改字符串内部的值
     * @author 二当家的白帽子 https://le-yi.blog.csdn.net/
     * @param str
     * @param value
     */
    private static void changeStrValue(String str, char[] value) {
        try {
            Field f = str.getClass().getDeclaredField("value");
            f.setAccessible(true);
            f.set(str, value);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        changeStrValue("abc", new char[]{'d','e','f'});

        // 这里的"abc"字符串和上面调用changeStrValue的参数"abc"会指向同一块内存
        String abc = "abc";
        System.out.println("abc");
        System.out.println(abc);
        System.out.println("abc".equals(abc));
    }
}

Чтобы понять этот код, помимо механизма отражения, вам также необходимо понять, как java обрабатывает строки. «Пул строковых констант» выходит за рамки этой статьи и является отдельной темой, поэтому я не буду говорить об этом в этой статье.

Исходное содержимое строки — «abc», мы не можем изменить это содержимое в обычных условиях, поскольку String — это инвариантный класс. Но отражение Дафа может разрушить все табу.


конец

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