注解与反射
注解 Annotation
- 注解概念
- 内置注解
- 元注解
- 自定义注解
1.注解是干什么的?
- 对程序作出解释,规范与约束程序
- 注解可以被其他程序(如 编译器等) 读取 reflection
- 可以使用在 包,类,方法,变量等,相当于给它们添加额外的信息-(通过反射访问)
2.内置注解(三个)
- @Override 重写
- @Deprecated 已过时的
- @SuppressWarnings(value = "all") 镇压警告
3.元注解 (四个)
- @Target
@Target({ElementType.TYPE})
注解能用在哪 - @Retention
@Retention(value = RetentionPolicy.RUNTIME)
注解作用范围 - @Document 把注解生成在Javadoc
- @Inherited 子类可继承父类注解
4.自定义注解
- @Interface xxx{ 参数类型 + 参数名( ) }
- 若只有一个参数,可使用 String value() , 这样调用注解可以直接赋值
上代码:
@myAnnotation(name = "参数类型 + 参数名()",length = 2,type = "lll",likes ={"芜","湖"} )
@myAnnotation2("直接写参数")
public static void main(String[] args) {
}
//注解能用在哪里
@Target({ElementType.TYPE,ElementType.FIELD,ElementType.METHOD,ElementType.PACKAGE})
@Retention(value = RetentionPolicy.RUNTIME) //注解在哪里有效
@Documented //注解也生成javadoc文档
@Inherited //子类可继承父类注解
@interface myAnnotation{ //自定义注解 参数类型+变量名()
String name();
int length();
String type();
String[] likes();
}
@interface myAnnotation2{ //只有一个参数时 用 参数类型+value()
String value();
}
反射 reflection
1.反射机制 是干嘛的?
- 反射机制,允许程序在执行期间 借助Reflection API 获得并操作 任何类的内部信息;
- 类,对象,构造器,方法,属性,泛型信息,注解
2.类的加载
-
加载 (把类的class文件读取到内存,生成Class对象)
-
链接 保证代码没有错误,为 **static **变量 默认初始值
-
初始化 static 静态变量静态方法块 赋值 ,初始化子类会先初始化其父类
2.1 类加载器Classloader
- 引导类 (根)加载器 java核心库 rt.jar 无法直接获取
- 拓展类加载器 jre/lib/ext下的jar
ExtClassloader
- 系统类加载器 项目jar,最常用
AppClassloader
2.2 类什么时候初始化
- main方法所在类,new对象,调用static (除final) 属性/方法,调用反射,子类(先初始化父类)
- 不会初始化:子类调用父类static,数组定义类
Son[] array = new Son[5];
3.获取Class对象
-
三种方式获取Class对象 + 基本数据类型 (类,对象,地址+类名)
Class c1 = person.getClass(); //对象.getClass Class c2 = Student.class; //类.class Class c3 = Class.forName("com.kuang.reflection.Student"); //Class.forName("") Class c4 = Integer.TYPE; //八大基本数据类型:Integer,Short,Long,Float,Double,Byte,Character,Boolean
-
哪些类型有Class对象 (.class)
Class c1 = Object.class; //类 Class c2 = Comparable.class; //接口 Class c3 = String[].class; //一维数组 Class c4 = int[][].class; //二维数组 Class c5 = Override.class; //注解 Class c6 = ElementType.class; //枚举 Class c7 = Integer.class; //基本数据类型 Class c8 = void.class; //void Class c9 = Class.class; //Class //只要元素类型与维度一样,就是同一个Class int[] a = new int[10]; int[] b = new int[100];
4.创建运行时类的对象
-
获得类的信息
Name,Field,Method,Constructor,SuperClass,Interface,Annotation
// 通过reflection获取Class对象 名字/对象/类 Class c1 = Class.forName("com.kuang.reflection.User"); //c1 = new User().getClass(); //c1 = User.class; //1.获得类的名字 System.out.println(c1.getName()); //包名+类名 System.out.println(c1.getSimpleName()); //类名 //2.获得类的属性 System.out.println("====================="); Field[] fields = c1.getFields(); //只能获得public属性 fields = c1.getDeclaredFields(); //获得全部属性 for (Field field : fields) { System.out.println(field); } //获得指定属性 (属性名) Field name = c1.getDeclaredField("name"); System.out.println(name); //3.获得类的方法 System.out.println("======================="); Method[] methods = c1.getMethods(); //获得本类及其父类的全部public方法 for (Method method : methods) { System.out.println(method); } System.out.println("---------"); methods = c1.getDeclaredMethods(); //获得本类的所有方法 for (Method method : methods) { System.out.println(method); } //获得指定方法 方法名+参数 (?加参数-->因为重载) Method getName = c1.getMethod("getName", null); Method setName = c1.getMethod("setName", String.class); System.out.println("指定方法:"+getName); System.out.println("指定方法:"+setName); //4.获得构造器 System.out.println("======================="); Constructor[] constructors = c1.getConstructors(); for (Constructor constructor : constructors) { System.out.println(constructor); } constructors = c1.getDeclaredConstructors(); for (Constructor constructor : constructors) { System.out.println("all:"+constructor); } //获得指定构造器 (参数) Constructor constructor = c1.getConstructor(String.class, int.class, int.class); System.out.println("指定构造器:"+constructor); constructor = c1.getDeclaredConstructor(null); System.out.println("公共指定构造器:"+constructor);
-
创建类的 对象
newInstance()
- 直接通过Class对象创建 (类中必须要有无参构造方法,有构造器的访问权限)
- 通过构造器创建
//1.Class对象直接 构造对象 newInstance User user = (User) c1.newInstance(); //本质 调用类的 无参构造器 //2.通过构造器创建对象 (有参) Constructor constructor = c1.getDeclaredConstructor(String.class, int.class,int.class); User user2 = (User) constructor.newInstance("刘波", 001,18);
-
获取,操作 类的 方法
.invoke(对象,值)
Method setName = c1.getMethod("setName", String.class);//先获得指定 方法 setName.invoke(user2,"张三"); //.invoke(对象,值)
-
获取,操作 类的 属性
.set(对象,值)
- 注:无法直接操作私有 属性/方法 , 需要关闭安全检测
.setAccessible(true)
Field name = c1.getDeclaredField("name"); name.setAccessible(true); //直接操作私有属性/方法 需要关闭安全检测 name.set(user2,"李四"); // .set(对象,值)
- 注:无法直接操作私有 属性/方法 , 需要关闭安全检测
-
关闭安全检测
.setAccessible(true)
- Method, Field , Constructor 都有 setAccessible 方法
- 取消java语言访问检查;提高反射效率;得以访问修改 私有成员 ;
5.反射操作注解
-
通过反射获取注解
- 获取类 的指定注解:
(注解名).getAnotation( 注解名.class ); (注意强转)
- 获取指定属性/方法 注解
指定属性.getAnnotation( 注解名.class );
- 获得注解的值
.参数名()
//获得注解的value的值 Table_kuang table_kuang = (Table_kuang)c1.getAnnotation(Table_kuang.class);//类型强转 System.out.println(table_kuang.value()); //.value() //获得类 (属性,方法) 指定的注解 Field name = c1.getDeclaredField("name");//先获取属性 Field_kuang annotation = name.getAnnotation(Field_kuang.class);//通过属性 获得注解信息 System.out.println(annotation.columnName()); //.参数名() System.out.println(annotation.type()); System.out.println(annotation.length());
- 获取类 的指定注解:
-
与ORM 对象关系映射 结合
实例:
import java.lang.annotation.*; import java.lang.reflect.Field; //利用注解和反射,完成类和表 结构的映射关系 public class Test11 { public static void main(String[] args) throws Exception { //通过反射获取注解 Class c1 = Class.forName("com.kuang.reflection.Student02"); Annotation[] annotations = c1.getAnnotations(); for (Annotation annotation : annotations) { System.out.println(annotation); } //获得注解的value的值 Table_kuang table_kuang = (Table_kuang)c1.getAnnotation(Table_kuang.class);//类型强转 System.out.println(table_kuang.value()); //.value() //获得类 (属性,方法) 指定的注解 Field name = c1.getDeclaredField("name");//先获取属性 Field_kuang annotation = name.getAnnotation(Field_kuang.class);//通过属性 获得注解信息 System.out.println(annotation.columnName()); //.参数名() System.out.println(annotation.type()); System.out.println(annotation.length()); } } //类名的注解 @Target(ElementType.TYPE) //注解作用域(目标) @Retention(value = RetentionPolicy.RUNTIME) //注解作用范围 @interface Table_kuang{ String value(); //注解类型+参数名 } //属性的注解 @Target(ElementType.FIELD) @Retention(value = RetentionPolicy.RUNTIME) @interface Field_kuang{ String columnName(); //列名 String type(); //类型 int length(); //长度 } @Table_kuang("db_kuang") class Student02{ @Field_kuang(columnName = "db_id",type = "int",length = 10) private int id; @Field_kuang(columnName = "db_age",type = "int",length = 5) private int age; @Field_kuang(columnName = "db_name",type = "varchar",length = 20) private String name; public Student02(){ } public Student02(int id,int age,String name){ this.id = id; this.age = age; this.name = name; } @Override public String toString() { return "Student02{" + "id=" + id + ", age=" + age + ", name=‘" + name + ‘\‘‘ + ‘}‘; } public int getId() { return id; } public void setId(int id) { this.id = id; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } }