注解和反射
一、注解(Annotation)
1.注解
注解可以给程序看,注释给人看。
2.内置注解
@Override 重写注解,@Deprecated 不推荐程序员使用,但是可以使用,或存在更好的方式。@SuppressWarnings 镇压警告注释
3.元注解(meta-annotation)
@Target 用于描述注解的使用范围(即可以用在什么地方)
@Retention 表示需要在什么级别保存改注解信息(SOURCE<CLASS<RUNTIME)一般写RUNTIME就行。
@Document 说明改注解被包含在javadoc中
@Inherited 说明子类可以继承父类中的该注解
4.自定义注解
使用@interface来声明一个注解,使用时自动继承java.lang.annotation.Annotation接口
public class test {
@MyAnnotation(age = 1)
public void test1(){
}
}
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation{
//注解的参数:参数类型+参数名();
String name() default "Asonare";//有默认值用的时候可以不写
int age(); //无默认值时使用时需定义 否则报错
}
只有一个值时建议使用value,写的时候可以省略。
二、反射(Reflection)
1.创建个User类实验
class User{
private String name;
private int age;
private int id;
public User(){
}
public User(String name, int age, int id) {
this.name = name;
this.age = age;
this.id = id;
}
2.获取Class类(此处只列举一种还有很多)
package XML.ReflectionTest;
public class test2 extends Object{
public static void main(String[] args) throws ClassNotFoundException {
//通过反射获取类得对象class对象
Class c1 = Class.forName("XML.ReflectionTest.User"); //包名加类名
System.out.println(c1); //输出结果 class XML.ReflectionTest.User
//一个类在内存中只有一个class对象
//一个类被加载后,类得整个结构都会被封装在class对象中
Class c2 = Class.forName("XML.ReflectionTest.User");
}
}
3.类的加载与ClassLoader在内存中加载的顺序(简单写下)
加载:将class文件字节码内容加载到内存中,并将这些静态数据转换成方法区的运行时的数据结构,然后生成一个代表这个类的java.lang.Class对象。
链接:验证->准备->解析
初始化
4.获取类运行时结构
get.Fields()只能找到pubilc属性,get.DeclaredFields()找到全部属性,get.getField()找到指定属性(pubilic)
get.DeclaredField()找到指定属性(全部),getMethods()获取本类及其父类的全部public方法,get.DeclaredMethods()获取本类的所有方法
5.动态创建对象执行方法
package XML.ReflectionTest;
//动态创建对象,通过反射
public class test3 {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
//获得Class对象
Class c1 = Class.forName("XML.ReflectionTest.User");
//构造一个对象
User o = (User) c1.newInstance();//本质时调用类的无参构造
System.out.println(o);// 打印结构 User{name='null', age=0, id=0}
}
}
//通过构造器创建对象
Constructor constructor = c1.getDeclaredConstructor(String.class, int.class, int.class);
User o1 = (User) constructor.newInstance("asonare", 1, 0);
System.out.println(o1);//User{name='asonare', age=1, id=0}
6.通过反射操控方法
//通过反射调用普通方法
User o2 = (User)c1.newInstance();
//通过反射获取一个方法
Method setName = c1.getDeclaredMethod("setName", String.class);
//invoke激活(对象,方法的值)
setName.invoke(o2,"asonare");
System.out.println(o2.getName());
7.通过反射操控属性
User o3 = (User)c1.newInstance();
Field name = c1.getDeclaredField("name");
//不能直接操作私有属性,需关闭程序的安全检测setAccessible值为TRUE时为关闭
name.setAccessible(true);
name.set(o3,"asonare");
System.out.println(name.getName());