反射(在类加载的时候,也想获取到类中的信息)//换一种方式使用类
正常情况下,要先进行类加载,然后创建对象调用
当我们不知道类中的属性,方法,构造器,注释时,我们也想调用类里面的属性与方法,可以通过反射获取到类的信息再使用。
java.lang.Class{//没有构造器,不能创建对象,所以所有类的类(包括object)就是它
}
Object就是Class的一个对象
new Class()//但是Class不能被创建对象= Object;
类的类 Class
属性的类 Field
方法的类 Method
构造器 ,注解。。。。。都有对应的大类,这些都是大类的对象
反射可以破坏封装
获取类中的public修饰的属性,也包含从父类中继承过来的public属性
Field[] getFields()
Field getField(String name)
获取类中声明的属性(包含私有的),但是不能获取从父类中继承过来的属性
Field[] getDeclaredFields()
Field getDeclaredField(String name)
获取当前类中的public方法,包含从父类中继承的public方法
Method[] getMethods()
Method getMethod(String name, Class<?>… parameterTypes)
获取当前类中声明的方法(包含私有的),但是不能获取从父类中继承过来的方法
Method[] getDeclaredMethods()
Method getDeclaredMethod(String name, Class<?>… parameterTypes)
反射访问属性
public static void main(String[] args)throws Exception {
Student stu = new Student();
Class c = stu.getClass();
//获取类中名字叫name的属性
Field f1 = c.getDeclaredField("name");
//设置私有属性可以被访问,否则报错
f1.setAccessible(true);
//用反射的方式,给指定对象的name属性赋值
//相当于之前的stu.name = "tom";
f1.set(stu,"tom");
//用反射的方式,获取这个属性的值
//相当于之前的stu.name
System.out.println(f1.get(stu));
System.out.println("----------------------");
//获取类中名字叫age的属性
Field f2 = c.getDeclaredField("age");
//用反射的方式,给指定对象的age属性赋值
//相当于之前的stu.age = 20;
f2.set(stu,20);
//用反射的方式,获取这个属性的值
//相当于之前的stu.age
System.out.println(f2.get(stu));
System.out.println("----------------------");
//获取类中名字叫num的属性
Field f3 = c.getDeclaredField("num");
//用反射的方式,给静态属性num赋值,不需要对象
//相当于之前的Student.num = 99;
f3.set(null,99);
//用反射的方式,获取这个静态属性的值,不需要对象
//相当于之前的Student.num
System.out.println(f3.get(null));
}
反射调用方法
public static void main(String[] args)throws Exception {
Student stu = new Student();
Class c = stu.getClass();
//获取类中的toString方法,没有参数,这是从父类继承的方法
Method m1 = c.getMethod("toString", null);
//反射的方式,调用stu对象中的这个方法,没有参数,并接收执行结果
//相当于之前的:Object result = stu.toString();
Object result = m1.invoke(stu,null);
//输出执行结果
System.out.println(result);
System.out.println("-------------------");
//获取类中的sayHello方法,需要一个String类型的参数,这是自己定义的方法
Method m2 = c.getMethod("sayHello", String.class);
//反射的方式,调用stu对象中的这个方法,参数是"tom",并接收执行结果
//相当于之前的:Object result = stu.sayHello("tom");
result = m2.invoke(stu,"tom");
//输出执行结果
System.out.println(result);
}`
注意, public Object invoke(Object obj, Object… args)
obj,表示要调用哪个对象的方法,如果是静态方法,可以传null
args,可变参数,表示要调用的方法的参数列表
m.invoke(obj,null) 中的m,就是通过Class对象获取到的类中的某一个指定的方法
反射创建对象
使用反射的方式可以创建对象,也就是需要反射调用构造器。
例如,反射调用类中无参构造器创建对象
public static void main(String[] args)throws Exception {
Class c = Student.class;
//默认调用类中的无参构造器来创建对象
//相当于之前的:Object obj = new Student();
Object obj = c.newInstance();
System.out.println(obj);
}
例如,反射调用类中有参构造器创建对象
public static void main(String[] args)throws Exception {
Class c = Student.class;
//获取类中的俩参构造器
Constructor constructor = c.getConstructor(String.class, int.class);
//调用有参构造器创建对象,并传入对应的参数值
//相当于之前的:Object obj = new Student("tom",20);
Object obj = constructor.newInstance("tom",20);
System.out.println(obj);
}
反射获取注解
使用反射,可以获取到一个类中的注解信息
与上面类似,但是只能抓到runtime阶段运行的注解