注解和反射
注解
内置注解
-
@Deprecated
// @Deprecated 意思是不推荐使用 @Deprecated public static void test(){ }
使用
@Deprecated
注解的方法在使用时会有这种提示。
-
@Override
// @Override 重写父类的方法 @Override public String toString() { return super.toString(); }
-
@SuppressWarnings
镇压警告@SuppressWarnings("all")
元注解( meta-annotation )
元注解的作用就是注解其他注解,Java 定义了 4 个标准的 meta-annotation 类型。
- @Target:描述注解的作用范围
- @Retention:表示需要在什么级别保存保存该注释信息,用于描述注解的生命周期。
(Source < Class < Runtime) - @Document:说明该注解将被包含在 javadoc 中
- @Inherited:说明该类的子类可以继承父类的注解
自定义注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation{
int id();
String name() default "klaus";
}
反射
一个类在内存中只有一个 Class 对象
一个类被加载后,类的整个结构都被封装在 class 中
package com.klaus.reflection;
// 什么是反射
public class Test extends Object{
public static void main(String[] args) throws ClassNotFoundException {
Class c1 = Class.forName("com.klaus.reflection.USer");
Class c2 = Class.forName("com.klaus.reflection.USer");
Class c3 = Class.forName("com.klaus.reflection.USer");
Class c4 = Class.forName("com.klaus.reflection.USer");
// 哈希值相同
System.out.println(c1.hashCode());
System.out.println(c2.hashCode());
System.out.println(c3.hashCode());
System.out.println(c4.hashCode());
}
}
class USer{
}
获取 class 的方法
package com.klaus.reflection;
public class Test2 {
public static void main(String[] args) throws ClassNotFoundException {
Person person = new Student();
System.out.println("这个人是" + person.name); //这个人是学生
//1. 通过对象获得
Class c1 = person.getClass();
System.out.println(c1.hashCode());//460141958
//2.forName
Class c2 = Class.forName("com.klaus.reflection.Student");
System.out.println(c2.hashCode());//460141958
//3.通过类名.class获得
Class c3 = Student.class;
System.out.println(c3.hashCode());//460141958
//4.基本内置类型有 Type方法
Class c4 = Integer.TYPE;
System.out.println(c4);//int
//5.获得class的父类型
Class c5 = c1.getSuperclass();
System.out.println(c5);//class com.klaus.reflection.Person
}
}
class Person{
String name;
public Person() {}
}
class Student extends Person{
public Student() {
this.name = "学生";
}
}
class Teacher extends Person{
public Teacher(){
this.name = "老师";
}
}
类的初始化
类的主动引用一定会发生类的初始化
- 虚拟机启动,先初始化 main 方法所在的类
- new 一个对象
- 使用类的静态成员(除了 final 常量)和静态方法
- 使用 java.lang.reflect 包的方法进行反射调用
- 初始化一个类,如果父类没有被初始化,那么先初始化父类
被动引用
- 访问一个静态域时,只有真正声明它的类才会被初始化
- 通过数组定义类引用,不会触发此类的初始化(比如说定义了一个对象类型的数组)
- 引用常量不会触发类的初始化(常量在链接阶段就存入常量池了)
反射的使用
Class c1 = Class.forName("com.klaus.reflection.User");
无参构造动态创建对象
// 无参构造
User user = (User) c1.newInstance();
System.out.println(user); / /USer{name='null', id=0, age=0}
有参构造创建对象
// 有参构造Constructor constructor = c1.getDeclaredConstructor(String.class, int.class, int.class);User instance =(User) constructor.newInstance("klaus", 12, 2);System.out.println(instance);// USer{name='klaus', id=12, age=2}
通过反射调用方法
//通过反射调用方法Method setName = c1.getDeclaredMethod("setName", String.class);// 获得方法setName.invoke(instance,"Klaus08");System.out.println(instance);//USer{name='Klaus08', id=12, age=2}
通过反射操作属性
//通过反射操作属性,对于私有属性要关闭 “安全检测”User user2 =(User) c1.newInstance();Field name = c1.getDeclaredField("name");name.setAccessible(true);name.set(user2,"zoe");System.out.println(user2.getName()); //zoe
全部代码如下:
package com.klaus.reflection;import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.lang.reflect.Method;// 动态创建对象public class Test7 { public static void main(String[] args) throws Exception { Class c1 = Class.forName("com.klaus.reflection.User"); // 无参构造 User u = (User) c1.newInstance(); System.out.println(u); // 有参构造 Constructor constructor = c1.getDeclaredConstructor(String.class, int.class, int.class); User instance =(User) constructor.newInstance("klaus", 12, 2); System.out.println(instance); //通过反射调用方法 Method setName = c1.getDeclaredMethod("setName", String.class);// 获得方法 setName.invoke(instance,"Klaus08"); System.out.println(instance); //通过反射操作属性,对于私有属性要关闭 “安全检测” User user2 =(User) c1.newInstance(); Field name = c1.getDeclaredField("name"); name.setAccessible(true); name.set(user2,"zoe"); System.out.println(user2.getName()); }}
setAccessible
反射&注解
通过反射获得注解信息,下面的代码演示了一般 ORM 注解的原理,通过注解获得属性对应列名,使 pojo 和表联系起来。
package com.klaus.reflection;import java.lang.annotation.*;import java.lang.reflect.Field;public class Test8 { public static void main(String[] args) throws Exception { Class c1 = Class.forName("com.klaus.reflection.Student_"); //通过反射获得注解 Annotation[] annotation = c1.getAnnotations(); for (Annotation annotation1 : annotation) { System.out.println(annotation1);//@com.klaus.reflection.TableKlaus(value=stu) } TableKlaus tableKlaus = (TableKlaus)c1.getAnnotation(TableKlaus.class); String value = tableKlaus.value(); System.out.println(value);//stu Field name = c1.getDeclaredField("name"); ColumnKlaus columnKlaus = name.getAnnotation(ColumnKlaus.class); System.out.println(columnKlaus.column());//name System.out.println(columnKlaus.type());//type }}@TableKlaus("stu")class Student_{ @ColumnKlaus(column ="name",type = "String") String name; @ColumnKlaus(column = "id", type = "int") int id;}// 类的注解@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@interface TableKlaus{ String value();}// 属性注解@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)@interface ColumnKlaus{ String column(); String type();}
本文来自博客园,作者:klaus08,转载请注明原文链接:https://www.cnblogs.com/klaus08/p/15132148.html