早上剛到公司,吃早點過程中,被群裡這樣一個問題所吸引,如下圖所示:
後來自己就又想了想,感覺自己說的也不全對,於是想從程序角度來做一個佐證。
當然,在寫這篇文章之前,也是查閱了很多文章,關於這個問題的一些觀點,匯總如下:
講真這些概念性的東西,我是真的看的雲裡霧裡的,建議還是看維基百科或者教材吧。
我個人觀點,肯定是注解和裝飾器不是一回事的。
話不多說,還是直接上代碼,用實際案例來說話吧!
@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的一種設計模式。
你覺得呢?歡迎評論區留言討論!