Java语言的反射机制

什么是反射机制?

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个 对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为 java语言的反射机制。

Java反射 API

反射API用来生成JVM中的类、接口或则对象的信息。

1. Class 类:反射的核心类,可以获取类的属性,方法等信息。

2. Field 类:Java.lang.reflec 包中的类,表示类的成员变量,可以用来获取和设置类之中的属性值。

3. Method 类: Java.lang.reflec 包中的类,表示类的方法,它可以用来获取类中的方法信息或者执 行方法。

4. Constructor 类: Java.lang.reflec 包中的类,表示类的构造方法。 

反射使用步骤(获取 Class 对象、调用对象方法)

1. 获取想要操作的类的 Class 对象,他是反射的核心,通过 Class 对象我们可以任意调用类的方法。

2. 调用 Class 类中的方法,既就是反射的使用阶段。

3. 使用反射 API 来操作这些信息。

 获取 Class 对象的 3 种方法

调用某个对象的getClass()方法

Person p=new Person();

Class clazz=p.getClass();

调用某个类的class属性来获取该类对应的Class对象

Class clazz=Person.class;

使用Class类中的forName()静态方法(最安全/性能最好)

Class clazz=Class.forName("类的全路径"); (最常用)

当我们获得了想要操作的类的 Class 对象后,可以通过 Class 类中的方法获取并查看该类中的方法和属 性。

//获取 Person 类的 Class 对象
Class clazz=Class.forName("reflection.Person");
//获取 Person 类的所有方法信息
Method[] method=clazz.getDeclaredMethods();
for(Method m:method){
System.out.println(m.toString());
}
//获取 Person 类的所有成员属性信息
Field[] field=clazz.getDeclaredFields(); for(Field
f:field){
System.out.println(f.toString());
}
//获取 Person 类的所有构造方法信息
Constructor[] constructor=clazz.getDeclaredConstructors();
for(Constructor c:constructor){
System.out.println(c.toString());
}

 创建对象的两种方法

Class对象的newInstance()

1. 使用 Class 对象的 newInstance()方法来创建该 Class 对象对应类的实例,但是这种方法要求该 Class 对象对应的类有默认的空构造器。

调用Constructor 对象的newInstance()

2. 先使用 Class 对象获取指定的 Constructor 对象,再调用 Constructor 对象的 newInstance() 方法 来创建 Class 对象对应类的实例,通过这种方法可以选定构造方法创建实例。

//获取 Person 类的 Class 对象
Class clazz=Class.forName("reflection.Person");
//使用.newInstane 方法创建对象
Person p=(Person) clazz.newInstance();
//获取构造方法并创建对象
Constructor
c=clazz.getDeclaredConstructor(String.class,String.class,int.class);
//创建对象并设置属性
Person p1=(Person) c.newInstance("李四","男",20);

静态编译和动态编译

静态编译:在编译时确定类型,绑定对象

动态编译:运行时确定类型,绑定对象

反射机制优缺点

优点: 运行期类型的判断,动态加载类,提高代码灵活度。

缺点: 性能瓶颈:反射相当于一系列解释操作,通知 JVM 要做的事情,性能 比直接的java代码要慢很多。

Java获取反射的三种方法

1.通过new对象实现反射机制

2.通过路径实现反射机制

3.通过类名实现反射机制

 public class Student {
 private int id;
 String name;
 protected boolean sex;
 public float score;
 }

 public class Get {
 //获取反射机制三种方式
 public static void main(String[] args) throws ClassNotFoundException {
 //方式一(通过建立对象)
 Student stu = new Student();
 Class classobj1 = stu.getClass();
 System.out.println(classobj1.getName());
 //方式二(所在通过路径-相对路径)
 Class classobj2 = Class.forName("fanshe.Student");
 System.out.println(classobj2.getName());
 //方式三(通过类名)
 Class classobj3 = Student.class;
 System.out.println(classobj3.getName());
 }
 }

反射中,Class.forName和classloader的区别

java中class.forName()classLoader都可用来对类进行加载。

class.forName()前者除了将类的.class文件加载到jvm中之外,还会对类进行解释,执行类中的static 块。

而classLoader只干一件事情,就是将.class文件加载到jvm中,不会执行static中的内容,只有在 newInstance才会去执行static块。

Class.forName(name, initialize, loader)带参函数也可控制是否加载static块。并且只有调用了 newInstance()方法采用调用构造函数,创建类的对象

反射机制的应用场景有哪些?

反射是框架设计的灵魂。 在我们平时的项目开发过程中,基本上很少会直接使用到反射机制,但这不能说明反射机制没有用,实 际上有很多设计、开发都与反射机制有关,例如模块化的开发,通过反射去调用对应的字节码;动态代 理设计模式也采用了反射机制,还有我们日常使用的 Spring/Hibernate 等框架也大量使用到了反射机 制。

举例:①我们在使用JDBC连接数据库时使用Class.forName()通过反射加载数据库的驱动程序; ②Spring框架也用到很多反射机制, 经典的就是xml的配置模式。Spring 通过 XML 配置模式装载 Bean 的过程:1) 将程序内所有 XML 或 Properties 配置文件加载入内存中; 2)Java类里面解析xml或 properties里面的内容,得到对应实体类的字节码字符串以及相关的属性信息; 3)使用反射机制,根据这 个字符串获得某个类的Class实例; 4)动态配置实例的属性

获取类中的成员方法并执行

1.Class类获取成员方法对象:
方法分类

Method[] getMethods():返回所有公共成员方法对象的数组,包括继承的

Method[] getDeclaredMethods():返回所有成员方法对象的数组,不包括继承的

Method getMethod(String methodName, Class...parameterTypes):返回单个公共成 员方法对象

Method getDeclaredMethod(String methodName, Class...parameterTypes):返回单 个成员方法对象

2.Method类型:
1)表示成员方法的类型,该类型的每个对象,都是一个具体的成员方法

2)成员方法对象具有的功能: 获取成员方法信息,比如:注解,名称,返回值类型,参数类型等等, 及运行方法.

3.Method类用于执行方法的功能:
//参数1: 要执行是那个对象的该方法 p.eat(), 参数1就是p

//参数2: 执行方法是需要的实参,都是Object类型, 基本类型自动装箱

// 返回值类型: Object 表示方法执行完之后的返回值 返回值是基本类的,会自动装箱 Object invoke(Object obj, Object...values):调用obj对象的成员方法,参数是 values,返回值是Object类型.
————————————————

// 反射获取成员方法对象
public class GetMethod {
public static void main(String[] args) throws Exception{
// 获取类对象
Class c1 = Class.forName("com.ujiuye.demo01.Person");
// 获取public修饰的方法,既能获取到自己类中声明公开的方法,也能获取到父类中声明的
公开方法
Method[] ms1 = c1.getMethods();
for (Method method : ms1) {
System.out.println(method);
}
System.out.println("-----------------------------------------");
// 获取所有的方法, 获取到自己类中声明的方法,父类继承的拿不到
Method[] ms2 = c1.getDeclaredMethods();
for (Method method : ms2) {
System.out.println(method);
}
System.out.println("=======================================");
// 创建一个该类的对象
Constructor con = c1.getConstructor();
Object o = con.newInstance();
// 获取某一个public修饰的方法对象
// 参数1: 获取方法对象的方法名
// 参数2: 方法中声明参数的类型的类对象
// getMethod(String methodName, Class...type);
// public void eat()
Method m1 = c1.getMethod("eat");
System.out.println(m1);
暴力反射
代码示例
// 执行方法m1
Object r1 = m1.invoke(o); // o.eat()
System.out.println(r1);
// public void eat(String name)
Method m2 = c1.getMethod("eat", String.class);
System.out.println(m2);
// 执行方法m1
m2.invoke(o, "翔"); // o.eat("翔")
// public int sum(int a, int b)
Method m3 = c1.getMethod("sum", int.class, int.class);
System.out.println(m3);
// 执行方法m3
Object r3 = m3.invoke(o, 10, 20);
System.out.println(r3);
System.out.println(r3.getClass());
// private double sum(double a, double b)
// 获取本类中任何一个方法对象
// getDeclaredMethod(String methodName. Class...type)
Method m4 = c1.getDeclaredMethod("sum", double.class, double.class);
System.out.println(m4);
Method m5 = c1.getDeclaredMethod("buy");
System.out.println(m5);
// 执行方法m4
Object r5 = m5.invoke(o); // o.buy()
System.out.println(r5);
}
}

暴力反射 

1.通过Class类中:

getDeclaredXXX方法: 可以获取类中的所有声明的成员(属性、方法、构造),私有的成员也可以获取 到.但是私有成员进行访问使用时,会因为权限问题导致失败,因此就需要暴力反射解决访问私有的问题.

2.修改该对象的访问权限:

AccessibleObject类是Field,Method和Constructor对象的基类. 它提供了在使用它时反射对象 将其标记为抑制默认Java语言访问控制检查的功能.

setAccessible(boolean flag): true的值表示反射对象应该在使用时抑制Java语言访问检 查,false的值表示反映的对象应该强制执行Java语言访问检查.

3.一旦设定当前对象可以访问,私有的成员也可以被访问,被修改.

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

今晚哒老虎

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值