Kami sering melihat hal -hal seperti "@Override", "@Target" dan seterusnya dalam kode java. Apa ini?
Di Java mereka adalah "anotasi".
Berikut ini adalah penjelasan ensiklopedia Baidu: java.lang.annotation.Retention dapat menginstruksikan kompiler untuk memperlakukan anotasi khusus Anda ketika Anda mendefinisikan pola anotasi. Kompiler akan meninggalkan informasi anotasi di arsip kelas, tetapi tidak dibaca oleh mesin virtual, tetapi hanya memberikan informasi ketika kompiler atau program alat berjalan.
Dengan kata lain, anotasi didasarkan pada file kelas, dan memiliki efek yang sama dengan makro dalam bahasa C.
Tidak ada jejak anotasi dalam file kelas.
Dasar anotasi adalah refleksi. Oleh karena itu, anotasi dapat dipahami sebagai konsep yang unik untuk Java.
1. Meta note
Dalam paket java.lang.annotation, empat "primitif" anotasi telah didefinisikan.
1).@Target, digunakan untuk mengklarifikasi jenis yang sedang dimodifikasi: (metode, bidang, kelas, antarmuka, dll.)
2).@Retensi, menggambarkan keberadaan annentation:
Anotasi RetentionPolicy.
Retensipolicy.class Kebijakan retensi default, anotasi akan ada dalam file bytecode kelas, tetapi tidak dapat diperoleh selama runtime.
Anotasi retensi.
3).@Didokumentasikan, secara default, anotasi tidak akan direkam di Javadoc, tetapi anotasi ini dapat digunakan untuk menunjukkan bahwa anotasi ini perlu dicatat.
4). @Meta-anotasi yang diwariskan adalah anotasi tag, dan @inHerited menjelaskan bahwa tipe beranotasi tertentu diwarisi.
Jika jenis anotasi menggunakan modifikasi @inherited digunakan untuk kelas, anotasi akan digunakan untuk subclass kelas.
2. Anotasi khusus
Paket com.joyfulmath.jvmexample.annnotaion; impor java.lang.annotation.elementType; impor java.lang.annotation.retention; import java.lang.annotation.RetensionPolicy; import java.lang.annotation.target;/*** @Autor. 13:36*/@target (elementType.field) @retention (retentionpolicy.runtime) public @interface fruitname {string value () default "";} Pertama -tama, anotasi umumnya membutuhkan modifikasi anotasi 2 meta:
@Target (elementType.field)
@Retention (retentionpolicy.runtime)
Fungsi spesifik telah dijelaskan di atas.
Semua anotasi akan memiliki bagian yang mirip dengan "func". Ini dapat dipahami sebagai parameter anotasi.
package com.joyfulmath.jvmexample.annnotaion;import com.joyfulmath.jvmexample.TraceLog;/*** @author deman.lu* @version on 2016-05-23 13:37*/public class Apple {@FruitName("Apple")String appleName;public void displayAppleName(){TraceLog.i(appleName);}} Log kode ini:
05-23 13: 39: 38.780 26792-26792/com.joyfulmath.jvMexample i/apple: displayapplename: null [at (apple.java:16)]]
Mengapa tugas tidak berhasil? Bagaimana Menetapkan File ke Anotasi "Apple"? Bagaimana melakukannya jika kompiler belum tahu.
3. Prosesor Anotasi
Kami juga membutuhkan prosesor untuk menjelaskan bagaimana anotasi bekerja, jika tidak, itu akan hampir sama dengan anotasi.
Melalui refleksi, konten anotasi dapat diperoleh:
Paket com.joyfulmath.jvmexample.annnotaion; import com.joyfulmath.jvmexample.tracelog; impor java.lang.reflect.field;/*** @author Deman.lu*@Versiz pada 2016-05-23? = ""; Field [] fields = clazz.getDeclaredFields (); untuk (lapangan lapangan: bidang) {if (field.isannotationpresent (fruitname.class)) {fruitname fruitname = field.getannotation (fruitname.class); fruitnamestr = fruitname.value ();Ini adalah penggunaan umum anotasi.
Analisis Kerangka Anotasi Android
Seperti yang dapat dilihat dari hal di atas, penggunaan kerangka kerja anotasi pada dasarnya membutuhkan refleksi.
Tetapi jika saya menggunakan kerangka anotasi dengan fungsi refleksi, maka saya mungkin juga menggunakannya secara langsung, itu lebih sederhana.
Jika ada mekanisme, ia dapat menghindari menulis banyak kode yang serupa, terutama selama pengembangan Android, sejumlah besar FindViewByID & OnClick dan acara lainnya sesuai.
Pola kode konsisten, tetapi kodenya berbeda. Pada saat ini, menggunakan kerangka anotasi dapat menghemat banyak waktu pengembangan, dan tentu saja, itu akan meningkatkan biaya overhead lainnya.
Berikut adalah contoh menggunakan Butterknife:
@BindString (r.string.login_error)
String LoginErrormessage;
Tampaknya sangat sederhana, ini adalah menetapkan string ke nilai awal yang sesuai dengan string res. Dengan cara ini Anda dapat menghemat waktu. Tentu saja ini hanya sebuah contoh.
Jika Anda menggunakan anotasi lain, Anda dapat menghemat banyak waktu pengembangan.
Mari kita lihat bagaimana itu diimplementasikan:
Paket Butterknife; impor android.support.annotation.stringres; impor java.lang.annotation.retention; impor java.lang.annotation.target; impor spesifikasi statis. <pr Pre> <code>* {@literal @} bindString (r.string.username_error) String usernameerrorText;* </code> </pe>*/ @retensi (kelas) @Target (bidang) public @interface bindstring {/** ID sumber daya string yang akan diikat. */@Stringres int value ();} BindString hanya memiliki satu parameter, nilai, yaitu menetapkan nilai ke @stringres.
Sama seperti di atas, di atas adalah di mana anotasi didefinisikan dan digunakan, tetapi penjelasan nyata dari anotasi adalah sebagai berikut: Butterknifeprocessor
Peta Pribadi <Typeelement, BindingClass> FindAndParsetargets (Roundenvironment Env)
Fungsi ini mencegat beberapa kode:
// Process each @BindString element.for (Element element : env.getElementsAnnotatedWith(BindString.class)) {if (!SuperficialValidation.validateElement(element)) continue;try {parseResourceString(element, targetClassMap, erasedTargetNames);} catch (Exception e) {logParsingError(element, BindString.class, e);}} Temukan semua elemen anotasi bindstring dan mulailah menganalisis:
private void parseresourcestring (elemen elemen, peta <typeelement, bindingClass> targetclassmap, atur <yypeelement> erasedTargetnames) {boolean haserror = false; typeelement endlosingElement = (typeelement) element.getEncLosingElement (); // Verifikasi tipe target. (!STRING_TYPE.equals(element.asType().toString())) {error(element, "@%s field type must be 'String'. (%s.%s)",BindString.class.getSimpleName(), enclosingElement.getQualifiedName(), element.getSimpleName());hasError = true;}// Verify common generated code pembatasan.haserror | = isInaccessibleageneratedCode (bindString.class, "bidang", elemen); haserror | = isBindingInwrongPackage (bindstring.class, elemen); if (haserror) {return;} // merakit informasi di bidang. element.getAnnotation (bindString.class) .value (); pengikat pengikatclass = getorcreateTeTargetClass (targetClassMap, EnclosingElement); fieldresource binding = baru fieldresourceBinding (id, nama, "getstring", false); bindingclass.addresource (mengikat); erasedTargetnames.add (inclosingElement);} Pertama verifikasi apakah elemen adalah jenis string.
// Merakit informasi di field.string name = element.getsimplename (). ToString (); int id = element.getAnnotation (bindString.class) .value ();
Dapatkan nama bidang, dan ID string.
terakhir
Peta <Typeelement, BindingClass> TargetClassMap
Deskripsi elemen dan anotasi disimpan satu per satu di peta.
@Override Proses Boolean Publik (set <? Extends Typeelement> Elements, Roundenvironment Env) {peta <Typeelement, BindingClass> TargetClassMap = FindandParsetargets (Env); for (MAP.Entry <Typeelement, BindingClass> Entry: TargetClassMap.entryset () {Typeelement, BindingClass- Entry: TargetClassMap.entryset () {) {Typeelement; entry.getValue (); coba {bindingclass.brewjava (). writeto (filer);} catch (ioException e) {error (typeelement, "tidak dapat menulis binder tampilan untuk type %s: %s", typeelement, e.getMessage ());}} return;} Di sinilah kerangka kerja anotasi dimulai, sebuah proses independen. Artikel ini tidak akan mempelajari detail spesifik, cukup jelaskan, ini adalah tempat yang didorong oleh kerangka kerja.
Dari informasi di atas, semua informasi anotasi disimpan di TargetClassMap.
Kode yang ditandai merah di atas harus menjadi inti dari kerangka anotasi.
Sejak Java SE5, Java telah memperkenalkan alat APT, yang dapat melakukan anotasi preprocess. Java SE6 mendukung prosesor anotasi yang diperluas.
Dan memprosesnya beberapa kali selama kompilasi. Kami dapat menggunakan prosesor anotasi khusus untuk menghasilkan kode Java baru sesuai dengan aturan ketika Java dikompilasi .
Javafile brewjava () {typespec.builder hasil = typespec.classbuilder (generatedClassName) .addmodifiers (publik); if (isFinal) {result.addmodifiers (Modifier.final);} else {result.addtypevariable (typevariablename.get ("t", targetTypeName));} typename targetType = isFinal? TargetTypeName: typevariablename.get ("t"); if (hasParentBinding ()) {result.Superclass (parameterizedTypeName.get (parentBinding.generatedClassName, targetType));} else {result.addsuperinterface (parameterizedTypeName.get (view_binder, targetype));} hasil. if (isGeneratingUnbinder ()) {result.addtype (createunbinderClass (targetType));} lain jika (! isFinal) {result.addmethod (createBindTotargetMethod ();} return javaFile.builder (generatedclassname.packagename () dari javaFile.builder (generatedclassname.packagename () dari javaFile.builder (GeneredClassname.packagename () dari JavaFile.builder (GeneratedClassname.packagename () dari JavaFile. Pisau mentega. Kunci dari bagian ini adalah membuat file baru.
Kemudian tulis konten yang relevan.