注解
注解(Annotation)
Annotation 的作用
- 不是程序本身,可以对程序做出解释;
- 可以被其他程序(如:编译器 )读取;
几个内置注解
-
@Override // 重写的注解;
-
@Deprecated //不推荐程序员使用,通常是危险的或者存在更好的方法;
-
@SuppressWarnings //镇压警告,可以放在 方法和 类 上;带有参数 “all”,“unchecjed” 等;
元注解
元注解就是负责解释其他注解的注解;Java定义了四个标准的 meta-annotation 类型;
@Tatget : 用于描述注解的使用范围;
@Retention :注解在什么级别是有效的(SOURCE < CLASS < RUNTIME)源码<类<运行时 ;
@Documented : 表示注解是否生成在JAVADOC文档中;
@Inherited : 子类可以继承父类的注解;
@MyAnnotation
public class AnnotationDemo {
@MyAnnotation
public void aMethod(){
};
}
// 自定义一个注解 MyAnnotation
//元注解
@Target(value = {ElementType.TYPE,ElementType.METHOD})//在类,方法上可以使用注解。 Target表示作用的范围
@Retention(value = RetentionPolicy.RUNTIME) // 在运行时有效 。 Retention 表示 在什么地方有效
@Documented
@Inherited
@interface MyAnnotation {
}
自定义注解
//自定义注解
@MyAnnotation2(name = "CH") //若有参数,必须在注解后面加上参数的值, 若注解的参数只有一个,可以将参数名设置为value,设置为value后,可以省 略参数名
public class AnnotationDemo01 {
@MyAnnotation3({"CH","zqx"}) //只有一个参数 ,且参数名为value, 省略参数名
public void MyAnnotationtest(){
}
}
@Target({ElementType.TYPE,ElementType.METHOD}) //元注解
@Retention(RetentionPolicy.RUNTIME) //元注解
@interface MyAnnotation2 {
//定义 注解的参数: 参数类型 + 参数名 + ();
String name(); //定义一个String 类型的 参数;
int age() default 0; //可以加一个默认值,若参数由默认值,可以在 注解的参数列表省略该参数;
}
@Target({ElementType.TYPE,ElementType.METHOD}) //元注解
@Retention(RetentionPolicy.RUNTIME) //元注解
@interface MyAnnotation3{
String[] value(); //只有一个参数,且参数名为 value的注解
}
反射机制
反射:Reflection;
Java是一门动态语言,有了反射机制,让Java成为了准动态语言;反射机制允许程序在执行期借助于 Reflection API 取得任何类的内部信息,并能直接操作任意对象的内部属性及方法;
加载完类之后,在堆内存的方法区中就产生一个Class类型的对象,一个类只有一个Class对象,这个对象就包含了完整的类的结构信息。我们就可以通过这个对象看到类的结构。
获取反射对象
获取反射对象就是获取一个类的 Class 对象;
获取 Class对象方式:
public class ReflectionTest {
public static void main(String[] args) throws ClassNotFoundException {
Class c1 = Class.forName("com.ch.Reflection.User"); // 1. 通过 Class类中的 forName()静态方法获取 User 的 Class对象,参数为类的 全路径,需抛出异常;
User user = new User();
Class c2 = user.getClass(); //2.已知一个类的实例,可以通过 实例名.getClass() 方法获得;
Class c3 = User.class; //3. 知道一个具体的类,通过 类名.class;获得;
Class c4 = Integer.TYPE; // 4 .基本数据包装类 都有一个 TYPR 属性来获取对应的 Class的对象
//一些方法:
Class superclass = c1.getSuperclass(); //获取一个类的父类Class对象, 通过 getSuperclass()方法;
}
}
//定义一个实体类 pojo, entity
class User{
private String name;
private int id;
public User(){
super();
}
public User(String name, int id) {
this.name = name;
this.id = id;
}
public String getName() {
return name;
}
public int getId() {
return id;
}
public void setName(String name) {
this.name = name;
}
public void setId(int id) {
this.id = id;
}
}
一些方法:
User user = new User();
Class c1 = user.getClass(); //得到 User类的 class对象
//获取类的名字;
c1.getName();
c1.getSimpleName();
//获取类的属性;
Field[] fields = c1.getFields();//只能得到 public 属性;
Field[] fields1 = c1.getDeclaredFields(); //可以得到所有属性;
Field name = c1.getDeclaredField("name"); //获取指定得属性
//获取类得方法
Method[] method = c1.getMethods();//只能得到 public 方法,本类和 继承的方法;
Method[] declaredMethods = c1.getDeclaredMethods(); //获取本类所有的方法,不获取继承的方法
Method getName = c1.getMethod("getName", null);//获取指定得方法
Method setName = c1.getMethod("setName", String.class);//获取指定得方法,参数为: 方法名 , 参数的class对象
//获取构造器
Constructor[] constructors = c1.getConstructors();//获取类的构造器
Constructor constructor = c1.getConstructor(String.class, int.class);//获取指定构造器 参数为 类型的class对象
通过class对象创建 类对象;
Class c1 = Class.forName("com.ch.Reflection.User");//获取User的class对象
User user = (User) c1.newInstance(); //通过 newInstance()方法创建 对象, 本质是调用了无参构造器,若类中没有无参构造会报错
//通过构造器创建对象
Constructor constructor = c1.getConstructor(String.class, int.class);//获取有参构造器;
User user1 = (User) constructor.newInstance("111", 18); //通过构造器创建对象;
//通过反射调用方法;
Method setName = c1.getDeclaredMethod("setName", String.class);//获取 setName()方法;
setName.invoke(user1,"晨昏"); // 通过 方法.invoke()方法 设置 值 , 将 user1的 name 设置为 晨昏; invoke 激活(对象,值);
System.out.println(user1.getName());
//通过反射操作属性;
Field name = c1.getDeclaredField("name");//获取私有属性 name
name.setAccessible(true);//设置 私有属性 必须关闭安全检测 ,通过 setAccessible(true)
name.set(user1,"晨昏Cc"); //调用set()方法 设置 某对象的 name属性值。 set(对象,值);
System.out.println(user1.getName());
反射操作注解
///通过反射获取注解
public class ReflectionTest01 {
public static void main(String[] args) throws NoSuchFieldException {
Class c1 = Student.class; //获取 Student 的 Class 对象;
//通过反射获得注解;
Annotation[] annotations = c1.getAnnotations(); // 通过 getAnnotations()方法获取所有的注解;
for (Annotation annotation : annotations) {
System.out.println(annotation);
}
//获取注解 的 value值;
TpyeAnnotation typeAnnotation = (TpyeAnnotation)c1.getAnnotation(TpyeAnnotation.class); //获取指定的注解,
String value = typeAnnotation.value(); //得到注解的 value值
System.out.println(value);
//获取属性的注解值
Field fieldName = c1.getDeclaredField("name"); //获取 name 属性;
FieldAnnotation annotation = fieldName.getAnnotation(FieldAnnotation.class); //获取 name属性的注解;
annotation.name(); //获取 注解的属性值
annotation.type();
annotation.length();
}
}
//创建一个实体类
//给类 属性 加上注解
@TpyeAnnotation("Stuent_tab")
class Student{
@FieldAnnotation(name = "Student_id",type = "int", length = 10)
private int id;
@FieldAnnotation(name = "Student_age",type = "int", length = 10)
private int age;
@FieldAnnotation(name = "Student_name",type = "String", length = 10)
private String name;
@Override
public String toString() {
return "Student{" +
"id=" + id +
", age=" + age +
", name='" + name + '\'' +
'}';
}
}
//创建一个作用在类上的注解
@Target(ElementType.TYPE) //元注解 注解的作用范围为 类;
@Retention(RetentionPolicy.RUNTIME) // 元注解 在运行时有效;
@interface TpyeAnnotation{
String value(); //注解的一个属性
}
//创建一个作用在属性上的注解
@Target(ElementType.FIELD) //元注解 注解的左右范围为 属性;
@Retention(RetentionPolicy.RUNTIME) // 元注解 在运行时有效;
@interface FieldAnnotation{
String name(); //字段名
String type(); //类型
int length(); //长度
}