2022-08-10 java之反射
[TOC](目录)
# 1.概念--什么是反射机制
Java反射机制是对在运行中的java程序,对于任何一个类,我们都能获取到他的属性和方法,对于任意一个对象,都能调用他的任意的方法和属性,这种动态获取类的信息和动态调用对象的属性和方法的功能我们成为反射机制
# 2. 反射相关的类有哪些
注意:只有先获取类,才能获取对应的方法、构造方法、成员变量
![在这里插入图片描述](https://img-blog.csdnimg.cn/59c8b933db8244f8bad1f0eaff439856.png)
# 3.获取类的方法
要操作一个类的字节码,需要首先获取到这个类的字节码,怎么获取java.lang.Class实例?
![在这里插入图片描述](https://img-blog.csdnimg.cn/ae38ae7377ca4654bc8429151e243eab.png)
前置代码(后面例子,都用这段代码)
```java
public class Student {
private String name;
private Integer no;
public Student() {
}
public Student(String name, Integer no) {
this.name = name;
this.no = no;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getNo() {
return no;
}
public void setNo(Integer no) {
this.no = no;
}
}
```
1. Class.forName(“完整类名带包名”)(静态方法)
```java
public static void main(String[] args) throws ClassNotFoundException {
Class<?> student = Class.forName("com.jisoft.night.Student");
System.out.println(student);
}
```
![在这里插入图片描述](https://img-blog.csdnimg.cn/2eb8244734b34f7e926e82e399e7ab55.png)
2. 对象.class
```java
public static void main(String[] args) throws ClassNotFoundException {
Student student1 = new Student();
Class<? extends Student> student2 = student1.getClass();
System.out.println(student2);
}
```
![在这里插入图片描述](https://img-blog.csdnimg.cn/0ad7b21f0cfa42d38ad41c15dfcf9735.png)
3. 类.class
```java
System.out.println(Student.class);
```
![在这里插入图片描述](https://img-blog.csdnimg.cn/58e50c8235bc4e9ea52bd185ec8cbc93.png)
# 4.通过反射实例化对象
newInstance()方法内部实际上调用了无参数构造方法,所以必须保证无参构造方法存在,否则会抛出java.lang.InstantiationException异常。
```java
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
Class<?> student = Class.forName("com.jisoft.night.Student");
// newInstance() 这个方法会调用User这个类的无参数构造方法,完成对象的创建。
// 重点是:newInstance()调用的是无参构造,必须保证无参构造是存在的!
Object o = student.newInstance();
}
```
# 5.JDBC重点(Class.forName导致类加载)
如果你只是希望一个类的静态代码块执行,其它代码一律不执行,可以使用:
```java
Class.forName("完整类名");
```
这个方法的执行会导致类加载,类加载时,静态代码块执行。
# 6.反射Filed【反射/反编译一个类的属性】
## 6.1.Class类方法
![在这里插入图片描述](https://img-blog.csdnimg.cn/b2b99be9b5ab4a10a006cd3f493d1c00.png)
## 6.2Field
![在这里插入图片描述](https://img-blog.csdnimg.cn/2e68b62da33c46e09355c73054aef447.png)
例子:
```java
class Test2{
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException, InstantiationException {
Class<?> student = Class.forName("com.jisoft.night.Student");
//获取类中指定的属性
Field name = student.getDeclaredField("name");
System.out.println("属性的名字:"+name.getName());//获取属性的名字
System.out.println("属性的类型:"+name.getType());//获取属性的类型
System.out.println("获取类中指定的属性:"+name);
//获取所有的类中所有的属性
Field[] fields = student.getDeclaredFields();
for (Field field : fields) {
System.out.println(field);
}
//通过反射操作属性-----set/get方法
Object obj = student.newInstance();
name.set(obj,"刘北北");
System.out.println(name.get(obj));
}
}
```
![在这里插入图片描述](https://img-blog.csdnimg.cn/9903a36bf6414b428a588e043d3e5785.png)
# 7、反射Method【反射/反编译一个类的方法】
## 7.1 Method类方法
![在这里插入图片描述](https://img-blog.csdnimg.cn/a08d66f12a7748a7ac955f983ca7cb7b.png)
重点getMethod()方法和invoke方法
在有了反射机制处理之后,即使没有明确的Person类型对象(依然需要实例化对象,Object对象描述,所有 的普通方法必须在有实例化对象之后才可以进行调用)。就可以通过反射调用。通过反射去调用setter,getter方法
```
Method getMethod(String name,Class...parameterTypes)
name: method的名称
parameterTypes:method的参数类型的列表(参数顺序需按声明method时的参数列表排列)
返回:符合method名称和参数的method对象
抛出错误:NoSuchMethodException (没有找到所要查询的Method对象或Method名称为“<init>”或“<clinit>”) NullPointerException (所要查询的Method对象的名称为null) SecurityException(调用的类或其父类没有调用权限)
```
invoke方法:
```
作用:调用包装在当前Method对象中的方法。
原型:Object invoke(Object obj,Object...args) 参数解释:obj:实例化后的对象 args:用于方法调用的参数
返回:根据obj和args调用的方法的返回值
抛出错误:IllegalAccessException(Method对象强制Java语言执行控制或无权访问obj对象) IllegalArgumentException(方法是实例化方法,而指定需要调用的对象并不是实例化后的类或接口)
```
```java
class Test3{
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
//通过类名获取获取class对象
Class<?> student = Class.forName("com.jisoft.night.Student");
//实例化对象
Object o = student.newInstance();
//通过getMethod方法获取setName方法的对象, 传入的参数为"要获取的方法名"和传入的参数类型
Method setName = student.getMethod("setName", String.class);
//通过invoke()调用方法
setName.invoke(o,"哈哈哈哈");
//通过getMethod获取getName方法的对象
Method getName = student.getMethod("getName");
//调用getName方法
Object invoke = getName.invoke(o);
System.out.println(invoke);
}
}
```