文章目录
一、反射的概述
Java的反射机制是在运行状态时,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象都能够调用它的任意一个方法和属性。这种动态获取的信息以及动态调用的方法的功能称为Java语言的反射机制。反射就是把类中的各种成分封装成一个对象,根据这些个对象来创建类的实例。
二、反射的使用
2.1 获取类对象
获取Class对象有两种,一种是类.class,一种是Class.forName()。.class适用于在编译时已经知道具体的类。
- .class
Class cl = String.class;
System.out.println(cl);
输出:
class java.lang.String
- Class.forName()
try {
Class<?> aClass = Class.forName("java.lang.String");
System.out.println(aClass.getName());
} catch (ClassNotFoundException e) {
System.out.println("找不到String类");
}
输出:
java.lang.String
2.2 获取类的成员
Student测试类:
public class Student {
private String name;
private Integer age;
public Student(String name, Integer age) {
this.name = name;
this.age = age;
System.out.println("name: " + name + " age: " + age);
}
public Student(String name) {
this.name = name;
System.out.println("name: " + name);
}
public Student() {
}
private Student(Integer age) {
this.age = age;
System.out.println("age: " + age);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
2.2.1 获取类的构造函数
获取所有的构造方法:
public static void main(String[] args) throws ClassNotFoundException {
Class<?> aClass = Class.forName("com.example.demo.thread.Student");
Constructor<?>[] declaredConstructors = aClass.getDeclaredConstructors();
for (Constructor constructor : declaredConstructors) {
//获取构造方法的权限修饰符
System.out.print("权限修饰符:" + Modifier.toString(constructor.getModifiers()) + " 参数类型:");
//获取构造方法的参数类型
Class[] parameterTypes = constructor.getParameterTypes();
for (int i = 0; i < parameterTypes.length; i++) {
System.out.print(parameterTypes[i].getSimpleName() + " ");
}
System.out.println(" ");
}
}
输出:
权限修饰符:private 参数类型:Integer
权限修饰符:public 参数类型:
权限修饰符:public 参数类型:String
权限修饰符:public 参数类型:String Integer
获取特定的构造方法:
获取无参构造方法:
try {
Constructor<?> constructor = aClass.getConstructor();
System.out.println(constructor);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
输出:
public com.example.demo.thread.Student()
获取有参构造方法:
Class[] p = {String.class, Integer.class};
try {
Constructor<?> constructor = aClass.getConstructor(p);
System.out.print(Modifier.toString(constructor.getModifiers()) + "参数:");
Class[] parametertypes = constructor.getParameterTypes();
for (int j = 0; j < parametertypes.length; j++) {
System.out.print(parametertypes[j].getSimpleName() + " ");
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
输出:
public参数:String Integer
调用构造函数:
Class[] p = {String.class, Integer.class};
try {
Constructor<?> constructor = aClass.getConstructor(p);
Object instance = constructor.newInstance("张三", 22);
System.out.println(instance);
} catch (NoSuchMethodException | InvocationTargetException | InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
输出:
name: 张三 age: 22
com.example.demo.thread.Student@4d7e1886
调用私有构造方法:
Class[] p1 = {Integer.class};
try {
Constructor<?> constructor = aClass.getDeclaredConstructor(p1);
constructor.setAccessible(true);
Student instance = (Student) constructor.newInstance(20);
System.out.println(instance.getAge());
} catch (NoSuchMethodException | InvocationTargetException | InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
输出:
20
2.2.2 获取类的方法
try {
Method method = aClass.getDeclaredMethod("setAge", Integer.class);
Object arg1s[] = {10};
Student student1 = Student.class.newInstance();
method.invoke(student1, arg1s);
System.out.println(student1.getAge());
} catch (NoSuchMethodException | InvocationTargetException | InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
输出:
10
2.2.3 获取类的成员变量
try {
Field field = aClass.getDeclaredField("age");
Student student = new Student("zs", 21);
try {
field.setAccessible(true);
field.set(student, 20);
System.out.println(student.getAge());
} catch (IllegalAccessException e) {
e.printStackTrace();
}
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
输出:
20
三、反射常见的面试问题
3.1 什么是反射机制?
Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意的属性和方法;这种动态获取信息以及动态调用对象方法的功能称为Java的反射机制。
3.2 反射机制优缺点
- 优点:运行期类型的判断,动态加载类,提高代码灵活度。
- 缺点:性能瓶颈。
3.3 反射机制的应用场景有哪些?
反射是框架设计的灵魂。
在我们平时的项目开发中,基本很少直接用到反射,但不能说反射技术没用。
- 使用JDBC连接数据库时使用Class.forName()通过反射加载数据库的驱动程序。
- Spring框架也有很多地方用到反射,最经典的就是Xml文件的配置模式。Spring通过Xml配置模式装载Bean的过程:1)将程序所有的XML或Properties配置文件加载到内存中;2)Java类里面解析配置文件中的内容,得到对应实体类的字节码字符串以及相关属性信息;3)使用反射机制,根据字符串获取某个类的Class实例;4)动态配置实例的属性。
3.4 Java获取反射的三种方法
- new个对象实例,对象.getClass();
- Class.forName(“Student”);
- 类名.class;
public class Student {
private int id;
String name;
protected boolean sex;
public float score;
}
public class Get {
//获取反射机制三种方式
public static void main(String[] args) throws ClassNotFoundException {
//方式一(通过建立对象)
Student stu = new Student();
Class classobj1 = stu.getClass();
System.out.println(classobj1.getName());
//方式二(所在通过路径-相对路径)
Class classobj2 = Class.forName("fanshe.Student");
System.out.println(classobj2.getName());
//方式三(通过类名)
Class classobj3 = Student.class;
System.out.println(classobj3.getName());
}
}