一、什么是反射
在运行状态中,对任意一个类,都能知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能为java语言反射机制
二、反射的三种方式
- 第一种方式
public class ReflectSample {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
Robot r = new Robot();
Class rc = r.getClass();
System.out.println("Class name is " + rc.getName());
//获取类名
}
}
此种方式明显已经创建了对象,再进行反射,反而显得多此一举,于是一般不采用这种方式
- 第二种方式
public class ReflectSample {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
Class rc = Robot.class;
System.out.println("Class name is " + rc.getName());
//获取类名
}
}
此种方式需要导入类的包,依赖性太强,一般也不采用
- 第三种方式
public class ReflectSample {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
Class rc = Class.forName("com.imooc.javabasic.reflect.Robot");
//根据类的全路径名获取Class
System.out.println("Class name is " + rc.getName());
}
}
注:Class.forName()方法需要抛出ClassNotFoundException
三、通过反射获取构造方法
public class Robot {
private String name;
public Robot(String name) {
System.out.println("默认的构造方法:"+name);
}
public Robot(){
System.out.println("无参的构造方法");
}
public Robot(int age){
System.out.println("有一个参数的构造方法:"+age);
}
public Robot(String name,int age){
System.out.println("有多个参数构造方法:"+name+","+age);
}
protected Robot(boolean n){
System.out.println("受保护的构造方法:"+n);
}
private Robot(char c){
System.out.println("私有的构造方法:"+c);
}
public void sayHi(String helloSentence){
System.out.println(helloSentence+" "+name);
}
private String throwHello(String tag){
return "Hello "+tag;
}
static {
System.out.println("Hello Robot");
}
}
public class ReflectSample {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
Class rc = Class.forName("com.imooc.javabasic.reflect.Robot");
System.out.println("Class name is " + rc.getName());
System.out.println("所有构造方法");
Constructor[] constructors = rc.getDeclaredConstructors();
//获取所有构造方法
for (Constructor c:constructors){
System.out.println(c);
}
System.out.println("所有公共构造方法");
constructors = rc.getConstructors();
//获取所有公共构造方法
for (Constructor c:constructors){
System.out.println(c);
}
System.out.println("获取公共、无参的构造方法");
Constructor constructor = rc.getConstructor(null);
//无参的构造方法,类型是一个null,也可以不写,此处为构造器参数的类型
System.out.println(constructor);
Object object = constructor.newInstance();
//newInstance是Constructor类的方法,创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例
Robot robot = (Robot) object;
System.out.println(robot);
System.out.println("获取私有的构造方法");
constructor = rc.getDeclaredConstructor(char.class);
System.out.println(constructor);
constructor.setAccessible(true);//默认为false,调用私有会报错,设为true,暴力访问,忽略修饰符
object = constructor.newInstance('男');//参数为构造方法的初始化参数
robot = (Robot) object;
System.out.println(robot);
}
}
运行结果
四、通过反射获取成员变量
public class Robot {
private String name;
public int number;
protected int age;
char gender;
public Robot(){}
@Override
public String toString() {
return "Robot{" +
"name='" + name + '\'' +
", number=" + number +
", age=" + age +
", gender=" + gender +
'}';
}
public void sayHi(String helloSentence){
System.out.println(helloSentence+" "+name);
}
private String throwHello(String tag){
return "Hello "+tag;
}
static {
System.out.println("Hello Robot");
}
}
public class ReflectSample {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
Class rc = Class.forName("com.imooc.javabasic.reflect.Robot");
System.out.println("Class name is " + rc.getName());
System.out.println("获取所有公有的字段");
Field[] fieldArray = rc.getFields();
for(Field f : fieldArray){
System.out.println(f);
}
System.out.println("获取所有的字段(包括私有、受保护、默认的)");
fieldArray = rc.getDeclaredFields();
for(Field f : fieldArray){
System.out.println(f);
}
System.out.println("获取公有字段并调用");
Field f = rc.getField("number");
System.out.println(f);
//获取一个对象
Object obj = rc.getConstructor().newInstance();//实例化Robot,Robot robot = new Robot();
//为字段设置值
f.set(obj, 1);//为Robot对象中的number属性赋值–》robot.number = 1
//验证
Robot robot = (Robot) obj;
System.out.println("编号:" + robot.number);
System.out.println("获取私有字段并调用");
f = rc.getDeclaredField("name");
System.out.println(f);
f.setAccessible(true);//设为true,可以访问私有
f.set(obj,"小爱");
System.out.println("验证:" + robot);
}
}
运行结果
五、通过反射获取方法
public class Robot {
private String name;
public int number;
protected int age;
char gender;
public Robot(){}
@Override
public String toString() {
return "Robot{" +
"name='" + name + '\'' +
", number=" + number +
", age=" + age +
", gender=" + gender +
'}';
}
protected void show(){
System.out.println("受保护,无参");
}
void play(){
System.out.println("默认,无参");
}
public void sayHi(String helloSentence){
System.out.println(helloSentence+" "+name);
}
private String throwHello(String tag){
return "Hello "+tag;
}
static {
System.out.println("Hello Robot");
}
}
public class ReflectSample {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
Class rc = Class.forName("com.imooc.javabasic.reflect.Robot");
System.out.println("Class name is " + rc.getName());
System.out.println("获取所有的公共方法");
rc.getMethods();
Method[] methodArray = rc.getMethods();
for(Method m : methodArray){
System.out.println(m);
}
System.out.println("获取所有的方法");
methodArray = rc.getDeclaredMethods();
for(Method m : methodArray){
System.out.println(m);
}
System.out.println("获取公有的sayHi()方法");
// Robot r = (Robot) rc.newInstance();
// r.sayHi("hello");//这句不是反射,不能调用私有方法
Method m = rc.getMethod("sayHi", String.class);//第二个参数为形参的Class类型对象
System.out.println(m);
//实例化一个Robot对象
Object obj = rc.getConstructor().newInstance();
Robot r = (Robot) obj;
Field name = rc.getDeclaredField("name");
name.setAccessible(true);
name.set(r,"Alice");
m.invoke(obj, "welcome");
//可获取public 以及继承实现的方法,不能获取私有
System.out.println("获取私有的throwHello()方法");
m = rc.getDeclaredMethod("throwHello", String.class);
//可获取public protected private 方法,不能获取继承或实现的方法
System.out.println(m);
m.setAccessible(true);//解除私有限定
Object result = m.invoke(obj, "Bob");//第一个为要调用的对象,第二个为方法的实参
System.out.println("返回:" + result);
}
}
运行结果
六、通过反射运行配置文件
public class Robot {
public void show(){
System.out.println("Hello!!");
}
static {
System.out.println("Hello Robot");
}
}
public class ReflectSample {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException, IOException {
// Class rc = Class.forName("com.imooc.javabasic.reflect.Robot");
// System.out.println("Class name is " + rc.getName());
//通过反射获取Class对象
Class rc = Class.forName(getValue("className"));//"com.imooc.javabasic.reflect.Robot"
//2获取show()方法
Method m = rc.getMethod(getValue("methodName"));//show
//3.调用show()方法
m.invoke(rc.getConstructor().newInstance());
}
public static String getValue(String key) throws IOException {
Properties pro = new Properties();//获取配置文件的对象
FileReader in = new FileReader(System.getProperty("user.dir")+"/src/"+"test.txt");//获取输入流
pro.load(in);//将流加载到配置文件对象中
in.close();
return pro.getProperty(key);//返回根据key获取的value值
}
}
test.txt
className = com.imooc.javabasic.reflect.Robot
methodName = show
运行结果:
七、总结
反射机制相关类
| 类名 | 用途 |
|---|---|
| Class类 | 代表类的实体,在运行的Java应用程序中表示类和接口 |
| Field类 | 代表类的成员变量(成员变量也称为类的属性) |
| Method类 | 代表类的方法 |
| Constructor类 | 代表类的构造方法 |
Class类
Class代表类的实体,在运行的Java应用程序中表示类和接口。
相关的方法
| 方法 | 用途 |
|---|---|
| getClassLoader() | 获得类的加载器 |
| getClasses() | 返回一个数组,数组中包含该类中所有公共类和接口类的对象 |
| getDeclaredClasses() | 返回一个数组,数组中包含该类中所有类和接口类的对象 |
| forName(String className) | 根据类名返回类的对象 |
| getName() | 获得类的完整路径名字 |
| newInstance() | 创建类的实例 |
| getPackage() | 获得类的包 |
| getSimpleName() | 获得类的名字 |
| getSuperclass() | 获得当前类继承的父类的名字 |
| getInterfaces() | 获得当前类实现的类或是接口 |
属性相关的方法
| 方法 | 用途 |
|---|---|
| getField(String name) | 获得某个公有的属性对象 |
| getFields() | 获得所有公有的属性对象 |
| getDeclaredField(String name) | 获得某个属性对象 |
| getDeclaredFields() | 获得所有属性对象 |
构造器相关的方法
| 方法 | 用途 |
|---|---|
| getConstructor(Class…<?> parameterTypes) | 获得该类中与参数类型匹配的公有构造方法 |
| getConstructors() | 获得该类的所有公有构造方法 |
| getDeclaredConstructor(Class…<?> parameterTypes) | 获得该类中与参数类型匹配的构造方法 |
| getDeclaredConstructors() | 获得该类所有构造方法 |
方法相关的方法
| 方法 | 用途 |
|---|---|
| getMethod(String name, Class…<?> parameterTypes) | 获得该类某个公有的方法或继承实现的方法 |
| getMethods() | 获得该类所有公有的方法以及继承实现的方法 |
| getDeclaredMethod(String name, Class…<?> parameterTypes) | 获得该类某个方法,不能获取继承实现的方法 |
| getDeclaredMethods() | 获得该类所有方法,不能获取继承实现的方法 |
Field类
Field代表类的成员变量(成员变量也称为类的属性)。
| 方法 | 用途 |
|---|---|
| equals(Object obj) | 属性与obj相等则返回true |
| get(Object obj) | 获得obj中对应的属性值 |
| set(Object obj, Object value) | 为obj设置对应属性值 |
Method类
Method代表类的方法。
| 方法 | 用途 |
|---|---|
| invoke(Object obj, Object… args) | 传递方法所属对象及方法实参,并调用对应的方法 |
Constructor类
Constructor代表类的构造器。
| 方法 | 用途 |
|---|---|
| newInstance(Object… initargs) | 根据传递的参数创建类的对象,参数为构造方法初始化参数 |
版权声明:本文为sinat_36416436原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。