Java的反射机制

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

1.什么是反射

  Java反射机制主要提供了以下功能:
   在运行时判断任意一个对象所属的类;
   在运行时构造任意一个类的对象;
   在运行时判断任意一个类所具有的成员变量和方法;
   在运行时调用任意一个对象的方法;
   生成动态代理。
  一般而言,开发者们常常谈论到的动态语言,大概认同的一个定义是:“程序运行时,允许改变程序结构或者变量类型,这种语言成为动态语言”。从这个观点来看,Pert、Python、Rudy是动态语言,C++、Java、C#不是动态语言。
  在这样的定义下和分类下,Java不是动态语言,它却有一个非常突出的动态相关机制:Reflection。这个词的意思是“反射、影像、倒影”,在Java里指的是我们可以运行时加载、探知、使用编译期间完全未知的classes。换句话说,Java程序可以加载一个运行时才知道名称的“class”,并获得它的完成构造(但不包括method定义),并生成相应的对象实体、或对其fields设值、或唤起其methods。这种“看透class”的能力被称为introspection(内省、内观、反省)。Reflection和introspection是常被并提的两个术语。

2.反射有什么用

  这里写图片描述
  (图片来自知乎)
  JVM:Java的虚拟机。java之所以能跨平台使用就是因为JVM,这个东西可以理解成一个一个进程、程序,只不过它的作用是用来跑Java代码的。上图是java的内存模型,关注点:方法区;堆;栈。
  为了理解JVM,我们写一个java程序:
  
  Object o = new Object();
  运行!
  首先,JVM启动,后缀“.java”的文件会被编译成一个“.class”的文件;
  然后被类加载器加载进JVM的内存中,类Object加载的方法区,创建了Object类的class对象到堆中(并不是new出来的对象,而是类的类型对象,每一个类只有一个class对象,作为方法区类的数据结构的接口)。
  JVM创建对象前,会先检查类是否被加载,寻找类对应的class对象,如果已经加载好,则会为对象分配内存、初始化,也就是:new Object()
  当程序逐行运行到末尾,程序结束,JVM关闭,程序的运行也就完成了。

  上述的程序对象是我们自己new出来的,程序相当于写死了放进JVM去运行。假如这时,我们突然需要某个请求需要用到某个类,但是这个类没有加载进JVM,是不是需要,终止程序,新写一段代码,new一下,再启动服务器?特别小的程序可能这是最快的方法,但当程序非常庞大,而有急需效率解决的时候,反射就给我们提供了一个非常便捷的处理方式,使得我们可以在程序运行过程中,通过更改一些设置,就可以轻松实现类的加载。
  比如,我们的项目的Dao层,有时候使用的MySQL,有时候使用crale,需要动态地根据实际情况加载驱动类,这个时候就需要使用Java的反射了。
  假设有两个类:
  com.java.dbtest.mysqlConnection;
  com.java.dbtest.oracleConnection;
  我们可能要用到,这时候,我们就可以把程序写的比较动态化,通过
  Class tc = Class.forName(“com.java.dbtest.mysqlConnection”);
  通过全类名让JVM在服务器中找到并加载这个这个类,如果我们需要使用oracle,更换一下全类名即可。

3.怎么使用反射

  反射的实现过程其实就是反编译:即.class→.java
  通过反射机制,访问java对象的属性、方法、构造方法等。
  以下是通过手动输入一个类的全路径,查询该类的所有方法的实例,文件未找到时,返回异常:未找到类文件(ClassNotFoundException)。

public class Test{
    public static void main(String[] args){

        Scanner input = new Scanner(System.in);
        System.out.print("请输入一个java全类名:");
        String cName = input.next();

        showField(cName);   
    }
    public static void main(String name){
        try{

            Class c = Class.forName(name);
            Method m[] = c.getDeclaredMethods();

            System.out.print("该java类的方法有:");

            for(int i = 0;i < m.length;i++){
                System.out.print(m[i].toString());  
            }   
        } catch (ClassNotFoundException e){
            System.out.print("类文件未找到!" + e);    
        }   
    }       
}  
4.Class类

  java.lang.Class类。
  Class类的实例表示正在运行的Java应用程序中的类和接口。枚举是一种类,注释是一种接口。每个数组属于被映射为Class对象的一个类,所有具有相同元素类型和维数的数组都共享该Class对象。基本的Java类型(boolean、byte、char、short、int、long、float和double)和关键字void也表示为Class对象。
  Class类是Java反射机制的入口,封装了一个类或者接口的运行时信息,通过调用Class类的方法可以获取这些信息。
  定义: public final class Class implements Serializable
  说明: final修饰,不可以被子类继承
  构造器: private Class()
  使用方法:

方法案例
使用静态forName()方法Class c = Class.forName(“java.lang.Object”);
使用类名.classClass c = Car.class;
包装类.TYPEClass c = Integer.TYPE;
使用对象中的getClass()方法String name = “user”;
Class c = name.getClass();
Class类.getSuperClass()Class c = String.TYPE.getSuperClass();

  
  常用方法:

方法方法摘要
Field[] getFields()返回一个包含Field 对象数组,存放该类或接口的所有可访问公共属性(含继承的公共属性)。
Field getField(String name)返回一个指定公共属性名的Field 对象(含继承的公共属性)。
Field[] getDeclaredFields()返回一个包含Field 对象数组,存放该类或接口的所有属性(不含继承的属性)。
Field getDeclaredField(String name)返回一个指定属性名的Field 对象(不含继承的属性) 。
Method[] getMethods()返回一个包含Method对象数组,存放该类或接口的所有可访问公共方法(含继承的公共方法)。
Method getMethod(String name,Class[] args)返回一个公共的指定名称和参数的Method对象(含继承的公共方法)。
Method[] getDeclaredMethods()返回一个包含Method对象数组,存放该类或接口的所有方法(不含继承的方法)。
Method[] getDeclaredMethod(String name,Class[] args)返回一个指定名称和参数的Method对象(不含继承的方法)。
Constructor[] getConstrutors()返回一个包含Constructor 对象数组,存放该类的所有公共构造方法。
Constructor getConstrutor(Class[] args)返回一个指定参数列表的公共Constructor对象。
Constructor[] getDeclaredConstructors()返回一个包含Constructor 对象数组,存放该类的所有构造方法。
Constructor getDeclaredConstrutor(Class[] args)返回一个指定参数列表的Constructor对象。
T newInstance()使用无参构造方法创建该类的一个新实例。
String getName()以 String 的形式返回该类的完整名字。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值