引言
Java中JRE、JDK、javac.exe、java.exe的区别及Java运行机制
反射的概念
- Java语言的 反射机制
- 在程序运行时,对于任意一个类,都能够知道这个类的所有属性和方法;
- 在程序运行时,对于任意一个对象,都能够调用它的任意属性和方法;
- 动态获取信息以及动态调用对象方法;(后面解释动态的意思)
- 好处
??一般创建类对象,并调用其中属性和方法,无法直接调到private修饰的成员。而利用反射调用它类中的属性和方法时,无视权限修饰符。
- 假设此时用户需要三个类方法:学生类、老师类、工人类,都是标准的JavaBean类
//学生类
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 +
'}';
}
}
//老师类
public class Teacher {
private String name;
private int age;
public Teacher() {
}public Teacher(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 teach(){
System.out.println("老师在上课");
}@Override
public String toString() {
return "Teacher{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
//工人类
public class Worker {
private String name;
private int age;
public Worker() {
}public Worker(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 work(){
System.out.println("工人在工作");
}@Override
public String toString() {
return "Worker{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
一、不用反射
- 作为程序员,我们先写好了学生类,然后写main方法类,将两个类打包给用户使用。
//使用学生类的主方法类
public class TestReflect {
public static void main(String[] args) {
Student stu = new Student();
stu.study();
//学生在学习
}
}
- 之后,我们又添加了老师方法,要交给用户使用。用户需要接收新写的老师方法和新写的main方法类。
//使用学生、老师类的主方法类
public class TestReflect {
public static void main(String[] args) {
Student stu = new Student();
stu.study();
//学生在学习Teacher tea = new Teacher();
tea.teach();
//老师在上课
}
}
- 再之后,我们又添加了工人方法,要交给用户使用。用户需要接收新写的工人方法和新写的main方法类。
//使用学生、老师、工人类的主方法类
public class TestReflect {
public static void main(String[] args) {
Student stu = new Student();
stu.study();
//学生在学习Teacher tea = new Teacher();
tea.teach();
//老师在上课Worker wor = new Worker();
wor.work();
//工人在工作
}
}
- 总结:这里可以看出,每次增加功能,都需要重写main方法,再交给用户使用。代码中,明确说明了要创建的对象是Student、Teacher、Worker...,写死了,不具有灵活性。
- 使用反射,我们增加一个properties配置文件,将创建对象的类名写在此文件中。主方法读到哪个对象,就用反射创建谁的字节码文件对象。读到什么,就创建什么,因此它是动态的。
- 文件结构展示:
文章图片
- properties配置文件:
className=myreflect1.Worker methodName=work
- main方法:(此处涉及反射的用法,可先看懂,学完用法后再来理解一遍)
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;
public class ReflectDemo1 {
public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
//获取系统类加载器,加载prop.properties文件
InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("myreflect1\\prop.properties");
//创建Properties集合
Properties prop = new Properties();
//将文件中的数据读取到集合当中
prop.load(is);
is.close();
//--------下面的代码就是利用反射创建对象并调用方法---------------------//获取字节码文件对象
Class clazz = Class.forName(prop.getProperty("className"));
//获取构造器对象
Constructor constructor = clazz.getConstructor();
//利用构造器对象创建一个对象
Object o = constructor.newInstance();
//获取方法对象
Method method = clazz.getMethod(prop.getProperty("methodName"));
//运行方法
method.invoke(o);
//结果:工人在工作
}
}
- 总结:使用反射后,无论用户需要使用哪个对象,我们只需要把修改好的配置文件发给用户使用。而用户手上的main方法代码无需修改,具有较高的灵活性。
- 利用反射可以无视修饰符获取类里面所有的属性和方法。(在用法中重点讲解)
- 先获取配置文件中的信息,动态获取信息并创建对象、调用方法。
Java反射机制及API使用
推荐阅读
- Java算法|Java 实现OS调度算法之先来先服务算法(FCFS)
- Java算法|Java 实现OS调度算法之短进程优先算法(SJF)
- 选择排序,简单排序,冒泡排序,快速排序的java代码实现
- 算法|Java算法系列3--基于链表自定义队列
- java无限级树生成算法,空间复杂度为O(2n)