注解和反射
目录
注解和反射
注解
- 所有框架的底层
内置注解举例
@Override
@SupressWarnnig
@Deprecated
元注解
-
注解的注解
@Target 作用对象 @Retention 作用级别(SOURCE<CLASS<RUNTIME) @Documented 是否包含将注解生成在javadoc中 @inherited 子类继承父类中该注解
自定义注解
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
//注解的参数:参数类型 参数名();
//注解可以显式赋值,如果没有默认值,就必须给注解赋值
String param1() default "";
int param2() default 0;
//如果默认值为-1,代表该参数不存在
int param3() default -1;
String[] params();
}
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
String value();
}
如何去读取注解?
- 反射
反射机制
哪些类型可以有Class对象?
- 各种类(外部类,成员(成员内部类,静态内部类),局部内部类,匿名内部类)
- 接口
- 数组
- 注解
- 枚举
- 包装类(基本数据类型)
- void
- Object
- Class
类是如何加载的?
-
加载到内存,从方法区的类的信息加载到堆中,对应一个java.lang.class对象
-
链接,正式为类变量(static)分配内存并设置对应的初始值
-
初始化
<clint>() {
静态代码块
静态变量赋值
}
java.lang.class在从方法区到堆中生成
什么时候会发生类的初始化?
-
类的主动引用(一定会发生类的初始化)
- 初始化main方法所在的类
- new一个类的对象
- 调用类的静态成员(除了final常量)和静态方法
- 反射调用
- 当初始化一个类,如果其父类没有被初始化,则会初始化它的父类
-
类的被动引用(不会发生类的初始化)
-
当访问一个静态域时,只有真正声明这个域的类才会被初始化。如:当通过子类引用父类的静态变量,不会导致子类初始化
Son.b (b是父类中的静态变量) -
通过数组定义类引用,不会触发此类的初始化
Student[] arr = new Student[2]; -
引用常量不会触发此类的初始化(常量在链接阶段就存入调用类的常量池中了)
Son.M (M为该类的静态常量)
-
类加载器的作用
-
*.java->Java编译器->*.class->类加载器->字节码校验器->解释器->操作系统
-
类加载器作用:将类(class)装载进内存。
- 引导类加载器(rt.jar)
- 扩展加载器
- 系统加载器
-
如何获取类加载器?
public class Test { public static void main(String[] args) throws ClassNotFoundException { //获取系统类加载器 ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader(); System.out.println(systemClassLoader); //获取系统类加载器的父类加载器->拓展类加载器 ClassLoader parent = systemClassLoader.getParent(); System.out.println(parent); //获取扩展类加载器的父类加载器->根加载器 ClassLoader parent1 = parent.getParent(); System.out.println(parent1); //测试当前类由哪个类加载器加载 ClassLoader classLoader = Class.forName("com.tiko.Test").getClassLoader(); System.out.println(classLoader); //测试JDK内置的类是由哪个加载器加载的 ClassLoader classLoader1 = Class.forName("java.lang.Object").getClassLoader(); System.out.println(classLoader1); //如何获取系统类加载器可以加载的路径 String property = System.getProperty("java.class.path"); System.out.println(property); } } -
双亲委派机制->多重检测,保证安全性
创建运行时类对象
获取运行时类的完整结构
-
通过反射获取运行时类的完整结构
public class Test { public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException { User user = new User(); Class c1 = user.getClass(); System.out.println(c1.getName()); System.out.println(c1.getSimpleName()); Field[] fields = c1.getFields(); for (Field field : fields) { System.out.println(fields); } Field[] declaredFields = c1.getDeclaredFields(); for (Field declaredField : declaredFields) { System.out.println(declaredField); } Field name = c1.getDeclaredField("name"); System.out.println(name); Method[] declaredMethods = c1.getDeclaredMethods(); for (Method declaredMethod : declaredMethods) { System.out.println(declaredMethod); } Constructor constructor = c1.getConstructor(String.class, int.class); System.out.println(constructor); //和其他方法,略去 } }
有了Class对象,能做什么?
通过Class对象来创建对象
public class Test {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
Class aClass = Class.forName("com.tiko.User");
Object o = aClass.newInstance();//本质上是调用无参构造器
System.out.println(o);
}
}
public class Test {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
//使用构造器创建对象
Class aClass = Class.forName("com.tiko.User");
Constructor constructor = aClass.getConstructor(String.class, int.class);
User zhangsan = (User)constructor.newInstance("zhangsan", 12);
System.out.println(zhangsan);
}
}
通过反射调用方法
- invoke()
public class Test {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
//使用构造器创建对象
Class aClass = Class.forName("com.tiko.User");
Constructor constructor = aClass.getConstructor(String.class, int.class);
User user1 = (User)constructor.newInstance("zhangsan", 12);
//使用反射获取方法
Method setName = aClass.getMethod("setName", String.class);
//调用方法
setName.invoke(user1, "张三");
System.out.println(user1.getName());
}
}
通过反射操作属性
public class Test {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
//使用构造器创 建对象
Class aClass = Class.forName("com.tiko.User");
Constructor constructor = aClass.getConstructor(String.class, int.class);
User user1 = (User)constructor.newInstance("zhangsan", 12);
Field name = aClass.getDeclaredField("name");
name.set(user1,"zhangsan");
System.out.println(user1.getName());//无法为private修饰,进行直接修改。若想修改,得关闭权限检测
}
}
- setAccessible()
public class Test {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
//使用构造器创建对象
Class aClass = Class.forName("com.tiko.User");
Constructor constructor = aClass.getConstructor(String.class, int.class);
User user1 = (User)constructor.newInstance("zhangsan", 12);
Field name = aClass.getDeclaredField("name");
//关闭安全检测
name.setAccessible(true);
name.set(user1,"zhangsan");//若想修改,得关闭权限检测
System.out.println(user1.getName());
}
}
性能对比分析
- 性能:普通调用>关闭检测的反射调用>反射
public class Test {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException {
//普通方式
test1();
//反射方式
test2();
//反射方式,且关闭检测
test3();
}
public static void test1() {
User user = new User();
long start = System.currentTimeMillis();
for (int i = 0; i < 100000000; i++) {
user.getName();
}
long stop = System.currentTimeMillis();
System.out.println(stop-start);
}
public static void test2() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
User user = new User();
Class<?> aClass = Class.forName("com.tiko.User");
Method getName = aClass.getMethod("getName", null);
long start = System.currentTimeMillis();
for (int i = 0; i < 100000000; i++) {
getName.invoke(user, null);
}
long stop = System.currentTimeMillis();
System.out.println(stop-start);
}
public static void test3() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
User user = new User();
Class<?> aClass = Class.forName("com.tiko.User");
Method getName = aClass.getMethod("getName", null);
getName.setAccessible(true);
long start = System.currentTimeMillis();
for (int i = 0; i < 100000000; i++) {
getName.invoke(user, null);
}
long stop = System.currentTimeMillis();
System.out.println(stop-start);
}
}
反射操作泛型(了解)
- 泛型->约束机制
- ParameterizedType
- GenericType
- TypeVariable
- WildcardType
public class Test {
public static void main(String[] args) throws NoSuchMethodException {
Method method1 = Test.class.getMethod("method1", Map.class, List.class);
Type[] genericParameterTypes = method1.getGenericParameterTypes();
for (Type genericParameterType : genericParameterTypes) {
System.out.println(genericParameterType);
if (genericParameterType instanceof ParameterizedType){
Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments();
for (Type actualTypeArgument : actualTypeArguments) {
System.out.println(actualTypeArgument);
}
}
}
}
public void method1(Map<String, User> map, List<User> user) {}
}
public class Test {
public static void main(String[] args) throws NoSuchMethodException {
Method method2 = Test.class.getMethod("method2", null);
Type genericReturnType = method2.getGenericReturnType();
System.out.println(genericReturnType );
if (genericReturnType instanceof ParameterizedType){
Type[] actualTypeArguments = ((ParameterizedType) genericReturnType ).getActualTypeArguments();
for (Type actualTypeArgument : actualTypeArguments) {
System.out.println(actualTypeArgument);
}
}
}
public Map<String, User> method2() {return null;}
}
反射操作注解
-
getAnnotations()
-
getAnnotaion()
-
ORM:对象关系映射
- 类和表名对应
- 属性和字段对应
- 对象和属性对应
利用注解和反射完成类和表结构的映射关系
//给类注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface Tab_annotation{
String value();
}
//给属性注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface Col_annontation{
String colname();
String type();
int length();
}
@Tab_annotation("tb_student")
public class Student {
@Col_annontation(colname = "name", type = "varchar(20)", length = 10)
private String name;
@Col_annontation(colname = "id", type = "int", length = 10)
private Integer id;
@Col_annontation(colname = "age", type = "int", length = 10)
private Integer age;
public Student() {
}
public Student(String name, Integer id, Integer age) {
this.name = name;
this.id = id;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getage() {
return age;
}
public void setage(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", id=" + id +
", age=" + age +
'}';
}
}
public class Test {
public static void main(String[] args) throws NoSuchMethodException, ClassNotFoundException, NoSuchFieldException {
Class<?> aClass = Class.forName("com.tiko.Student");
//通过反射获取注解
Annotation[] annotations = aClass.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println(annotation);
}
//通过反射获取注解value的值
Tab_annotation annotation = aClass.getAnnotation(Tab_annotation.class);//获取指定的注解
String value = annotation.value();//根据注解获取对应的值
System.out.println(value);
//获得指定的注解的值
Field field = aClass.getDeclaredField("name");//通过反射获取类中的属性
Col_annontation annotation1 = field.getAnnotation(Col_annontation.class);//获取属性上的注解
String colname = annotation1.colname();//获取注解上的值
String type = annotation1.type();
int length = annotation1.length();
System.out.println(colname + ","+ type+ "," + length);
}
}

浙公网安备 33010602011771号