写在前面
早上刚到公司,被群里这样一个问题所吸引,如下图所示:
后来又想了想,感觉自己说的也不全对,于是想从程序角度来做一个佐证。
当然,在写这篇文章之前,也是查阅了很多文章,关于这个问题的一些观点,汇总如下:
讲真这些概念性的东西,我是真的看的云里雾里的,建议还是看维基百科或者教材吧。
我个人观点,肯定是注解和装饰器不是一回事的。
话不多说,还是直接上代码,用实际案例来说话吧!
@zhujie('参数')
都是@开头,注解、装饰器都可以自定义、都可以带参数、都可以被标注代码块之前执行。
示例代码如下:
@Override
public String toString() {
return "PlaylistInfo{" +
"curtime='" + curtime + '\'' +
", issmarter='" + issmarter + '\'' +
", xmusicnum='" + xmusicnum + '\'' +
", picurl=" + picurl +
", playlist=" + playlist +
", systemtime=" + systemtime +
'}';
}
@Override:重写的意思,不满意父类的可以自己在实现下,一般在编译阶段会对方法进行检查。
很明显,注解放在方法上方,仅负责编译、检查,并未对方法中的内容和该方法的功能做出改变。
实例代码如下:
class TestClass():
@property
def myValue(self):
return self.value
if __name__=="__main__":
TestClass.myValue = '装饰器呀!'
print (TestClass.myValue)
@property: 作为属性的意思
明显看出,装饰器直接改变了函数的功能。
由上得出,注解和装饰器的不同:
到这里,你是不是会觉得,他俩根本就不是一回事,因为根本不一样呀。
其实,在java中的注解和反射可以实现python里装饰器的效果。
是不是又蒙了?
别急,我们接着往后看!
注解的好处:在不改动源代码的基础上,对源代码实现新功能。如果有大面积代码需要改动同样功能,可以在方法或者类上面使用注解实现。
分别用python与Java方式,实现对程序计算的校验,把异常结果写到error.log文件中。
实例代码如下:
# 此时就是作为写入错误结果使用
def check(func):
def wrapper(*args, **kwargs):
try:
res = func(*args, **kwargs)
return res
except Exception as err:
with open("error.log", mode="at", encoding='utf-8') as f:
f.write("start".center(50, '*'))
f.write('\n')
f.write(str(func))
f.write('\n')
f.write(str(err.__class__))
f.write('\n')
f.write("end".center(50, '*'))
f.write('\n')
return wrapper
@check
def add(a, b):
print(a + b)
@check
def divide(a, b):
print(a / b)
add(50, 50)
divide(100, 0)
示例代码如下:
public class Calculator {
@Check
public void add() {
System.out.println(50 + 50);
}
@Check
public void divide() {
System.out.println(100 / 0);
}
}
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Check {
}
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Method;
public class CheckDemo {
public static void main(String[] args) throws IOException {
Calculator test = new Calculator();
Class<? extends Calculator> c = test.getClass();
Method[] methods = c.getMethods();
BufferedWriter bw = new BufferedWriter(new FileWriter("input.txt"));
for (Method m :
methods) {
if (m.isAnnotationPresent(Check.class)) {
try {
m.invoke(test);
} catch (Exception e) {
bw.newLine();
bw.write(e.getCause().getMessage()+"----");
bw.newLine();
bw.write(String.valueOf(e.getCause().getClass()));
}
}
}
bw.flush();
bw.close();
}
}
分别运行各自编译器,结果如下图所示:
由上可知,Java中的注解和反射可以实现python里装饰器的效果。
输入用户密码,返回用户信息接口
示例代码如下:
from flask import Flask
import json
from flask import request
app = Flask(__name__) #启动
@app.route('/rongrong/getUserInfo',methods=['GET']) #请求路径、请求方式
def login():
username = request.args.get("username") #获取url中参数“username”的值
password = request.args.get("password") #获取url中参数“password”的值
if username and password: #如果传入了值为真打印下面信息
data = json.dumps({
"username":username,
"password":password,
"code":"200",
"message":"成功"
},ensure_ascii=False) #解决中文乱码问题
else: #如果传参为空打印下面信息
data = json.dumps({
"message":"请传递参数"
},ensure_ascii=False)
return data
if __name__ == "__main__":
app.run() #运行
示例代码如下:
@RequestMapping(value = "/rongrong/getUserInfo", method = RequestMethod.GET)
public Result<List<Student>> findStudentByName(HttpServletRequest request) {
String username = request.getParameter("username");
String password = request.getParameter("password");
JsonRootBean jsonRootBean = new JsonRootBean();
jsonRootBean.setUsername(username);
jsonRootBean.setPassword(password);
jsonRootBean.setCode("200");
jsonRootBean.setMessage("成功");
Result result = ResultUtils.success(jsonRootBean);
return result;
}
python结果:
Java结果:
Python的装饰器很单一,就是通过一层壳对一个函数的行为进行修饰,而@decorator_func 只是一个语法糖,用以美化装饰器的写法。
Java中的注解则不同,它是从语言层面为代码中的类,函数,字段增加一些运行时可以读到的元数据,而注解的提供者要在运行时对这些元数据进行读取,并做相应的处理。
笔者才疏学浅,写这篇文正完全是出于技痒,自然也是查阅了大量文章,才有此文。
以下内容仅代表个人观点:
通过各种手段可以让他们变成一回事儿,所以就结果而言,没错,可以把他们当成是一回事儿。
换句话说,有时候感觉装饰器更像是Java的一种设计模式。
你觉得呢?欢迎评论区留言讨论!