一.引入
上文中,提到了注解類JyzTargetPackage可以定義為@Target(ElementType.PACKAGE),可是在被注解類里我無論怎么加,編譯器都報錯,於是引入了package-info.java這個文件。
二.創建package-info.java
- "I found that when you create a new package in eclispe there is a check box to check if you want a package-info.java."勾上就行了。
- 如果不幸的是你已經創建了這個包並在里面定義了很多類,而eclispe又是不能直接創建一個package-info.java文件的。只能在包對應文件夾里,手動創建一個package-info.java,寫上包名,最后刷新eclispe即可。
三.package-info.java的作用
- "Package annotations must be in file package-info.java",package-info.java為我們提供了包注解的地方。JyzTargetPackage(http://zy19982004.iteye.com/blog/1979208)苦苦尋找終於找到地方了。
- 提供包級別的類(或接口),這些類(或接口)只有本包里才能訪問,即使是子包也不能訪問。
- 提供包的整體注釋說明。
package-info.java
- /**
- * <b>package-info不是平常類,其作用有三個:</b><br>
- * 1、為標注在包上Annotation提供便利;<br>
- * 2、聲明包的私有類和常量;<br>
- * 3、提供包的整體注釋說明。<br>
- *
- * @author JoyoungZhang@gmail.com
- */
- @JyzTargetPackage(version="1.0")
- package com.jyz.study.jdk.annotation;
- class PackageInfo{
- public void common(){
- System.out.println("sa");
- }
- }
- class PackageInfoGeneric<T extends Throwable>{
- private T obj;
- public void set(T obj){
- this.obj = obj;
- }
- public void common(){
- System.out.println(obj + "sa");
- }
- }
- interface packageInfoInteger{
- public void test();
- }
- class PackageConstants{
- public static final String ERROE_CODE = "100001";
- }
TestPackageInfo.java
- package com.jyz.study.jdk.annotation;
- import java.io.IOException;
- /**
- * 測試package-info.java文件的作用
- * 1、為標注在包上Annotation提供便利;<br>
- * 2、聲明包的私有類和常量;<br>
- * @author JoyoungZhang@gmail.com
- *
- */
- public class TestPackageInfo {
- public static void main(String[] args) {
- //1
- Package p = Package.getPackage("com.jyz.study.jdk.annotation");
- if(p != null && p.isAnnotationPresent(JyzTargetPackage.class)){
- JyzTargetPackage nav = p.getAnnotation(JyzTargetPackage.class);
- if(nav != null){
- System.out.println("package version:" + nav.version());
- }
- }
- //2
- PackageInfo packageInfo = new PackageInfo();
- packageInfo.common();
- //泛型也能很好的工作,在pakcage-info.java里定義的類和普通類沒什么區別
- PackageInfoGeneric<Exception> packageInfoGeneric = new PackageInfoGeneric<Exception>();
- packageInfoGeneric.set(new IOException("device io"));
- packageInfoGeneric.common();
- Sub sub = new Sub();
- sub.test();
- System.out.println(PackageConstants.ERROE_CODE);
- }
- }
- class Sub implements packageInfoInteger{
- @Override
- public void test() {
- System.out.println("sub");
- }
- }
- console output:
- package version:1.0
- sa
- java.io.IOException: device iosa
- sub
- 100001
需要注意兩點
- package-info.java里不能聲明public class(或 interface)
- 剛開始p.isAnnotationPresent(JyzTargetPackage.class)返回false,后來找到原因JyzTargetPackage沒有加上@Retention(RetentionPolicy.RUNTIME)。
@Inherited的使用
@Inherited:允許子類繼承父類的注解。
二.代碼
- @Target(ElementType.TYPE)
- @Retention(RetentionPolicy.RUNTIME)
- @Inherited
- public @interface DBTable {
- public String name() default "";
- }
- @Target(ElementType.TYPE)
- @Retention(RetentionPolicy.RUNTIME)
- public @interface DBTable2 {
- public String name() default "";
- }
- package com.jyz.study.jdk.reflect;
- import java.util.Arrays;
- import com.jyz.study.jdk.annotation.DBTable;
- import com.jyz.study.jdk.annotation.DBTable2;
- /**
- * 1.演示從Class對象上獲得反射元素Field Method Constructor
- * 2.演示AnnotatedElement接口的四個方法
- * @author JoyoungZhang@gmail.com
- *
- */
- public class DeclaredOrNot {
- public static void main(String[] args) {
- Class<Sub> clazz = Sub.class;
- System.out.println("============================Field===========================");
- //public + 繼承
- System.out.println(Arrays.toString(clazz.getFields()));
- //all + 自身
- System.out.println(Arrays.toString(clazz.getDeclaredFields()));
- System.out.println("============================Method===========================");
- //public + 繼承
- System.out.println(Arrays.toString(clazz.getMethods()));
- //all + 自身
- System.out.println(Arrays.toString(clazz.getDeclaredMethods()));
- System.out.println("============================Constructor===========================");
- //public + 自身
- System.out.println(Arrays.toString(clazz.getConstructors()));
- //all + 自身
- System.out.println(Arrays.toString(clazz.getDeclaredConstructors()));
- System.out.println("============================AnnotatedElement===========================");
- //注解DBTable2是否存在於元素上
- System.out.println(clazz.isAnnotationPresent(DBTable2.class));
- //如果存在該元素的指定類型的注釋DBTable2,則返回這些注釋,否則返回 null。
- System.out.println(clazz.getAnnotation(DBTable2.class));
- //繼承
- System.out.println(Arrays.toString(clazz.getAnnotations()));
- //自身
- System.out.println(Arrays.toString(clazz.getDeclaredAnnotations()));
- }
- }
- @DBTable
- class Super{
- private int superPrivateF;
- public int superPublicF;
- public Super(){
- }
- private int superPrivateM(){
- return 0;
- }
- public int superPubliceM(){
- return 0;
- }
- }
- @DBTable2
- class Sub extends Super{
- private int subPrivateF;
- public int subPublicF;
- private Sub(){
- }
- public Sub(int i){
- }
- private int subPrivateM(){
- return 0;
- }
- public int subPubliceM(){
- return 0;
- }
- }
- console output:
- ============================Field===========================
- [public int com.jyz.study.jdk.reflect.Sub.subPublicF, public int com.jyz.study.jdk.reflect.Super.superPublicF]
- [private int com.jyz.study.jdk.reflect.Sub.subPrivateF, public int com.jyz.study.jdk.reflect.Sub.subPublicF]
- ============================Method===========================
- [public int com.jyz.study.jdk.reflect.Sub.subPubliceM(), public int com.jyz.study.jdk.reflect.Super.superPubliceM(), public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException, public final void java.lang.Object.wait() throws java.lang.InterruptedException, public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException, public boolean java.lang.Object.equals(java.lang.Object), public java.lang.String java.lang.Object.toString(), public native int java.lang.Object.hashCode(), public final native java.lang.Class java.lang.Object.getClass(), public final native void java.lang.Object.notify(), public final native void java.lang.Object.notifyAll()]
- [private int com.jyz.study.jdk.reflect.Sub.subPrivateM(), public int com.jyz.study.jdk.reflect.Sub.subPubliceM()]
- ============================Constructor===========================
- [public com.jyz.study.jdk.reflect.Sub(int)]
- [private com.jyz.study.jdk.reflect.Sub(), public com.jyz.study.jdk.reflect.Sub(int)]
- ============================AnnotatedElement===========================
- true
- @com.jyz.study.jdk.annotation.DBTable2(name=)
- [@com.jyz.study.jdk.annotation.DBTable(name=), @com.jyz.study.jdk.annotation.DBTable2(name=)]
- [@com.jyz.study.jdk.annotation.DBTable2(name=)]
三.代碼說明
- 代碼演示了從Class對象上獲得反射元素Field Method Constructor時get*和getDeclared*的區別。
- 代碼演示了AnnotatedElement接口的四個方法。
- java.lang.reflect.AnnotatedElement表示可以被注解的元素。它只有四個方法,參考代碼DeclaredOrNot.java。
- 當我使用clazz.getAnnotations()時,我期望得到控制台打印出來的內容,但實際上卻只得到了[@com.jyz.study.jdk.annotation.DBTable2(name=)],后來發現是DBTable里沒有聲明@Inherited。
- java.lang.reflect.AnnotatedElement表示可以被注解的元素。它只有四個方法,參考代碼DeclaredOrNot.java。