怪本身二,曾一度理解java的@和python的@是相似的概念,在刷了python後,回頭來再看java的註解各類懵逼,立下此文,以警後人,順便,題段詩:java
python代碼跑完後,冬雷滾滾夏雨雪。python
java項目看完時,家祭無忘告乃翁。spring
——————————————————————華麗的分割線———————————————————api
綜述:框架
python的@是一種語法糖,主要是對裝飾器的應用,更貼近函數式的概念。在裝飾器中是有具體的代碼邏輯,會改變裝飾對象的行爲和性質。裝飾器通常用在方法和類上函數
而java的註解僅僅是一種代碼層面上的註釋,僅僅是個代碼能看懂的標記,不會改變裝飾對象,實際的邏輯都是框架去作的。註解能夠用在方法,類,變量上。.net
對java產生誤解的地方就是,實際上python僅經過裝飾器就能實現AOP,而看java的時候還須要應用動態代理,去設計切點,鏈接點,通知,心想,怎麼搞得那麼複雜...還有註解的定義裏啥代碼也沒有是在搞毛,這個註解會幹嗎。然鵝其實人家啥也不幹。。。純粹是被python慣壞了設計
——————————————————————華麗的分割線———————————————————代理
python:對象
def timer(func):
def _timer(*args,**kw):
begin=datetime.now().microsecond
rs=func(*args,**kw)
end=datetime.now().microsecond
print("函數%s耗時%d"%(func.__name__,end=begin)) return rs return _timer
def foo():
print("function foo")
這樣即至關於foo=timer(foo),即函數爲變量
再調用foo(),至關於跑一下在運行原來的foo前有個begin後有個end一減算一下時間,便可知道foo的運行時間
那麼@timer這個函數加給任意一個函數,都能得出它的實際,就跟AOP同樣同樣的
——————————————————————華麗的分割線———————————————————
java:
java從jdk1.5後開始支持註解,僅僅是標記,閱讀的時候用人類語言理解就行。
在自定義註解時有幾個jdk提供的元註解
註解 | 說明 |
---|---|
@Target | 表示該註解能夠用在什麼地方,由ElementType枚舉定義 CONSTRUCTOR:構造器的聲明 FIELD:域聲明(包括enum實例) LOCAL_VARIABLE:局部變量聲明 METHOD:方法聲明 PACKAGE:包聲明 PARAMETER:參數聲明 TYPE:類、接口(包括註解類型)或enum聲明 ANNOTATION_TYPE:註解聲明(應用於另外一個註解上) TYPE_PARAMETER:類型參數聲明(1.8新加入) TYPE_USE:類型使用聲明(1.8新加入) PS:當註解未指定Target值時,此註解可使用任何元素之上,就是上面的類型 |
@Retention | 表示須要在什麼級別保存該註解信息,由RetentionPolicy枚舉定義 SOURCE:註解將被編譯器丟棄(該類型的註解信息只會保留在源碼裏,源碼通過編譯後,註解信息會被丟棄,不會保留在編譯好的class文件裏) CLASS:註解在class文件中可用,但會被VM丟棄(該類型的註解信息會保留在源碼裏和class文件裏,在執行的時候,不會加載到虛擬機(JVM)中) RUNTIME:VM將在運行期也保留註解信息,所以能夠經過反射機制讀取註解的信息(源碼、class文件和執行的時候都有註解的信息) PS:當註解未定義Retention值時,默認值是CLASS |
@Documented | 表示註解會被包含在javaapi文檔中 |
@Inherited | 容許子類繼承父類的註解 |
比方說spring中Controller
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Component public @interface Controller { String a() default 「」; }
@Controller(「/path」) public class testController { }
這裏有個快捷方式,就是說註解Controller裏只有一個參數a時,在使用時就不用a="/path",直接寫上就行