1.全部代码
1.user
public class User {
@ViewInject(age = 22,name="sunweihao")//为注解设置值
private String name;
private int age;
private String watch(String TV){
return "看"+TV;
}
@Override
public String toString() {
return "User{" +
"age=" + age +
", name='" + name + '\'' +
'}';
}
}
2.ViewInject
public class AnnotationMainTest {
public static void main(String[] args) throws Exception {
/**
* 需求:获取User类中name字段上的自定义注解的值,然后将该值通过反射设置给User对象中的属性
*/
User user=new User();
/**
* 获取到User类的字节码
*/
Class<User> userClass = User.class;
/**
* 将字节码的name、age字段获取到
*/
Field userClassDeclaredField = userClass.getDeclaredField("name");//获取到user类的对象
Field userClassDeclaredFieldAge = userClass.getDeclaredField("age");
/**
* 将当前字段的注解对象获取到
*/
ViewInject viewInject = userClassDeclaredField.getAnnotation(ViewInject.class);//userClassDeclaredField要注解位置的那个
if (viewInject!=null) {
/**
* 获取自定义对象的参数
*/
int age = viewInject.age();
String name = viewInject.name();
System.out.println(name+age);
/**
* 通过暴力反射,将这两个值设置给对象,因为他们是私有的
*/
userClassDeclaredField.setAccessible(true);//设置允许访问,其实就是暴力反射
userClassDeclaredField.set(user,name);//给user对象的declaredField 设置值为name
userClassDeclaredFieldAge.setAccessible(true);//设置允许访问,其实就是暴力反射
userClassDeclaredFieldAge.set(user,age);//给user对象的declaredField 设置值为name
System.out.println(user.toString());
}else {
System.out.println("为空");
}
//根据方法名进行方法反射
Method declaredMethod = userClass.getDeclaredMethod("watch", String.class);
declaredMethod.setAccessible(true);//一定
Object invoke = declaredMethod.invoke(user, "苍井空电影");
System.out.println(invoke);
}
}
@Target(ElementType.FIELD)//作用领域
//@Retention(RetentionPolicy.SOURCE)//源码编译成字节码时,会把User类里的@ViewInject(即注解信息)清除掉
//@Retention(RetentionPolicy.CLASS)//该注解会被编译到字节码中,但是当虚拟机全加载这个字节码的时候,注解信息就被清除
@Retention(RetentionPolicy.RUNTIME)//该注解类一直保留到加载到虚拟机中
public @interface ViewInject {
//两个参数
int age();
String name();
}
3.AnnotationMainTest
2.步骤
1.写注解类
设置作用域在参数上,注解的持续时间一直保留到虚拟机中
@Target(ElementType.FIELD)//作用领域
//@Retention(RetentionPolicy.SOURCE)//源码编译成字节码时,会把User类里的@ViewInject(即注解信息)清除掉
//@Retention(RetentionPolicy.CLASS)//该注解会被编译到字节码中,但是当虚拟机全加载这个字节码的时候,注解信息就被清除
@Retention(RetentionPolicy.RUNTIME)//该注解类一直保留到加载到虚拟机中
public @interface ViewInject {
//两个参数
int age();
String name();
}
2.写User类并添加注解
这里注解位置在name上,这个类似标识,用于获取注解类
public class User {
@ViewInject(age = 22,name="sunweihao")//为注解设置值
private String name;
private int age;
private String watch(String TV){
return "看"+TV;
}
@Override
public String toString() {
return "User{" +
"age=" + age +
", name='" + name + '\'' +
'}';
}
}
3.获取user类中的字段:name
User user=new User();
/**
* 1.获取到User类的字节码
*/
Class<User> userClass = User.class;
/**
* 将字节码的name字段获取到
*/
Field userClassDeclaredField = userClass.getDeclaredField("name");//name的字段
4.根据user类字段的标识,来获取注解类ViewInject.class
ViewInject viewInject = userClassDeclaredField.getAnnotation(ViewInject.class);
5.获取注解类的值,并为user设置值
int age = viewInject.age();
String name = viewInject.name();
System.out.println(name+age);
/**
* 通过暴力反射,将这两个值设置给对象,因为他们是私有的
*/
userClassDeclaredField.setAccessible(true);//设置允许访问,其实就是暴力反射
userClassDeclaredField.set(user,name);//类,为name字段设置值
6.图解:
1.方法反射
//根据方法名进行方法反射
Method declaredMethod = userClass.getDeclaredMethod("watch", String.class);
declaredMethod.setAccessible(true);//一定
Object invoke = declaredMethod.invoke(user, "苍井空电影");
System.out.println(invoke);
3.问题与反思
1.反射的意义:
为达需求,打破封装思想,面向对象,有些时候我们要拿封装里面的东西,但是拿不到,我们就可以通过反射的形式来打破封装