1. 程式人生 > >關於java編譯時註解你需要知道的二三事。解除你的顧慮!

關於java編譯時註解你需要知道的二三事。解除你的顧慮!

做Android開發。大家肯定會關心你的app的效能問題。不知道從何時開始。網上有流傳一句。不要使用註解。用註解會影響效能。這不能說錯。但是也不能說對。這裡普及一下關於註解的一些你需要知道的知識

網上常說的註解。基本是執行時註解。而所說的註解會影響效能。則是指的此型別的註解。因為執行時註解的解析。完全依賴於反射。而反射的效率。是比原生的慢的。特別是對於原先的老機型。本來配置就低。執行就卡。再使用過多註解。執行時去反射解析。就導致執行效率更慢了。這也就是網上老司機們所說的。註解會影響效能的主因了。但是其實這個基本可以不用去管。現在的手機執行得那麼溜。你就是用註解。那其實也影響不了多少效能的。

而對於編譯時註解。就不一樣了。我們都知道。我們寫的java檔案。會先經過編譯。將java檔案編譯成.class檔案。再對class檔案進行打包等一系列處理。生成apk。最終才執行到我們的手機上。所以編譯時註解。是在java編譯生成.class檔案這一步進行的操作。根本和我們的apk執行。沒半毛錢關係。所以效率問題也就無從說起了。

區分註解使用的是執行時。還是編譯時。我們只需要看註解的定義就行。如:

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.CLASS)
public @interface Params {
    ...
}
@Inherited
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Field {
    ...
}

@Retention是一種元註解。指定該註解的作用域。RUNTIME則是指的執行時註解。CLASS則是指的編譯時註解。還有一種叫做SOURCE。基本很難用到。此處就不說了。

編譯時註解對比執行時註解的優勢在於。它是在對程式進行編譯時期。根據你的註解處理器的邏輯。處理該註解。並生成相應的java檔案。提供給你呼叫。所以。使用編譯時註解。你程式執行時。是使用的生成的普通java類來提供呼叫。而不是像執行時註解那樣通過反射來呼叫。程式效能問題也就無從說起了。

下面來說一個對於編譯時註解。需要注意的問題。

我們都知道。在Android上的程式。有個64K的方法數限制。當然。網上也有說是64K的類數限制。具體是方法數還是類數咱不去管。但是肯定是有限制。所以。現在很多人對於引進一個庫。有個衡量的標準。就是看jar包的大小。方法數有多少。來衡量是否引進該lib。其實在此我想說。對於一般的庫你這樣來衡量無可厚非。但是編譯時註解的庫。就需要用另一種眼光來看了。

下面我先來說說對於編譯時註解框架引入專案的方式。對於Android Studio來說。這玩意引入很簡單。

首先。在專案根目錄的build.gradle中。加入apt框架

classpath 'com.neenbedankt.gradle.plugins:android-apt:1.4'

然後。在要使用編譯時註解框架的module中。應用apt外掛。加入編譯時註解框架引用

apply plugin: 'com.neenbedankt.android-apt'
dependencies {
    compile 'org.lzh.compiler.lib:processortool-api:0.6'
    apt 'org.lzh.compiler.lib:processortool-compiler:0.6'
}

compile 命令引用的是編譯時註解框架的api。即專案中需要使用的註解。都是來自於這種庫。
apt 命令是引用的編譯時註解框架的註解處理器lib。在程式編譯時。會呼叫該庫中的註解處理器去進行註解處理。生成符合邏輯的java檔案提供呼叫。

下面是Eclipse的用法。還是以上面的框架為例。

框架分為api和compiler兩部分。在專案上libs資料夾下。放置api的lib。
api

然後需要配置使用的註解處理器部分。游標放專案名上點選ALT + ENTER進入Properties找到Java compiler:
compiler config

1處開啟註解處理器開關。2處指定生成的java檔案所放置的路徑。
compiler config 2

1處啟用配置。2處新增處理處理器的jar包以及該註解處理器依賴的jar包。apply應用即可。這樣就配置完全了Eclipse下新增編譯時註解框架的流程。

然後註解處理器既然是生成了java類檔案。那麼就肯定需要我們自己能夠查閱該生成的檔案。對於Andorid Studio工程。生成的程式碼類的位置位於build資料夾下:
這裡寫圖片描述

圖中圈出來的即是生成的java類程式碼。根據使用的apt的版本不同。路徑也有所不同。此處生成於build/generated/source/apt目錄下。也有別的apt版本。生成的類位於build/source資料夾下。就這兩個地址。找找就知道了。

然後對於Eclipse工程。還記得Eclipse圖配置的第一張圖的第2處吧。有個.apt_generated的路徑名。生成的檔案就位於這個路徑下:
這裡寫圖片描述

好了。學會配置之後。再來說上面提到的問題。為什麼說對於編譯時註解的庫。我們需要用另一種眼光來判斷是否可以引進入專案中呢。

因為我們專案引進的其實只有api的lib。對於註解處理器的lib。那是提供給IDE使用的。並不會將compiler的jar打包到你的APK中去。所以看引入後方法量的增加數量。一個就是看api的lib所含有的方法數。一個就是被編譯處理之後。生成的程式碼數。這就是和一般的lib不一樣的地方。

來做個證明。
這裡寫圖片描述

圖中的兩個jar包即是編譯時註解框架的兩個lib。兩個apk。app-debug-apt.apk為引入了該框架的。app-debug-noapt.apk為沒有引用該框架的。從他們的大小就可以看出。打包時肯定沒有將compiler的jar包給打包進入 apk中。

當然。還有一種方式可以證明。即你在專案中使用的時候。你是完全不可以拿到compiler中的類。只能拿到api中所存在的類。並使用它。這個有興趣的也可以試試。

如果有對於編譯時註解感興趣的童鞋,推薦幾個網址以供學習: