JavaSE之反射
反射
反射机制概述
是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意属性和方法。
这种动态获取信息以及动态调用对象方法的功能称为Java语言的反射机制。
举一个例子来说明上面的意思:
假设有一个Student类,其中只有study方法是用public修饰的,private修饰的只能在本类中使用。
所以在Student类实例化后的对象,只有study方法可以被调用的!
但是如果使用了反射,就可以!反射在调用它的类中的属性与方法时,是无视修饰符的!!!
动态获取信息以及动态调用对象方法的功能简单的来说就是先获取配置文件中的信息,动态获取信息并创建对象和方法。
获取Class类对象的三种方式
-
Class.forName(全类名)方法
-
类名.class属性
-
对象名.getClass()方法
使用案例
Student类
package com.itheima.servlet;
public class Student {
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void study(){
System.out.println("学生在学习");
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
使用Demo类通过反射获取Student类对象
package com.itheima.servlet;
public class Demo {
public static void main(String[] args) throws ClassNotFoundException {
//1.Class类中的静态方法forName("全类名")
//全类名:包名 + 类名
Class clazz = Class.forName("com.itheima.servlet.Student");
System.out.println(clazz);
//class com.itheima.servlet.Student
//2.通过class属性来获取
Class clazz2 = Student.class;
System.out.println(clazz2);
//class com.itheima.servlet.Student
//3.利用对象的getClass方法来获取class对象
//getClass方法是定义在Object类中.
Student s = new Student();
Class clazz3 = s.getClass();
System.out.println(clazz3);
//class com.itheima.servlet.Student
System.out.println(clazz == clazz2);
//true
System.out.println(clazz2 == clazz3);
//true
}
}
反射获取构造方法并使用
Class类获取构造方法对象的方法
方法名 | 说明 |
---|---|
Constructor<?>[] getConstructors() | 返回所有公共构造方法对象的数组 |
Constructor<?>[] getDeclaredConstructors() | 返回所有构造方法对象的数组 |
Constructor<T> getConstructor(Class<?>... parameterTypes) | 返回单个公共构造方法对象 |
Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) | 返回单个构造方法对象 |
使用样例如下:
同样是Student类,其中有2个private修饰的成员变量,2个public修饰的成员方法,1个private修饰的成员方法。
package com.itheima.servlet;
public class Student {
private String name;
private int age;
public Student() {
System.out.println("public...Student...无参构造方法");
}
private Student(String name) {
System.out.println("name的值为" + name);
System.out.println("public...Student...有参构造方法");
}
public Student(String name,int age) {
System.out.println("name的值为:" + name + "年龄为:" + age);
System.out.println("public...Student...有参构造方法");
}
}
package com.itheima.servlet;
import java.lang.reflect.Constructor;
public class Demo {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
//1.getConstructors 返回所有公共的构造方法对象数组
Class clazz1 = Class.forName("com.itheima.servlet.Student");
Constructor[] constructors1 = clazz1.getConstructors();
for (Constructor constructor1 : constructors1) {
System.out.println(constructor1);
}
//public com.itheima.servlet.Student()
//public com.itheima.servlet.Student(java.lang.String,int)
//2.getDeclaredConstructors 返回所有的构造方法对象数组
Class clazz2 = Class.forName("com.itheima.servlet.Student");
Constructor[] declaredConstructors2 = clazz2.getDeclaredConstructors();
for (Constructor declaredConstructor2 : declaredConstructors2) {
System.out.println(declaredConstructor2);
}
//public com.itheima.servlet.Student()
//private com.itheima.servlet.Student(java.lang.String)
//public com.itheima.servlet.Student(java.lang.String,int)
//3.getConstructor 返回单个公共构造方法对象
Class clazz3 = Class.forName("com.itheima.servlet.Student");
System.out.println(clazz3.getConstructor());
System.out.println(clazz3.getConstructor(String.class,int.class));
//public com.itheima.servlet.Student()
//public com.itheima.servlet.Student(java.lang.String,int)
//4.getDeclaredConstructor 返回单个构造方法对象
Class clazz4 = Class.forName("com.itheima.servlet.Student");
System.out.println(clazz4.getDeclaredConstructor(String.class));
//private com.itheima.servlet.Student(java.lang.String)
}
}
运行结果已在上述代码中给出,感兴趣,请详细阅读。
Constructor类用于创建对象的方法
方法名 | 说明 |
---|---|
T newInstance(Object...initargs) | 根据指定的构造方法创建对象 |
setAccessible(boolean flag) | 设置为true,表示取消访问检查 |
newInstance()方法的使用
package com.itheima.servlet;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class ReflectDemo01 {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchMethodException {
/**
* 1.获取class对象
* 2.获取构造方法对象
* 3.利用newInstance创建的Student对象
*/
//1.创建有参Student对象
Class clazz1 = Class.forName("com.itheima.servlet.Student");
Constructor constructor1 = clazz1.getConstructor(String.class,int.class);
Student stu1 = (Student) constructor1.newInstance("zhansan",18);
System.out.println(stu1);
//name的值为:zhansan年龄为:18
//public...Student...有参构造方法
//com.itheima.servlet.Student@1540e19d
//2.创建空参Student对象
Class clazz2 = Class.forName("com.itheima.servlet.Student");
Constructor constructor2 = clazz2.getConstructor();
Student stu2 = (Student) constructor2.newInstance();
System.out.println(stu2);
//public...Student...无参构造方法
//com.itheima.servlet.Student@677327b6
}
}
setAccessible()方法的使用
被private修饰的方法不能直接使用
如果用反射强制获取并使用,需要临时取消访问检查
package com.itheima.servlet;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class ReflectDemo01 {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchMethodException {
/**
* 1.获取class对象
* 2.获取构造方法对象
* 3.利用newInstance创建的Student对象
*/
Class clazz = Class.forName("com.itheima.servlet.Student");
Constructor constructor = clazz.getDeclaredConstructor(String.class);
//被private修饰的方法不能直接使用
//如果用反射强制获取并使用,需要临时取消访问检查
constructor.setAccessible(true);
Student student = (Student)constructor.newInstance("zhanshan");
System.out.println(student);
}
}
总的来说就是:
如果是public的,直接创建对象
newInstance(Object... initargs)
如果是非public的,需要临时取消检查,然后再创建对象
setAccessible(boolean) 暴力反射
反射获取成员变量并使用
Class类获取成员变量对象的方法
方法名 | 说明 |
---|---|
Field[] getFields() | 返回所有公共成员变量对象的数组 |
Field[] getDeclaredFields() | 返回所有成员变量对象的数组 |
Field getField(String name) | 返回单个公共成员变量对象 |
Field getDeclaredField(String name) | 返回单个成员变量对象 |
Field类用于给成员变量赋值的方法
方法名 | 说明 |
---|---|
void set(Object obj, Object value) | 赋值 |
Object get(Object obj) | 获取值 |
反射获取成员方法并使用