java注解和反射
1、注解
Annotation是从JDK5.0开始引入的新技术。
• Annotation的作用: – 不是程序本身,可以对程序作出解释。(这一点,跟注释没什么区别) – 可以被其他程序(比如:编译器等)读取。(注解信息处理流程,是注解和注释的重大区别 。如果没有注解信息处理流程,则注解毫无意义)
• Annotation的格式: – 注解是以“@注释名”在代码中存在的,还可以添加一些参数值,例如: @SuppressWarnings(value=“unchecked”)。
• Annotation在哪里使用? – 可以附加在package, class, method, field等上面,相当于给它们添加了额外的辅助信 息,我们可以通过反射机制编程实现对这些元数据的访问。
1.1、内置注解
- @Override
- – 定义在java.lang.Override中,此注释只适用于修辞方法,表示一个方 法声明打算重写超类中的另一个方法声明。
- @Deprecated
- – 定义在java.lang.Deprecated中,此注释可用于修辞方法、属性、类 ,表示不鼓励程序员使用这样的元素,通常是因为它很危险或存在更 好的选择。
@SuppressWarnings
– 定义在java.lang.SuppressWarnings中,用来抑制编译时的警告信息 。
– 与前两个注释有所不同,你需要添加一个参数才能正确使用,这些参 数值都是已经定义好了的,我们选择性的使用就好了,参数如下:
– @SuppressWarnings(“unchecked”)
– @SuppressWarnings(value={“unchecked”, “deprecation”})
1.2、自定义注解
使用@interface自定义注解时,自动继承了java.lang.annotation.Annotation接口
• 要点:
– @interface用来声明一个注解
• 格式为:
– public @interface 注解名 {定义体} – 其中的每一个方法实际上是声明了一个配置参数。
– 方法的名称就是参数的名称 – 返回值类型就是参数的类型(返回值类型只能是基本类型、Class、String、enum)
– 可以通过default来声明参数的默认值。
– 如果只有一个参数成员,一般参数名为value
• 注意:
注解元素必须要有值。我们定义注解元素时,经常使用空字符串、0作为默认值。 也经常使用负数(比如:-1)表示不存在的含义
1.3、元注解
元注解的作用就是负责注解其他注解。 Java定义了4个标准的 meta-annotation类型,它们被用来提供对其它 annotation 类型作说明。
• 这些类型和它们所支持的类在java.lang.annotation包中可以 找到
– @Target
作用: – 用于描述注解的使用范围(即:被描述的注解可以用在什么地方)
– @Retention
作用: – 表示需要在什么级别保存该注释信息,用于描述注解的生命周期
– @Documented
注解表明这个注解应该被 javadoc工具记录. 默认情况下,javadoc是不包括注解的. 但如果声明注解时指定了 @Documented,则它会被 javadoc 之类的工具处理, 所以注解类型信息也会被包括在生成的文档中,是一个标记注解,没有成员。
– @Inherited
允许子类继承父类的注解。
类继承关系中@Inherited的作用
类继承关系中,子类会继承父类使用的注解中被@Inherited修饰的注解
接口继承关系中@Inherited的作用
接口继承关系中,子接口不会继承父接口中的任何注解,不管父接口中使用的注解有没有被@Inherited修饰
类实现接口关系中@Inherited的作用
类实现接口时不会继承任何接口中定义的注解
1.4、案例
//自定义注解
//该注解可以作用在方法、类、接口、注解、枚举类型上
@Target({ElementType.METHOD,ElementType.TYPE})
//该注解的生命周期可以在java程序运行中一直有效,一般自定义注解都是RUNTIME
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@interface Test01{
String name() default "aa";
int age() default 1;
String address() default "";
int height() default -1;
}
2、反射
1、案例
public class Test01 {
public static void main(String[] args) throws ClassNotFoundException {
Student student = new Student();
//通过student实例的getClass()方法获取Class对象
Class c1 = student.getClass();
System.out.println(c1.hashCode());
//通过类的全类名获取Class对象
Class c2 = Class.forName("AnnotationAndReflex.reflection.Student");
System.out.println(c2.hashCode());
//通过具体类的class属性获取Class对象
Class c3 = Student.class;
System.out.println(c3.hashCode());
Class c4 = c1.getSuperclass();
System.out.println(c4);
//基本数据类型的包装类可以通过TYPE属性获取Class对象
Class c5 = Integer.TYPE;
System.out.println(c5);
}
}
class Person{
String name;
int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
class Student extends Person{
public String getPerson(){
return this.name;
}
}
public static void main(String[] args) {
//获取系统类的加载器
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
System.out.println(systemClassLoader);
//获取系统类加载器的父类加载器--》扩展类加载器
ClassLoader loaderParent = systemClassLoader.getParent();
System.out.println(loaderParent);
//获取扩展类加载器的父类加载器--》根加载器(C/C++)
ClassLoader parent = loaderParent.getParent();
System.out.println(parent);
//查看当前系统的类是由哪个加载器加载的
ClassLoader classLoader = Class.forName("AnnotationAndReflex.reflection.Test03").getClassLoader();
System.out.println(classLoader);
}
Class c = Class.forName("AnnotationAndReflex.reflection.User");
System.out.println(c.getName());//获取包名加类名
System.out.println(c.getSimpleName());//获取类名
Field[] fields = c.getFields();//只能获取本类公共的属性
for (Field field : fields) {
System.out.println("正常"+field);
}
Field[] declaredFields = c.getDeclaredFields();//可以获取本类私有和公共属性
for (Field declaredField : declaredFields) {
System.out.println(declaredField);
}
Method[] methods = c.getMethods();//可以获取本类和父类的公共方法
for (Method method : methods) {
System.out.println("正常"+method);
}
Method[] declaredMethods = c.getDeclaredMethods();//只能获取本类的私有和公共方法
for (Method declaredMethod : declaredMethods) {
System.out.println(declaredMethod);
}
Constructor[] constructors = c.getConstructors();
for (Constructor constructor : constructors) {
System.out.println("正常"+constructor);
}
Constructor[] declaredConstructors = c.getDeclaredConstructors();
for (Constructor declaredConstructor : declaredConstructors) {
System.out.println(declaredConstructor);
}
Field age = c.getDeclaredField("age");//获取本类中指定的私有属性
System.out.println(age);
2、通过反射操作对象
Class c = Class.forName("AnnotationAndReflex.reflection.User");
Constructor declaredConstructor = c.getDeclaredConstructor(String.class, int.class);
//通过反射调用有参构造器
User user = (User) declaredConstructor.newInstance( "aaa", 10);
System.out.println(user);
Method setName = c.getDeclaredMethod("setName", String.class);
User user1 = new User();
//通过反射调用对象的公有方法
setName.invoke(user1, "aaa111");
System.out.println(user1.getName());
//通过反射调用对象的私有属性
Method setName1 = c.getDeclaredMethod("saveName",String.class);
User user2 = new User();
//通过反射调用对象的私有方法之前必须关闭安全检测
setName1.setAccessible(true);
System.out.println(setName1.invoke(user2, "2121"));
//通过反射操作对象的私有属性值
Field name = c.getDeclaredField("name");
name.setAccessible(true);
name.set(user2,"gggg");
System.out.println(user2.getName());
3、通过反射操作泛型
public void test01(Map<User,String> map1, List<String> list){
}
public Map<String,User> test02(){
return null;
}
public static void main(String[] args) throws NoSuchMethodException {
Method method = Test06.class.getDeclaredMethod("test01", Map.class, List.class);
//通过反射获取类中方法输入参数的泛型
Type[] genericParameterTypes = method.getGenericParameterTypes();
for (Type genericParameterType : genericParameterTypes) {
if(genericParameterType instanceof ParameterizedType){
Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments();
for (Type actualTypeArgument : actualTypeArguments) {
System.out.println(actualTypeArgument);
}
}
}
//通过反射获取类中方法返回参数的泛型
Method method1 = Test06.class.getDeclaredMethod("test02");
Type genericReturnType = method1.getGenericReturnType();
if(genericReturnType instanceof ParameterizedType){
Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments();
for (Type actualTypeArgument : actualTypeArguments) {
System.out.println(actualTypeArgument);
}
}
}
4、通过反射操作注解
public class Test07 {
public static void main(String[] args) throws NoSuchFieldException {
Class c = Table1.class;
Annotation[] annotations = c.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println(annotation);
}
//通过反射获取类注解的值
TableName annotation = (TableName)c.getAnnotation(TableName.class);
System.out.println(annotation.value());
//通过反射获取类中属性注解的值
Field name = c.getDeclaredField("name");
ColumnName columnName = name.getAnnotation(ColumnName.class);
System.out.println(columnName.name());
System.out.println(columnName.type());
System.out.println(columnName.length());
}
}
@TableName("表1")
class Table1{
@ColumnName(name = "name1",type = "varchar",length = 10)
private String name;
@ColumnName(name = "age1",type = "int",length = 10)
private int age;
public Table1() {
}
public Table1(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Table1{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface TableName{
String value();
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface ColumnName{
String name();
String type();
int length();
}