摘要:而這可以通過注解辦到,在代碼中以指令語言的形式化方法來為代碼提供更多信息。有注解的說明這個(gè)成員變量是一個(gè)列名,然后根據(jù)注解信息來生成相應(yīng)的語句。也就是說把注解信息提取了出來。
注解是向代碼中添加信息的一種方法,并且在之后還可以使用這些數(shù)據(jù)
就比如這個(gè)方法是用來剝香蕉的,但是我們看就是一串代碼,我們沒辦法在代碼里寫一段指令說“我這個(gè)程序是用來剝香蕉的”,當(dāng)然除了注釋。而這可以通過注解辦到,在代碼中以Java指令語言的形式化方法來為代碼提供更多信息。
package tij.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; public class AnnotationTest { } class Testable { void execute() { System.out.println("Executing..."); } @Test void testExecute() { execute(); } } @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @interface Test {}
@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @interface UseCase { public int id(); public String description() default "no description"; } class PasswordUtils { @UseCase(id = 47, description = "Passwords must contain at least one numeric") public boolean validatePassword(String password) { return (password.matches("w*dw*")); } @UseCase(id = 48) public String encryptPassword(String password) { return new StringBuilder(password).reverse().toString(); } @UseCase(id = 49, description = "New passwords can"t equal previously used ones") public boolean checkForNewPassword(ListprevPasswords, String password) { return !prevPasswords.contains(password); } }
這是個(gè)注解的簡(jiǎn)單應(yīng)用,通過這些注解,我們?cè)陂喿x代碼的時(shí)候可以更清晰的獲取更多信息
2.元注解 二、編寫注解處理器package tij.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collections; import java.util.List; public class AnnotationTest { public static void trackUseCases(ListuseCases, Class> cl) { for (Method m : cl.getDeclaredMethods()) { UseCase uc = m.getAnnotation(UseCase.class); if (uc != null) { System.out.println( "Found Use Case:" + uc.id() + " " + uc.description()); } useCases.remove(new Integer(uc.id())); } for (int i : useCases) { System.out.println("Warning:Missing use case-" + i); } } public static void main(String[] args) { List useCases = new ArrayList (); Collections.addAll(useCases, 47, 48, 49, 50); trackUseCases(useCases, PasswordUtils.class); } } @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @interface UseCase { public int id(); public String description() default "no description"; } class PasswordUtils { @UseCase(id = 47, description = "Passwords must contain at least one numeric") public boolean validatePassword(String password) { return (password.matches("w*dw*")); } @UseCase(id = 48) public String encryptPassword(String password) { return new StringBuilder(password).reverse().toString(); } @UseCase(id = 49, description = "New passwords can"t equal previously used ones") public boolean checkForNewPassword(List prevPasswords, String password) { return !prevPasswords.contains(password); } }
因?yàn)樽⒔馐荍ava語言之一,也正是因?yàn)橛锌梢宰x取注解的方法,所以注解才強(qiáng)于直接注釋。
在上面的例子中我們可以看出,可以將各個(gè)方法的注解信息讀取出來
就像之前的id和dicription一樣,這叫做注解元素,可用類型如下:
就是注解元素必須有一個(gè)確認(rèn)的值,沒有不行,空也不行,那假如就是空的就是不存在咋整呢。
所以我們只能定義一些特殊的值來解決
@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @interface SimulatingNull{ public int id() default -1; public String decription() default ""; }3.生成外部文件
package tij.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; public class AnnotationTest { public static void main(String[] args) {} } @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @interface DBTable { public String name() default ""; } @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @interface Constraints { boolean primaryKey() default false; boolean allowNull() default true; boolean unique() default false; } @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @interface SQLString { int value() default 0; String name() default ""; Constraints constraints() default @Constraints; } @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @interface SQLInteger { String name() default ""; Constraints constraints() default @Constraints; } @DBTable(name = "MEMBER") class Member { @SQLString(30) String firstName; @SQLString(50) String lastName; @SQLString Integer age; @SQLString(value = 30, constraints = @Constraints(primaryKey = true)) String handle; static int memberCount; public String getFirstName() { return firstName; } public String getLastName() { return lastName; } public Integer getAge() { return age; } public String getHandle() { return handle; } public String toString() { return handle; } }
其實(shí)這段代碼很好的舉了個(gè)注解運(yùn)用的例子,
@Target(ElementType.TYPE)這個(gè)東西告訴編譯器,這條注解要用在類聲明上,就像DBTable一樣,這個(gè)注解放在了class Member之前
@Target(ElementType.FIELD)這個(gè)東西告訴編譯器,這條注解要放在域聲明之前。
另外,如果只有一個(gè)名字叫做value的元素需要賦值的時(shí)候,就不需要“key=value”這種賦值,不用key,默認(rèn)的。
不過,為了每個(gè)類型都設(shè)計(jì)一個(gè)注解未免太麻煩了,我們可以這么做
enum Type{ String,Integer,Float; } @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @interface TableColumn { Type type() default Type.String; Constraints constraints() default @Constraints; }
這樣就用一個(gè)注解就可以套上各種類型,不過這樣就不能針對(duì)不同類型設(shè)計(jì)具有針對(duì)性的注解元素了
我們還可以為一個(gè)元素打上倆注解,這沒什么,就是亂了點(diǎn)
4.注解不支持繼承不讓繼承,別逼逼
5.實(shí)現(xiàn)處理器package tij.annotation; import java.lang.annotation.Annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List; public class AnnotationTest { public static void main(String[] args) { DBTable dbTable = Member.class.getAnnotation(DBTable.class); String tableName = dbTable.name(); ListcolumnDefs = new ArrayList (); for (Field field : Member.class.getFields()) { System.out.println(field.getName()); String columnName = null; Annotation[] anns = field.getDeclaredAnnotations(); if (anns.length < 1) continue;// 沒檢測(cè)得到注解,說明這個(gè)參數(shù)并不是一個(gè)數(shù)據(jù)庫表的列 if (anns[0] instanceof SQLInteger) { SQLInteger sInt = (SQLInteger) anns[0]; if (sInt.name().length() < 1) columnName = field.getName(); else columnName = sInt.name(); columnDefs.add(columnName + " INT" + getConstraints(sInt.constraints())); } if (anns[0] instanceof SQLString) { SQLString sString = (SQLString) anns[0]; if (sString.name().length() < 1) columnName = field.getName(); else columnName = sString.name(); columnDefs.add(columnName + " VARCHAR(" + sString.value() + ")" + getConstraints(sString.constraints())); } } StringBuilder createCommand = new StringBuilder( "CREATE TABLE " + tableName + "("); for (String columnDef : columnDefs) { createCommand.append(" " + columnDef + ","); } String tableCreate = createCommand.substring(0, createCommand.length() - 1) + ");"; System.out.println("Table Creation SQL for" + Member.class + " is: " + tableCreate); } private static String getConstraints(Constraints con) { String constraints = ""; if (!con.allowNull()) constraints += " NOT NULL "; if (con.primaryKey()) constraints += " PRIMARY KEY "; if (con.unique()) constraints += " UNIQUE "; return constraints; } } @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @interface DBTable { public String name() default ""; } @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @interface Constraints { boolean primaryKey() default false; boolean allowNull() default true; boolean unique() default false; } @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @interface SQLString { int value() default 0; String name() default ""; Constraints constraints() default @Constraints; } @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @interface SQLInteger { String name() default ""; Constraints constraints() default @Constraints; } @DBTable(name = "MEMBER") class Member { @SQLString(30) public String firstName; @SQLString(50) public String lastName; @SQLString public Integer age; @SQLString(value = 30, constraints = @Constraints(primaryKey = true)) public String handle; static int memberCount; public String getFirstName() { return firstName; } public String getLastName() { return lastName; } public Integer getAge() { return age; } public String getHandle() { return handle; } public String toString() { return handle; } }
這段代碼超棒,實(shí)際的告訴你這些注解到底怎么用,有什么用。有注解的說明這個(gè)成員變量是一個(gè)列名,然后根據(jù)注解信息來生成相應(yīng)的SQL語句。也就是說把注解信息提取了出來。
三、使用apt處理注解說實(shí)話,沒看懂
package tij.annotation; import java.io.IOException; import java.io.PrintWriter; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Set; import com.sun.mirror.apt.AnnotationProcessor; import com.sun.mirror.apt.AnnotationProcessorEnvironment; import com.sun.mirror.apt.AnnotationProcessorFactory; import com.sun.mirror.declaration.AnnotationTypeDeclaration; import com.sun.mirror.declaration.MethodDeclaration; import com.sun.mirror.declaration.ParameterDeclaration; import com.sun.mirror.declaration.TypeDeclaration; public class AnnotationTest { public static void main(String[] args) {} } @ExtractInterface("IMultipier") class Multiplier { public int multiply(int x, int y) { int total = 0; for (int i = 0; i < x; i++) { total = add(total, y); } return total; } private int add(int x, int y) { return x + y; } public static void main(String[] args) { Multiplier m = new Multiplier(); System.out.println("11*16=" + m.multiply(11, 16)); } } @Target(ElementType.TYPE) @Retention(RetentionPolicy.SOURCE) @interface ExtractInterface { public String value(); } class InterfaceExtractorProcessor implements AnnotationProcessor { private final AnnotationProcessorEnvironment env; private ArrayList四、沒看懂= =真的 五、基于注解的單元測(cè)試interfaceMethods = new ArrayList (); public InterfaceExtractorProcessor(AnnotationProcessorEnvironment env) { this.env = env; } @Override public void process() { for (TypeDeclaration typeDec1 : env.getSpecifiedTypeDeclarations()) { ExtractInterface annot = typeDec1 .getAnnotation(ExtractInterface.class); if (annot == null) break; for (MethodDeclaration m : typeDec1.getMethods()) if (m.getModifiers().contains(Modifier.STATIC) && !(m.getModifiers().contains(Modifier.STATIC))) interfaceMethods.add(m); if (interfaceMethods.size() > 0) { try { PrintWriter writer = env.getFiler() .createSourceFile(annot.value()); writer.println("package" + typeDec1.getPackage().getQualifiedName() + ";"); writer.println("public interface " + annot.value() + " {"); for (MethodDeclaration m : interfaceMethods) { writer.print(" public "); writer.print(m.getReturnType() + " "); writer.print(m.getSimpleName() + " ("); int i = 0; for (ParameterDeclaration parm : m.getParameters()) { writer.print(parm.getType() + " " + parm.getSimpleName()); if (++i < m.getParameters().size()) writer.print(", "); } writer.println(");"); } writer.println("}"); writer.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } } class InterfaceExtractorProcessorFactory implements AnnotationProcessorFactory { @Override public AnnotationProcessor getProcessorFor( Set atds, AnnotationProcessorEnvironment env) { return new InterfaceExtractorProcessor(env); } @Override public Collection supportedAnnotationTypes() { return Collections.singleton("annotations.ExtractInterface"); } @Override public Collection supportedOptions() { return Collections.emptySet(); } }
QNMLGB的不看了老子
end
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/70182.html
摘要:迭代器解決了這個(gè)問題。刪除后于是我們可以寫一個(gè)方法,接受一個(gè)類型,然后讓他調(diào)用方法,這就不需要考慮這個(gè)是個(gè)還是了,也就是說,可以將遍歷容器的操作與序列底層的結(jié)構(gòu)分離,迭代器統(tǒng)一了對(duì)容器類的訪問方式。十二和兩種遍歷的方法,與迭代器方法。 一、泛型和類型安全的容器 package tij.hoding; import java.util.ArrayList; public class ...
摘要:四上的操作看五格式化輸出運(yùn)用和語言很相似和是等價(jià)的喲類格式化說明符轉(zhuǎn)換六正則表達(dá)式網(wǎng)上教程學(xué)七掃描輸入新增了類。 一、不可變String String類型的對(duì)象是不可變的,所有的改變實(shí)際上都是創(chuàng)建了一個(gè)新的String對(duì)象,另外當(dāng)String作為傳入?yún)?shù)的時(shí)候,其實(shí)實(shí)際上傳入的是這個(gè)引用的一個(gè)拷貝,這個(gè)方法結(jié)束了之后這個(gè)傳入的引用也就消失了,原來的那個(gè)String不會(huì)受到方法內(nèi)的影響而...
摘要:通過運(yùn)行時(shí)類型信息,程序能夠使用基類的指針或引用來檢查這些指針或引用所指的對(duì)象的實(shí)際派生類型。編程應(yīng)該盡量面向接口編程,應(yīng)該對(duì)類型信息盡量的少了解二對(duì)象看書,書上寫得好靜態(tài)語句塊在這個(gè)類被加載的時(shí)候運(yùn)行。 一、為什么需要RTTI Run-Time Type Information。通過運(yùn)行時(shí)類型信息,程序能夠使用基類的指針或引用來檢查這些指針或引用所指的對(duì)象的實(shí)際派生類型。編程應(yīng)該盡量...
摘要:內(nèi)部類中也可以取得這個(gè)外部類對(duì)象引用。創(chuàng)建成員內(nèi)部類對(duì)象的時(shí)候需要外部類對(duì)象。另外在方法中的內(nèi)部類不能加等權(quán)限修飾符,只能加和修飾符。可以在接口內(nèi)部定義內(nèi)部類,而且他們即使沒有修飾,也會(huì)自動(dòng)變成的。 Thinking in Java撈干貨,寫筆記 一、成員內(nèi)部類 1.最基本使用 public class Demo { class Contents{ privat...
摘要:但如果導(dǎo)出類還有抽象方法,那這個(gè)類還應(yīng)該加上聲明為抽象類。并且接口具有繼承的一系列特點(diǎn),如向上轉(zhuǎn)型等等。接口中的方法是自動(dòng)是的。 Thinking in Java 好書全是干貨 一、抽象類和抽象方法 抽象方法:這種方法只有聲明而沒有方法體,下面是抽象方法生命所采用的語法 abstract void f(); 包含抽象方法的類叫做抽象類,如果一個(gè)類包含一個(gè)或多個(gè)抽象方法,該類必須被限定為...
閱讀 3691·2021-11-19 09:56
閱讀 1473·2021-09-22 15:11
閱讀 1133·2019-08-30 15:55
閱讀 3379·2019-08-29 14:02
閱讀 2917·2019-08-29 11:07
閱讀 439·2019-08-28 17:52
閱讀 3175·2019-08-26 13:59
閱讀 442·2019-08-26 13:53