Java反射机制解读

反射机制是Java动态性之一,而说到动态性首先得了解动态语言。那么何为动态语言?

一、动态语言
动态语言,是指程序在运行时可以改变其结构:新的函数可以引进,已有的函数可以被删除等结构上的变化。比如常见的JavaScript就是动态语言,除此之外Ruby,Python等也属于动态语言,而C、C++则不属于动态语言。

二、Java是动态语言吗?
从动态语言能在运行时改变程序结构结构或则变量类型上看,Java和C、C++一样都不属于动态语言。 
但是JAVA却又一个非常突出的与动态相关的机制:反射机制。Java通过反射机制,可以在程序运行时加载,探知和使用编译期间完全未知的类,并且可以生成相关类对象实例,从而可以调用其方法或则改变某个属性值。所以JAVA也可以算得上是一个半动态的语言。

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

2.反射的应用场合 
在Java程序中许多对象在运行是都会出现两种类型:编译时类型和运行时类型。 
编译时的类型由声明对象时实用的类型来决定,运行时的类型由实际赋值给对象的类型决定 

如:

Person p=new Student();
其中编译时类型为Person,运行时类型为Student。 
除此之外,程序在运行时还可能接收到外部传入的对象,该对象的编译时类型为Object,但是程序有需要调用该对象的运行时类型的方法。为了解决这些问题,程序需要在运行时发现对象和类的真实信息。然而,如果编译时根本无法预知该对象和类属于哪些类,程序只能依靠运行时信息来发现该对象和类的真实信息,此时就必须使用到反射了。

四、Java反射API
反射API用来生成JVM中的类、接口或则对象的信息。 
- Class类:反射的核心类,可以获取类的属性,方法等信息。 
- Field类:Java.lang.reflec包中的类,表示类的成员变量,可以用来获取和设置类之中的属性值。 
- Method类: Java.lang.reflec包中的类,表示类的方法,它可以用来获取类中的方法信息或者执行方法。 

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

五、使用反射的步骤
1.步骤

  • 获取想要操作的类的Class对象
  • 调用Class类中的方法
  • 使用反射API来操作这些信息
2.获取Class对象的方法

  • 调用某个对象的getClass()方法
Person p=new Person();
Class clazz=p.getClass();

  • 调用某个类的class属性来获取该类对应的Class对象
Class clazz=Person.class;

  • 使用Class类中的forName()静态方法; (最安全/性能最好)
Class clazz=Class.forName("类的全路径"); //最常用

3.获取方法和属性信息

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

Person类,包含属性字段,构造函数和get set方法

package reflection;

public class Person {
    private String name;
    private String gender;
    private int age;

    public Person() {

    }
    public Person(String name, String gender, int age) {
        this.name = name;
        this.gender = gender;
        this.age = age;
    }
    //getter和setter方法
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getGender() {
        return gender;
    }
    public void setGender(String gender) {
        this.gender = gender;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }

    public String toString(){
        return "姓名:"+name+"  性别:"+gender+"  年龄:"+age;
    }

}

使用反射机制:

package reflection;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

/*
 * 通过用户输入类的全路径,来获取该类的成员方法和属性
 * Declared获取全部不管是私有和公有
 * 1.获取访问类的Class对象
 * 2.调用Class对象的方法返回访问类的方法和属性信息
 */
public class Test {

    public static void main(String[] args) {
        try {
            //获取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());
            }

            //动态调用Person的方法,设置和获取Person的属性
            Person person = new Person();
            Class clazz2 = person.getClass();
            Method setName = clazz2.getMethod("setName", String.class);
            setName.invoke(person, "张三");

            Method getMethod = clazz2.getMethod("getName");
            String name = (String) getMethod.invoke(person);
            System.out.println(name);

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

}

输出结果:

public java.lang.String reflection.Person.toString()
public java.lang.String reflection.Person.getName()
public void reflection.Person.setName(java.lang.String)
public java.lang.String reflection.Person.getGender()
public void reflection.Person.setGender(java.lang.String)
public int reflection.Person.getAge()
public void reflection.Person.setAge(int)
private java.lang.String reflection.Person.name
private java.lang.String reflection.Person.gender
private int reflection.Person.age
public reflection.Person()
public reflection.Person(java.lang.String,java.lang.String,int)
张三
4.创建对象
当我们获取到所需类的Class对象后,可以用它来创建对象,创建对象的方法有两种:
  • 使用Class对象的newInstance()方法来创建该Class对象对应类的实例,但是这种方法要求该Class对象对应的类有默认的空构造器。
  • 先使用Class对象获取指定的Constructor对象,再调用Constructor对象的newInstance()方法来创建 Class对象对应类的实例,通过这种方法可以选定构造方法创建实例。
package reflection;

import java.lang.reflect.Constructor;
public class Demo01 {

    public static void main(String[] args) {
        try {
            //获取Person类的Class对象
            Class clazz=Class.forName("reflection.Person"); 
            /**
             * 第一种方法创建对象
             */
            //创建对象
            Person p=(Person) clazz.newInstance();
            //设置属性
            p.setName("张三");
            p.setAge(16);
            p.setGender("男");
            System.out.println(p.toString());

            /**
             * 第二种方法创建
             */
            //获取构造方法
            Constructor c=clazz.getDeclaredConstructor(String.class,String.class,int.class);
            //创建对象并设置属性
            Person p1=(Person) c.newInstance("李四","男",20);
            System.out.println(p1.toString());
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

}

输出结果:

姓名:张三 性别:男 年龄: 16 
姓名:李四 性别:男 年龄: 20

以上是Java反射机制的简单解读




猜你喜欢

转载自blog.csdn.net/luanxiyuan/article/details/80554955
今日推荐