Механизм излучения Java: во время работы программа имеет возможность получить все методы и свойства класса, а для любого объекта она может вызвать любой из его методов или получить его свойства.
Популярный анализ: файлы java должны быть скомпилированы в файлы .class, прежде чем они смогут быть загружены и использованы jvm, а данные .class объектов в jvm — это Class; если мы можем получить этот объект Class, мы можно получить Class> соответствующий тип объекта, а также методы и значения атрибутов, объявленные в типе; вы также можете создать объект соответствующего типа в соответствии с Class и оперировать объектом по очереди через Field и Метод
Введение в классы, связанные с Java
имя класса
описывать
Class<T>
Сущность, представляющая класс, представляющая класс или интерфейс в работающем приложении Java.
Field
Переменные-члены класса (переменные-члены также называются свойствами класса)
public Class<Example> getExampleByInstance(){
Example example = new Example();
// getClass是Object类里面的方法;《?》 是通配符
Class<?> clazz = example.getClass();
return (Class<Example>)clazz;
}
3 Получите класс с полным путем, указанным именем класса, через Class.forName
//获取所有的构造方法 / private public
public Constructor<?>[] getDeclaredConstructors()
//获取特定的构造方法 / private public
public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
//获取类的父类
public native Class<? super T> getSuperclass()
//获取类实现的接口
private Class<?>[] getInterfaces(boolean cloneArray)
//获取在类内定义的内部类或接口
public Class<?>[] getDeclaredClasses()
//获取所有的方法
public Method[] getDeclaredMethods() throws SecurityException
//根据方法名和参数获得特定的方法
public Method getDeclaredMethod(String name, Class<?>... parameterTypes)
//获取类型的定义的所有属性
public Field[] getFields() throws SecurityException
// 根据属性命名获得特定的Field
public Field getField(String name)
Метод обычно используемые методы работы
//获得方法的放回类型
public Class<?> getReturnType()
//获得方法的传入参数类型
public Class<?>[] getParameterTypes()
//obj是实例对象,args是方法,反过来由Method控制对象的方法调用
public Object invoke(Object obj, Object... args)
Общие методы работы в полевых условиях
//属性与obj相等则返回true
public boolean equals(Object obj)
//获得obj中对应的属性值
public Object get(Object obj)
//设置obj中对应属性值
public void set(Object obj, Object value)
Constructor
//根据传递的参数创建类的对象:initargs 构造方法参数
public T newInstance(Object... initargs)
1 Создайте объект в соответствии с классом
//方式一 clazz.newInstance()
Class<Example> clazz = Example.class;
Example example = clazz.newInstance();
//方式二 先获取再由Constructor:clazz.getConstructors()/getConstructor(...)
//再由Constructor.newInstance 方法构造对象
-----------------------------------------
public class Example {
private int value;
public Example(){ } // 如果只声明有参构造函数,clazz.newInstance()会报错
public Example(Integer value){ this.value = value; }
static public void main(String[] args) throws Exception{
Class<Example> clazz = Example.class;
//根据指定构造函数参数获取Constructor
Constructor<Example> constructor = clazz.getConstructor(Integer.class);
Example example = constructor.newInstance(100);
System.out.println(example.value);
}
}
2 Получить поле по классу и манипулировать свойствами экземпляра
public class Example {
private int value , count;
static public void main(String[] args) throws Exception{
Class<Example> clazz = Example.class;
//获取所有的属性,getField只能获取public的属性
Field[] fs = clazz.getDeclaredFields();
//根据名称获取指定 Field
Field value = clazz.getDeclaredField("value");
Example example = clazz.newInstance();
//使用反射机制可以打破封装性,导致了java对象的属性不安全
value.setAccessible(true); //setAccessible(true)让private的参数可赋值操作
//由Field反过去设置example的值
value.set(example,100);
System.out.println(example.value);
}
}
3 Получите метод по классу и вызовите метод экземпляра путем отражения
public class Example {
public static void main(String[] args) throws Exception {
Class<Example> clazz = Example.class;
Example example = clazz.newInstance();
Method[] methods = clazz.getDeclaredMethods();
//getDeclaredMethod和getMethod是:getMethod只能返回public的方法
Method method = clazz.getDeclaredMethod("hello", String.class);
method.setAccessible(true);
method.invoke(example, "cscw");
}
private void hello(String name) { System.out.println(name + " Hello!"); }
}
-----
cscw Hello!
Сценарии, в которых применяется механизм отражения
1 Динамическое расширение: Предполагается, что существует одна и та же группа классов, реализующих один и тот же интерфейс, а способ загрузки классов не ограничен. Когда нам нужны функции, реализованные этим конкретным классом, нам просто нужно загрузить файл .class и получить соответствующий объект Class. Экземпляр объекта может быть создан классом или конструктором; в соответствии с определением интерфейса можно получить метод в классе, а метод функции можно вызвать с отражением экземпляра.
2 IOC Spring реализован на основе механизма отражения
3 динамических прокси JDK
Отражение и динамические прокси JDK
Класс Proxy и интерфейс InvocationHandler предоставляются в составе пакета Java java.lang.reflect. С помощью этого класса и интерфейса можно создать динамический прокси-класс JDK или динамический прокси-объект.
public interface InvocationHandler {
//所有方法都会调用此代理方法
Object invoke(Object var1, Method var2, Object[] var3) throws Throwable;
}
public class Proxy implements Serializable{
...
//根据interfaces和InvocationHandler生成代理对象
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces, InvocationHandler h)
...
}
Динамический прокси JDK реализуется Proxy и InvocationHandler; прокси-объект должен реализовывать интерфейс. Прокси-объект генерируется Proxy и может быть преобразован в объект класса реализации OBJ интерфейса интерфейса. При вызове метода OBJ будет запущен InvocationHandler.invoke, а параметры, в свою очередь,прокси-объект,Объект метода,иПараметры, требуемые методом Метод. К методу вызова можно добавить расширенную логику, такую как операции регистрации;И может использовать технологию отражения для вызова метода прокси-объекта в вызове.
Пример
public class ExampleFactory<T> implements InvocationHandler{
private T target; //被代理对象
public T bind(T obj){
target = obj;
return (T)Proxy.newProxyInstance(obj.getClass().getClassLoader(),
obj.getClass().getInterfaces(),this);
}
/** Object o 是代理对象; o的方法调用 -> ExampleFactory.invoke
* invoke(...) -> 在invoke方法里面 反射调用代理对象方法+增强逻辑
*/
@Override
public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
//增强逻辑
System.out.println("log start");
//反射调用被代理对象方法
Object result = method.invoke(target,objects);
System.out.println("log end");
return result;
}
}
-----------
public interface Face {
void hello(String name);
}
---------
//被代理对象必须实现一个接口,并由接口方法对方提供功能
public class Example implements Face {
public void hello(String name) {
System.out.println(name + " Hello!");
}
public static void main(String[] args) {
//ExampleFactory<Face> 相当于一个中介人
ExampleFactory<Face> factory = new ExampleFactory<>();
//example 是代理对象
Face example = exampleProxy.bind(new Example());
example.hello("思婷");
}
}
-----
log start
思婷 Hello!
log end
Добро пожаловать на ошибку в тексте
Обратите внимание на публичный номер и общайтесь вместе