Java反射

什么是反射?Java反射机制?

反射主要是指程序可以访问、检测和修改其本身状态或行为的一种能力。

Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性。使用反射使Java具有动态语言的特性,增强了程序的灵活性和可移植性。

作用

反射被广泛地用于那些需要在运行时检测或修改程序行为的程序中。

(1)在运行时判断任意一个对象所属的类型。

(2)在运行时构造任意一个类的对象。

(3)在运行时判断任意一个类所具有的成员变量和方法。

(4)在运行时调用任意一个对象的方法,甚至可以调用private方法。

==注意:上述功能都是在运行时环境中,而不是在编译时环境中==

用途

MyBatis中为Mapper接口通过反射实现具体的类。

数据库JDBC过程中,加载驱动。

Spring中通过xml配置文件加载不同的对象或类。

等等…

缺点

  1. 性能第一

反射包括了一些动态类型,所以 JVM 无法对这些代码进行优化。因此,反射操作的效
率要比那些非反射操作低得多。我们应该避免在经常被 执行的代码或对性能要求很高的程
序中使用反射。

  1. 安全限制

使用反射技术要求程序必须在一个没有安全限制的环境中运行。

  1. 内部暴露

由于反射允许代码执行一些在正常情况下不被允许的操作(比如访问私有的属性和方
法),所以使用反射可能会导致意料之外的副作用--代码有功能上的错误,降低可移植性。
反射代码破坏了抽象性,因此当平台发生改变的时候,代码的行为就有可能也随着变化。

反射机制中的类

实现Java反射机制的API在Java.lang.reflect包下,具有以下几点。

(1)Class类:代表一个类。

(2)Filed类:代表类的成员变量。

(3)Method类:代表类的方法。

(4)Constructor类:代表类的构造方法。

(5)Array类:提供了动态创建数组及访问数组元素的静态方法。该类中的所有方法都是静态的

具体功能实现

  1. 反射机制获取类有三种方法,我们来获取Employee类型
//第一种方式,会抛ClassNotFoundException异常  
try {
       Class clazz = Class.forName("com.learn.Employee");
       System.out.println(clazz.getName());
} catch (ClassNotFoundException e) {
       e.printStackTrace();
}
//第二种方式,Java中每个类都有class属性
Class clazz2 = Employee.class;
//第三种方式,任何一个Java对象都有getClass 方法 
Employee e = new Employee();
Class clazz3 = e.getClass();//clazz3是运行时类 (e的运行时类是Employee)
  1. 创建对象:获取类以后我们来创建它的对象,利用newInstance
try {
      Class clazz = Class.forName("com.learn.Employee");//ClassNotFoundException异常
      //创建此Class对象所表示的类的一个实例
    Object object = clazz.newInstance();////调用了Employee的无参数构造方法.  
  //IllegalAccessException  InstantiationException 异常

} catch (ClassNotFoundException e) {
      e.printStackTrace();
} catch (IllegalAccessException e) {
      e.printStackTrace();
} catch (InstantiationException e) {
      e.printStackTrace();
}
  1. 获取属性:分为所有的属性和指定的属性:

a.先看获取所有的属性的写法:

//获取整个类
Class c = Class.forName("java.lang.Integer");
//获取所有的属性
Field[] fields = c.getDeclaredFields();
for(Field field:fields){
  System.out.println(
    Modifier.toString(field.getModifiers()) +//获得属性的修饰符,例如public,static等等
    " "+field.getName() );//返回由此 Field对象表示的字段的名称。
}

b.获取特定的属性

//获取类
Class c2 = Class.forName("com.learn.Employee");
//获取id属性
try {
      Field id = c.getDeclaredField("id");
       //实例化这个类赋给对象obj
      Object obj  = c.newInstance();
      //打破封装
      id.setAccessible(true); //使用反射机制可以打破封装性,导致了java对象的属性不安全。
       //给obj对象的id属性赋值"1024"
      id.set(obj, 1024); //set
      //获取属性值
      System.out.println(id.get(obj));

} catch (NoSuchFieldException e) {
      e.printStackTrace();
}
  1. 获取方法,和构造方法
方法关键字含义
getDeclaredMethods(获取所有的方法
getReturnType()获得方法的放回类型
getParameterTypes()获得方法的传入参数类型
getDeclaredMethod(“方法名”,参数类型.class,……)获得特定的方法
构造方法关键字含义
getDeclaredConstructors()获取所有的构造方法
getDeclaredConstructor(参数类型.class,……)获取特定的构造方法
父类和父接口含义
getSuperclass()获取某类的父类
getInterfaces()获取某类实现的接口
  1. 利用反射创建数组

其中的Array类为java.lang.reflect.Array类。

    Class<?> cls = Class.forName("java.lang.String");
    Object array = Array.newInstance(cls,25);
    //往数组里添加内容
    Array.set(array,0,"hello");
    Array.set(array,1,"Java");
    Array.set(array,2,"fuck");
    Array.set(array,3,"Scala");
    Array.set(array,4,"Clojure");
    //获取某一项的内容
    System.out.println(Array.get(array,3));
  1. 调用方法

当我们从类中获取了一个方法后,我们就可以用invoke()方法来调用这个方法。

 //获取整个类
Class c = Class.forName("com.learn.Employee");
//获取此类的实例对象
Object ob = c.newInstance();
try {
  //获取Employee类的function方法
  Method method = c.getMethod("function", String.class);
  //调用method对应的方法 => function("是的!")
  String str = (String) method.invoke(ob,"是的!");
  System.out.println( str );

} catch (NoSuchMethodException e) {
  e.printStackTrace();
}

其中Employee类为

public class Employee {

    private Integer id;
    private String name;

    public String function(String string){
        return "调用function方法"+string;
    }
  ...省略set get 方法
}

这样我们就可以获得类的各种内容,进行了反编译。对于JAVA这种先编译再运行的语言来说,反射机制可以使代码更加灵活,更加容易实现面向对象。

参考文章:

  1. https://blog.csdn.net/cnzl0123/article/details/73459750

  2. https://blog.csdn.net/LemonTreey/article/details/54095043

  3. https://www.sczyh30.com/posts/Java/java-reflection-1/#%E4%B8%80%E3%80%81%E5%9B%9E%E9%A1%BE%EF%BC%9A%E4%BB%80%E4%B9%88%E6%98%AF%E5%8F%8D%E5%B0%84%EF%BC%9F

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值