python 中的@装饰器与java中的注解对比

python 装饰器 与 java 的注解

代码效果

  • python
@spend
def run(a, b):
    result = a + b
    print(result)
    return result
  • java
@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
      

执行对比

  1. python 执行函数 run,装饰器的内容,就自动被调用了,也不需要额外的代码去处理两者之间的关系
    	run(1, 2)  # 直接运行原代码 即可,无需其他调用
    
  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 无实际内容
    
  3. 这从原理上来说,python 通过在代码层面识别 @ 符号,自动运行装饰器内容,函数本身当作一个参数传递到装饰器中,实际执行的是装饰器
    • 而java需要手动处理这一过程,首先加载所有可能的类,加载对象,识别载体,再进行封装运行

总结

  1. python 的装饰器功能更为强大,使用也较为简单,通过@ 符号 可以增强相关函数或类功能
  2. java 的注解,对于程序本身运行来说,无实际意义,需要通过其他代码识别并封装功能,以实现 代理,控制反转等特性
  3. 两种语言中,@ 都能实现功能增强,简化重复代码调用,优化代码观感,提升开发效率的作用

你可能感兴趣的:(python,java,开发语言)