JAVA中的反射机制

91 阅读4分钟

反射机制是什么

1、Java反射机制的核心是在程序运行时动态加载类并获取类的详细信息,从而操作类或对象的属性和方法。本质是JVM得到class对象之后,再通过class对象进行反编译,从而获取对象的各种信息。
2、Java属于先编译再运行的语言,程序中对象的类型在编译期就确定下来了,而当程序在运行时可能需要动态加载某些类,这些类因为之前用不到,所以没有被加载到JVM。通过反射,可以在运行时动态地创建对象并调用其属性,不需要提前在编译期知道运行的对象是谁。

  • 我们编译时知道类或对象的具体信息,此时直接对类和对象进行操作即可,无需使用反射(reflection)
  • 如果编译不知道类或对象的具体信息,此时应该如何做呢?这时就要用到 反射 来实现。比如类的名称放在XML文件中,属性和属性值放在XML文件中,需要在运行时读取XML文件,动态获取类的信息
    这里最典型的就是Servlet,log4j
public class Test {
    public static void main(String[] args) throws Exception {
//编码/编译的时候,已经知道要创建哪个类的对象,此时和反射没关系
        //创建对象
        //Animal an = new Dog();
        Animal an = new Cat();
        //操作属性
        an.nickName ="旺财";        an.color = "黑色";
        //执行方法
        an.shout();        an.shout("门口");
        an.run();        System.out.println(an);
        //编码/编译的时候,不知道要创建哪个类的对象,只有根据运//行时动态获取的内容来创建对象
   //使用Properties类读取属性文件,最终得到了类的完整路径字符串
        String className = "com.bjsxt.why.Cat";
        //创建对象
        //Animal an2 = new "com.bjsxt.why.Cat"();
        Class clazz = Class.forName(className);
        Object an2 = clazz.newInstance();
        //操作属性
        //执行方法
    }
}

反射机制的优缺点

1、优点:

在运行时获得类的各种内容,进行反编译,对于Java这种先编译再运行的语言,能够让我们很方便的创建灵活的代码,这些代码可以在运行时装配,无需在组件之间进行源代码的链接,更加容易实现面向对象。
2、缺点:

(1)反射会消耗一定的系统资源,因此,如果不需要动态地创建一个对象,那么就不需要用反射;

(2)反射调用方法时可以忽略权限检查,因此可能会破坏封装性而导致安全问题。

反射的入口—Class类

-Class类是Java 反射机制的起源和入口

  • 用于获取与类相关的各种信息
  • 提供了获取类信息的相关方法
  • Class类继承自Object类

-Class类是所有类的共同的图纸

  • 每个类有自己的对象,好比图纸和实物的关系
  • 每个类也可看做是一个对象,有共同的图纸Class,存放类的结构信息,比如类的名字、属性、方法、构造方法、父类和接口,能够通过相应方法取出相应信息

-Class类的对象称为类对象

Class类的常用方法:

getFields()——  获得类的public类型的属性。

getDeclaredFields()——  获得类的所有属性

getField(String name)——  获得类的指定属性

getMethods()——  获得类的public类型的方法

getMethod (String name,Class [] args)——  获得类的指定方法

getConstrutors()——  获得类的public类型的构造方法

getConstrutor(Class[] args)——  获得类的特定构造方法

newInstance()——  通过类的无参构造方法创建对象

getName()——  获得类的完整名字

getPackage()——  获取此类所属的包

getSuperclass()——  获得此类的父类对应的Class对象

使用反射创建对象

调用无参数构造方法创建对象

方法1:通过Class的newInstance()方法

  • 该方法要求该Class对象的对应类有无参构造方法
  • 执行newInstance()实际上就是执行无参构造方法来创建该类的实例

方法2:通过Constructor的newInstance()方法

  • 先使用Class对象获取指定的Constructor对象
  • 再调用Constructor对象的newInstance()创建Class对象对应类的对象
  • 通过该方法可选择使用指定构造方法来创建对象

方法1:

public class TestConstructor1 {
    public static void main(String[] args) throws Exception{
        //不使用反射创建对象
        //Dog dog = new Dog();
        //使用反射创建对象
        //1.获取类的完整路径字符串
        String className = "com.bjsxt.why.Dog";
        //2.根据完整路径字符串获取Class对象信息
        Class clazz = Class.forName(className);
        //3.直接使用Class的方法创建对象
        Object obj = clazz.newInstance();
        System.out.println(obj.toString());
    }
}

方法2:

public class TestConstructor2  {
    public static void main(String[] args) throws Exception{
        //不使用反射创建对象
        //Dog dog = new Dog();
        //使用反射创建对象
        //1.获取类的完整路径字符串
        String className = "com.bjsxt.why.Dog";
        //2.根据完整路径字符串获取Class对象信息
        Class clazz = Class.forName(className);
        //3.获取无参数构造方法
        Constructor con = clazz.getConstructor();
        //4.使用无参数构造方法来创建对象
        Object obj = con.newInstance();
        System.out.println(obj);
    }
}