每一个类都有一个class对象,包含了与类有关的信息,当编译一个新类时,会产生一个同名的.class文件,该文件内容保持着class对象。
简而言之,通过反射,我们可以在运行时获得程序或程序集中每一个类型的成员和成员的信息。程序中一般的对象的类型都是在编译期就确定下来的,而 Java 反射机制可以动态地创建对象并调用其属性,这样的对象的类型在编译期是未知的。所以我们可以通过反射机制直接创建对象,即使这个对象的类型在编译期是未知的。
反射可以提供运行时的类信息,并且这个类可以在运行时才加载进来,甚至在编译时期该类的 .class 不存在也可以加载进来。
Class 和 java.lang.reflect 一起对反射提供了支持,java.lang.reflect 类库主要包含了以下三个类:
- Field:可以使用get()和set()方法读取和修改Field对象关联的字段
- Method:可以使用 invoke() 方法调用与 Method 对象关联的方法;
- Constructor:可以用 Constructor 创建新的对象
反射的基本运用:
1.获取class对象
/**使用class类的forname静态方法
*/
public static Class<?> forName(String className)
```
比如在 JDBC 开发中常用此方法加载数据库驱动:
```java
Class.forName(driver);
//直接获取某一个对象的class
Class<?> klass = int.class;
Class<?> classInt = Integer.TYPE;
//调用某个对象的getclass()方法,比如:
StringBuilder str = new StringBuilder("123");
Class<?> klass = str.getClass();
2.通过反射来生成对象主要有两种方式
//1.使用Class对象的newInstance()方法来创建Class对象对应类的实例。
Class<?> c = String.class;
Object str = c.newInstance();
// 2.先通过Class对象获取指定的Constructor对象,再调用Constructor对象的newInstance()方法来创建实例。这种方法可以用指定的构造器构造类的实例。
//获取String所对应的class对象
class<?> c=String.class;
//获取String类带一个String参数的构造器
Constructor constructor = c.getConstructor(String.class);
//获取构造器创建实例
Object obj = constructor.newInstance("dsds");
System.out.println(obj);
下面是一个面试可以回答反射的例子:
实体类:
package com.aixs.basic.reflect;
/**
* @author aixscode.github.io
* @date 2019/1/21 9:29
*/
public class Robot {
private String name;
public void sayHi(String helloSentence)
{
System.out.println(helloSentence+" "+name);
}
private String throwhello(String tag)
{
return "Hello "+tag;
}
}
反射实例:
package com.aixs.basic.reflect;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* @author aixscode.github.io
* @date 2019/1/21 9:31
*/
public class ReflectSample {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
//通过全类名找到Class
Class c= Class.forName("com.aixs.basic.reflect.Robot");
//创建出类实例
Robot r=(Robot) c.newInstance();
//打印类的全类名
System.out.println("Class name is"+c.getName());
//调用Robot throwhello 方法(私有)
// 1.构建Method对象 调用getDeclaredMethod
// 2.设置Accessible 为true
// 3.invoke()
Method getHello = c.getDeclaredMethod("throwhello", String.class);//除去继承和实现其他类的方法的的所有方法
getHello.setAccessible(true);
Object str= getHello.invoke(r,"bob");
System.out.println("gethello result is "+ str);
// getMethod 调用public方法
Method sayHi = c.getMethod("sayHi", String.class);//除去私有的其他方法(包括继承实现其他类的方法)
sayHi.invoke(r, "welcome");
//得到成员
Field name = c.getDeclaredField("name");
name.setAccessible(true);
name.set(r,"Alice");
sayHi.invoke(r, "welcome");
}
}
运行结果:
Class name iscom.aixs.basic.reflect.Robot
gethello result is Hello bob
welcome null
welcome Alice