注解(annotation)和反射(reflect)
------- android培训、java培训、期待与您交流! ----------
JDK5.0新特性-注解@(Annotation)
在java.lang包下 java提供了三个基本的注解:
@Override
表示一个方法声明打算重写超类中的另一个方法声明。如果方法利用此注释类型进行注解但没有重写超类方法,则编译器会生成一条错误消息。
@Deprecated
用 @Deprecated注释的程序元素,不鼓励程序员使用这样的元素,通常是因为它很危险或存在更好的选择。在使用不被赞成的程序元素或在不被赞成的代码中执行重写时,编译器会发出警告。
@SuppressWarnings
指示应该在注释元素(以及包含在该注释元素中的所有程序元素)中取消显示指定的编译器警告。注意,在给定元素中取消显示的警告集是所有包含元素中取消显示的警告的超集。例如,如果注释一个类来取消显示某个警告,同时注释一个方法来取消显示另一个警告,那么将在此方法中同时取消显示这两个警告。
注解就相当于你的一个源程序中要调用的一个类,要在源程序中应用某个注解,得先准备好了这个注解。就像你要调用某个类,得先有开发好这个类。
为注解增加基本属性:
注解的返回类型可以是基本类型 String类型 Class类型 枚举类型注解类型还可以是前面这些类型的数组,如果不是这些类型编译器就会报错。
例:代码
@MyAnnotation(value="haha",array={2,3,4,5,6},clazz=Integer.class)//相当于创建一个@MyAnnotation实例对象
publicclass AnnotationTest{
publicstaticvoid main(String[] args) {
//用反射技术检查注解
Class clazz=AnnotationTest.class;
if(clazz.isAnnotationPresent(MyAnnotation.class));
{
MyAnnotation ma=(MyAnnotation)clazz.getAnnotation(MyAnnotation.class);
System.out.println(ma.color());
System.out.println(ma.value());
System.out.println(ma.array().length);
System.out.println(ma.lamp().nextLamp());
System.out.println(ma.attribute().value());
System.out.println(ma.clazz().getName());
}
}
}
//为自定义的注解添加元注解
//注解默认保留在class阶段
@Retention(RetentionPolicy.RUNTIME)//将注解保留在runtime阶段
public@interfaceMyAnnotation {
//为注解添加各种属性,注解很像接口,那么属性很像方法
//比如说有一个color属性
String color() default"red";
//value做属性值时特殊,并且只有一个value属性需要赋值时,在该属性赋值时可以省略“value=”
String value();
//为注解增加一个数组类型的属性
//在应用注解的类身上如果数组属性只有一个值,那么在赋值时可以不用写{}直接写一个值,如array=1
int[] array()default {1,2,3};
//为该注解增加一个枚举类型的属性
Enumtest.TrafficLamp lamp()default Enumtest.TrafficLamp.RED;
//还能添加注解类型的属性
MateAnnotation attribute()default@MateAnnotation("注解类型属性");//默认值相当于注解的实例对象
//Class类型属性
Class clazz() default String.class;
}
public@interfaceMateAnnotation {
String value();
}
反射
反射的基础:(反射不是jdk1.5新特性)
Java程序在运行时,Java运行时系统一直对所有的对象进行所谓的运行时类型标识。这项信息纪录了每个对象所属的类。虚拟机通常使用运行时类型信息选准正确方法去执行,用来保存这些类型信息的类是Class类。Class类封装一个对象和接口运行时的状态,当装载类时,Class类型的对象自动创建。
Class 没有公共构造方法。Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的 defineClass 方法自动构造的,因此不能显式地声明一个Class对象。
虚拟机为每种类型管理一个独一无二的Class对象。也就是说,每个类(型)都有一个Class对象。运行程序时,Java虚拟机(JVM)首先检查是否所要加载的类对应的Class对象是否已经加载。如果没有加载,JVM就会根据类名查找.class文件,并将其Class对象载入。
基本的 Java 类型(boolean、byte、char、short、int、long、float 和 double)和关键字 void 也都对应一个 Class 对象。
每个数组属于被映射为 Class 对象的一个类,所有具有相同元素类型和维数的数组都共享该 Class 对象。
一般某个类的Class对象被载入内存,它就用来创建这个类的所有对象。
获得一个类的字节码对象有三种方法:
1. Class cl=类.class;
2. Class cl1=类对象.getClass();
3. Class cl2=Class.forName(“类的完整名”);//利用Class类的静态方法或得字节码对象。
每个类的字节码对象在内存中都只存在一份。
理解反射的概念:
反射就是把java中的各种成分映射成相应的java类。
构造方法的反射应用:
成员变量的反射:Field类
成员方法的反射:Method类
method.invoke(null,22);//当调用静态方法时,不需要指定对象,因为调用静态的不需要对象,指定为null即可。
数组的反射:
具有相同的维数和元素类型的数组属于同一类型,即具有相同的Class实例对象
代表数组的Class实例对象的getSuperClass()方法返回的父类为Object类对应的Class。
基本类型的一位数组可以被当做Object类型使用,不能当做Object[]类型使用;非基本类型的一位数组既可以当做Object类型使用又可以当做Object[]类型使用。
Array工具类用于完成对数组的反射操作。