python 装饰器 与 java 的注解
代码效果
@spend
def run(a, b):
result = a + b
print(result)
return result
@spend
public class Run() {
public Run() {
System.out.println("run")
}
}
java 和 python 在某种程度上,长相相似,都是@符号 + 名称,放在类,或者函数上 在实际效果上,python 执行后,可以做到功能替换,功能增强,例如,在run 函数执行前后,打印 开始 和结束
代码如下def spend(func):
def fn(*args, **kwargs):
print("start")
data = func(*args, **kwargs)
print("end")
return data
return fn
@spend
def run(a, b):
result = a + b
print(result)
return result
run(1, 2)
结果如下start
3
end
而 java 的 @ 注解,不能提供任何形式的功能,只能给出一个标记,而该标记能保存在类的隐藏对象中,此时需要提供另一份代码,该代码识别出被标记的部件(类,方法,属性,甚至方法的参数),而后通过的 反射,运行该代码,并增强功能,以下是如何实现 python 中装饰器相似的功能
在函数前后打印开始和结束
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
@Anno1
class Run {
Integer a;
Integer b;
Run(int a, int b) {
this.a = a;
this.b = b;
}
int add() {
int result = a + b;
System.out.println(result);
return result;
}
}
@Retention(RetentionPolicy.RUNTIME)
@interface Anno1{
}
public class AnnotationTest{
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
// 获取对象
Class c = Run.class;
if (c.isAnnotationPresent(Anno1.class)) {
// 获取构造函数
Constructor d = c.getDeclaredConstructor(int.class, int.class);
// 实例化对象
Object o = d.newInstance(1, 2);
// 获取对象
Method r = c.getDeclaredMethod("add");
System.out.println("start");
// 执行函数
r.invoke(o);
System.out.println("end");
}
}
}
结果如下start
3
end
执行对比
python 执行函数 run,装饰器的内容,就自动被调用了,也不需要额外的代码去处理两者之间的关系 run(1, 2) # 直接运行原代码 即可,无需其他调用
java 如果直接执行 Run(1, 2).add(), 将不会有任何效果,只会打印 3
, 需要执行另一个类执行 // 获取对象
Class c = Run.class;
if (c.isAnnotationPresent(Anno1.class)) {
// 获取构造函数
Constructor d = c.getDeclaredConstructor(int.class, int.class);
// 实例化对象
Object o = d.newInstance(1, 2);
// 获取对象
Method r = c.getDeclaredMethod("add");
System.out.println("start");
// 执行函数
r.invoke(o);
System.out.println("end");
}
// 需要通过反射执行,并添加额外功能,实际的注解 @interface Anno1 无实际内容
这从原理上来说,python 通过在代码层面识别 @ 符号,自动运行装饰器内容,函数本身当作一个参数传递到装饰器中,实际执行的是装饰器
而java需要手动处理这一过程,首先加载所有可能的类,加载对象,识别载体,再进行封装运行
总结
python 的装饰器功能更为强大,使用也较为简单,通过@ 符号 可以增强相关函数或类功能 java 的注解,对于程序本身运行来说,无实际意义,需要通过其他代码识别并封装功能,以实现 代理,控制反转等特性 两种语言中,@ 都能实现功能增强,简化重复代码调用,优化代码观感,提升开发效率的作用