一、反射应用
1、正射的概念
指的是我们知道类的定义和类中的方法名称,直接先创建对象,然后通过对象去调用方法。
例如:
Apple apple = new Apple()
apple.setPrice(15)
2、反射的概念
指的是一开始不知道我要初始化的类对象是什么,自然也无法使用 new 关键字来创建对象,需要用JDK 提供的反射 API 进行反射调用。需要通过类的路径字符串创建对象,通过方法名称字符串调用方法。
例如:
public class Apple {
private int price;
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
public static void main(String[] args) throws Exception{
Class clz = Class.forName("com.jbrh.api.Apple");
Object appleObj =clz.newInstance();
Method setPriceMethod = clz.getMethod("setPrice", int.class);
setPriceMethod.invoke(appleObj, 15);
Method getPriceMethod = clz.getMethod("getPrice");
System.out.println(getPriceMethod.invoke(appleObj));
}
}
3、反射机制
java源文件从创建到运行会经历3个阶段
1)源码阶段
2)Class类对象阶段
3)运行阶段


4、为什么学反射
如果你事先创建好了B类,那么你可以直接创建B对象并调用其方法,那么如果我和另外一位老铁分开开发程序,这个B类是他写的,我们彼此开发完全独立,我需要在我的程序中创建B对象,然后调用B方法获取学生的年龄,这个时候可能这位老铁还没有完成B类的开发,这怎么办?
这就用到了反射了,我在开发程序的时候只需要跟他约定好B类的信息,例如类名称,字段名称、方法名称,我就可以通过反射的机制在他还未写B类的时候动态创建B对象并调用其方法了。等他的B类完成创建之后,我们的代码合并部署运行,我就可以调用到B的方法了。
5、反射的优缺点
1、优点:在运行时获得类的各种内容,进行反编译,对于Java这种先编译再运行的语言,能够让我们很方便的创建灵活的代码,这些代码可以在运行时装配,无需在组件之间进行源代码的链接,更加容易实现面向对象。
2、缺点:
(1)反射会消耗一定的系统资源,因此,如果不需要动态地创建一个对象,那么就不需要用反射;
(2)反射调用方法时可以忽略权限检查,因此可能会破坏封装性而导致安全问题。
6、类对象和类的对象
1)类对象是类加载的产物,封装了一个类的所有信息(类名、父类、接口、属性、方法、构造方法)
2)类的对象是基于某个类new出来的对象,也称为实例对象

7、三种获取类对象的方法
1)通过类的对象,获取类对象
Person person = new Person()
Class cla = person.getClass()
场景:常用于对象的字节码获取方式
2)通过类名获取类对象
Class cla = 类名.class
场景:常用于参数的传递
3)以静态方法通过全类名获取类对象
Class cla = Class.forName("全类名")
场景:常用于读取配置文件,将类名定义在配置文件中。读取文件,加载类对象。
二、Class对象的常用方法
1、获取成员变量

package com.mylifes1110.java.bean
import java.lang.reflect.Field
class Person {
private String name
public Integer age
protected Double score
@Override
public String toString() {
return "Person{" + "name='" + name + '\'' + ", age=" + age + ", score=" + score + '}'
}
}
public class TestReflectFiled {
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
Person person = new Person()
Class<? extends Person> personClass = person.getClass()
//获取 public 修饰的所有成员变量
Field[] fields = personClass.getFields()
for (Field field : fields) {
System.out.println(field)
}
//获取 public 修饰的指定名称的成员变量
Field age = personClass.getField("age")
System.out.println(age)
//获取成员变量age的值
Object ageValue = age.get(person)
System.out.println(ageValue)
//设置age的值
age.set(person, 18)
System.out.println(person)
//获取所有成员变量,不被修饰符限制
Field[] declaredFields = personClass.getDeclaredFields()
for (Field declaredField : declaredFields) {
System.out.println(declaredField)
}
/*
private java.lang.String com.mylifes1110.java.bean.Person.name
public java.lang.Integer com.mylifes1110.java.bean.Person.age
protected java.lang.Double com.mylifes1110.java.bean.Person.score
*/
//获取指定名称的成员变量,不被修饰符限制
Field name = personClass.getDeclaredField("name")
//忽略访问修饰符的安全检查
name.setAccessible(true)
Object nameValue = name.get(person)
System.out.println(nameValue)
}
}
2、获取构造方法

package com.mylifes1110.java.bean;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
class Person {
private String name;
public Integer age;
protected Double score;
public Person() {}
public Person(String name, Integer age, Double score) {
this.name = name;
this.age = age;
this.score = score;
}
@Override
public String toString() {
return "Person{" + "name='" + name + '\'' + ", age=" + age + ", score=" + score + '}';
}
}
public class TestReflectConstructor {
public static void main(String[] args) throws IllegalAccessException, NoSuchMethodException, InvocationTargetException, InstantiationException {
Person person = new Person();
Class<? extends Person> personClass = person.getClass();
Constructor<? extends Person> constructor = personClass.getConstructor();
System.out.println(constructor);
Person p1 = constructor.newInstance();
System.out.println(p1);
Constructor<? extends Person> constructor2 = personClass.getConstructor(String.class, Integer.class, Double.class);
System.out.println(constructor2);
Person p2 = constructor2.newInstance("Ziph", 18, 100.00);
System.out.println(p2);
Constructor<?>[] constructors = personClass.getConstructors();
for (Constructor<?> constructor1 : constructors) {
System.out.println(constructor1);
}
}
}
3、获取方法

package com.mylifes1110.java.bean;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
class Person {
private String name;
public Integer age;
protected Double score;
public void jump() {
System.out.println("跳起来。");
}
public void run(Integer meters) {
System.out.println("我今天跑步跑了" + meters + "米。");
}
@Override
public String toString() {
return "Person{" + "name='" + name + '\'' + ", age=" + age + ", score=" + score + '}';
}
}
public class TestReflectMethod {
public static void main(String[] args) throws IllegalAccessException, NoSuchMethodException, InvocationTargetException {
Person person = new Person();
Class<? extends Person> personClass = person.getClass();
Method jump = personClass.getMethod("jump");
jump.invoke(person);
Method run = personClass.getMethod("run", Integer.class);
run.invoke(person, 2000);
Method[] methods = personClass.getMethods();
for (Method method : methods) {
System.out.println(method);
System.out.println(method.getName());
}
}
}
4、获取类名

public class TestReflectClassName {
public static void main(String[] args) {
Person person = new Person();
Class<? extends Person> personClass = person.getClass();
String className = personClass.getName();
System.out.println(className);
}
}