1注解的本质是一个接口。
这里可以看到注解编译过后就是一个接口
在javac命令的时候 private修饰词,不会被编译: 但是public会被编译:
这里使用public的时候:
会去找public上的注解符号,显示找不到
去掉public属性上的注解,再编译:
找不到包文件:
去掉import
编译通过。
这里看来private属性编译的时候是不会再最开始的时候编译的,应该是在调用方法的时候去初始化。这句话错了,看下图,只是用的javap的参数不一样,导致的结果不一样,
这里注意文件是单独编译还是所有文件一起编译,就是说你是吧一个项目中的某个文件单独拿出来编译还是所以文件编译完了。如果是所有文件用myeclipse编译完了,那么基本是不会包import包找不到的。
2.接口和类的javap:
这个是接口和他的javap:
package com.richinfo.annation;
publicinterface test {
java.lang.String name();
java.lang.String type();
int length();
}
//反射: 我们一般在new数据对象,这是在初始化类的时候在方法区:然后我们使用new 根据方法区的类去创建一个对象,
//反射是通过jvm在运行的时候去拿到运行时数据区的数据.
//注解也是在运行时的数据??保存在哪?怎么拿?是不是只要是继承annation接口的都可以看做是注解?然后保存在某个区域.
//注解本身是接口,但是没有值,那么怎么给接口的方法注入值?
//接口和类。
//
//接口的编译
//public interface com.richinfo.annation.test {
// public abstract java.lang.String name();
//
// public abstract java.lang.String type();
//
// public abstract int length();
// }
//在这里可以看到接口没有构造函数,也就是从另外一方面说接口不能被实例化。那么接口的作用是什么?多态??
这个是类和他的javap:
packagecom.richinfo.annation;
publicclass test1 {
//如果在定义变量的时候初始化变量值,那么在默认的无参构造函数里会默认初始化类的时候给该变量赋值
publicstaticintage2;
publicintage=2;//变量名,指着一个地址或者操作数
static {
age2=1;
}
public test1(int age) {
super();
this.age = age;
}
publicint getAge() {
returnage;
}
publicvoid setAge(int age) {
this.age = age;
}
}
//未初始化age时候方法的编译
//Compiled from "test1.java"
//public class com.richinfo.annation.test1 {
// public int age;
//
// publiccom.richinfo.annation.test1();
// Code:
// 0: aload_0
// 1: invokespecial#10 // Method java/lang/Object."
// 4: return
//
// public intgetAge();
// Code:
// 0: aload_0
// 1: getfield #18 // Field age:I
// 4: ireturn
//
// public void setAge(int);
// Code:
// 0: aload_0
// 1: iload_1
// 2: putfield #18 // Field age:I
// 5: return
//}
//初始化age=1时候反编译的指令
//public class com.richinfo.annation.test1 {
// public static int age2;
//
// public int age;
//
// static {};
// Code:
// 0: iconst_1
// 1: putstatic #11 // Field age2:I
// 4: return
//
// public com.richinfo.annation.test1();
// Code:
// 0: aload_0
// 1: invokespecial #16 // Method java/lang/Object."
// 4: aload_0
// 5: iconst_2
// 6: putfield #18 // Field age:I
// 9: return
//
// public int getAge();
// Code:
// 0: aload_0
// 1: getfield #18 // Field age:I
// 4: ireturn
//
// public void setAge(int);
// Code:
// 0: aload_0
// 1: iload_1
// 2: putfield #18 // Field age:I
// 5: return
// }
//带参数的构造函数的反编译
//public class com.richinfo.annation.test1 {
// public static int age2;
//
// public int age;
//
// static {};
// Code:
// 0: iconst_1
// 1: putstatic #11 // Field age2:I
// 4: return
//
// public com.richinfo.annation.test1(int);
// Code:
// 0: aload_0
// 1: invokespecial #17 // Method java/lang/Object."
// 4: aload_0
// 5: iconst_2
// 6: putfield #19 // Field age:I
// 9: aload_0 //这里为什么用局部变量这个指令初始化age而不是全局变量
//那么这里肯定是在构造方法里面默认有对变量的操作,int age =1;并且会把class 和所有的对象的int age对应起来
// 10: iload_1
// 11: putfield #19 // Field age:I
// 14: return
//
// public int getAge();
// Code:
// 0: aload_0
// 1: getfield #19 // Field age:I
// 4: ireturn
//
// public void setAge(int);
// Code:
// 0: aload_0
// 1: iload_1
// 2: putfield #19 // Field age:I
// 5: return
// }
这两个对比一下:接口没有构造器,也就是说接口不能被实例化,但是类有构造器:而且类里面的构造器会有一些初始化动作。可以看上面类初始化的javap对应的反编译指令:都是在构造器,默认的或者自己定义的构造器里面有一些初始化的动作。
那么这个和注解有什么关系呢?我们可以看到注解的本质是接口,而接口是没有构造器的,那么我们为什么可以通过反射获取到注解?没有构造器如何获取注解??答案是不能获取注解?你如何去反射到一个接口??其实在这里java做了一个动作,就是动态代理,给我们自定义的注解实现了动态代理,生成了他的子类,我们获取到的注解都是动态代理后子类,而不是接口。