大数据——Java反射机制

认识反射

反射机制

Java的反射机制是Java的特性之一,反射机制是构建框架技术的基础所在。
Java反射机制是指在运行状态中,动态获取信息以及冬天调用对象方法的功能。
Java反射有3个动态性质:
(1)运行时生成对象实例。
(2)运行期间调用方法。
(3)运行时更改属性。
通过Java反射,可以实现以下功能:
(1)在运行时判断任意一个对象所属的类。
(2)在运行时构造任意一个类的对象。
(3)在运行时判断任意一个类所具有的方法和属性。
(4)在运行时调用任意一个对象的方法。

Java反射常用API

使用Java反射技术常用的类如下:
(1)Class类:反射的核心类,反射所有的操作都是围绕该类来生成的,通过Class类,可以获取类的属性、方法等内容信息。
(2)Field类:表示类的属性,可以获取和设置类中属性的值。
(3)Method类:表示类的方法,可以用来获取类中方法的信息,或者执行方法。
(4)Constructor类:表示类的构造方法。
在Java程序中使用反射的基本步骤如下:
(1)导入java.lang.reflect.*。
(2)获得需要操作的类的java.lang.Class对象
(3)调用Class的方法获取Field、Method等对象。
(4)使用反射API进行操作。

反射的应用

获取类的信息

通过反射获取类的信息分为两步,首先获取Class对象,然后通过Class对象获取信息。

获取Class对象

每个类被加载后,系统就会为该类生成一个对应的Class对象,通过该Class对象就可以访问Java虚拟机加中的这个类。Java程序中获得Class对象通常有如下3中方式:
(1)调用对象的getClass()方法
getClass()方法是java.lang.Object类中的一个方法,所有的Java对象都可以调用该方法,该方法会返回该对象所属类对应的Class对象。使用方式如以下代码所示:

Student p=new Student()://Student为自定义的学生类型
Class cla=p.getClass();//cla为class对象

(2)调用类的class属性
调用某个类的class属性可获取该类对应的Class对象,这种方式需要在编译期期间就知道类的名称。使用的方式如以下代码所示:

Class cla=Student.class;//Student为自定义的学生类型

上述代码中,Student.class将会返回Student类对应的Class对象。
(3)使用Class类的forName()静态方法
使用Class类的forName()静态方法也可以获取该类对应的Class对象。该方法需要传入字符串参数,该字符串参数的值是某个类的全名,既要在类名前添加完整的包名。

Class cla=Class.forName("com.pb.jadv.reflection.Student");//正确
Class cla=Class.forName("Student")//错误

在上述代码中,如果传入的字符串不是类的全名,就会抛出一个ClassNotFoundException异常。

从Class对象获取信息

在获得了某个类所对应的Class对象之后,程序就可以调用Class对象的方法来获取该类的详细信息。Class类提供了大量实例方法来获取Class对象所对应类的详细信息。
(1)访问Class对应的类所包含的构造方法
访问Class对应的类所包含的构造方法的常用方法如下所示:

方法说明
Constructor getConstructor(Class[] params)返回此Class对象所包含的类的指定的public构造方法,params参数是按声明顺序指定该方法参数类型的Class对象的一个数组。构造方法的参数类型与params所指定的参数类型匹配
Constructor[] getConstructors()返回此Class对象所包含的类的所有public构造方法
Constructor getDeclaredConstructor(Class[] params)返回此Class对象所包含的类的指定构造方法,与构造方法的访问级别无关
Constructor[] getDeclaredConstructort()返回此Class对象所包含的类的所有构造方法,与构造方法的访问级别无关

(2)访问Class对应的类所包含的方法
访问Class对应的类所包含的方法的常用方法如下所示:

方法说明
Method getMethod(String name,Class[] params)返回此Class对象所包含的类的指定的public方法,name参数用于指定方法名称,params参数时按声明顺序标志该方法参数类型的Class对象的一个数组
Method[] getMethod()返回此Class对象所包含的类的所有public方法
Method getDeclaredMethod(String name,Class[]params)返回此Class对象所包含的类的指定方法,与方法的访问级别无关
Method[] getDeclaredMethod()返回此Class对象所包含的类的全部方法,与方法的访问级别无关

(3)访问Class对应的类所包含的属性
访问Class对应的类所包含的属性的常用方法如下所示:

方法说明
Field getField(String name)返回此Class对象所包含的类的指定的public属性,name参数用于指定属性名称
Field[] getFields()返回此Class对象所包含的类的所有public属性
Field getDeclareField(String name)回此Class对象所包含的类的指定属性,与属性的访问级别无关,name表示属性名称
Field getDeclareFields()回此Class对象所包含的类的全部属性,与属性的访问级别无关

Class对象可以获得该类里的成员、包括方法、构造方法及属性。其中方法由Method对象表示,构造方法由Constructor对象表示,属性由Field表示。
Method、Constructor、Field这3个类都定义值java.lang.reflect包下,并实现了java.lang.reflect.Member接口,程序可以通过Method对象来执行对应的方法,通过Constructor对象来调用相应的构造方法创建对象,通过Field对象直接访问并修改对象的属性值。

创建对象

通过反射来创建对象有如下两种方式:
(1)使用Class对象的newInstance()方法创建对象
(2)使用Constructor对象创建对象。
使用Class对象的newInstance()方法来创建该Class对象对应类的实例,这种方式要求该Class对象的对应类有默认构造方法,而执行newInstance()方法时实际上是利用默认构造方法来创建该类的实例。而使用Constructor对象创建对象,要先使用Class对象获取指定的Constructor对象,再调用Constructor对象的newInstance()方法创建该Class对象对应类的实例。通过这种方式可以选择使用某个类的指定构造方法来创建实例。
如果创建Java对象时不是利用默认构造方法,而是使用指定的构造方法,则可以利用Constructor对象,每个Constructor对应一个构造方法。指定构造方法创建Java对象需要如下3个步骤:
(1)获取该类的Class对象。
(2)利用Class对象的getConstructor()方法来获取指定构造方法。
(3)调用Constructor的newInstance()方法创建Java对象。

访问类的属性

使用Field对象可以获取对象的属性。通过Field对象可以对属性进行取值或赋值操作。
最主要的方法:
setAccessible(true)//对获取到的属性设置访问权限。参数为true,可以对私有属性取值和赋值。

访问类的方法

使用Method对象可以调用对象的方法。在Method类中包含一个invoke()方法,方法定义如下:
Objecet invoke(Object obj,Object args)
其中obj是执行该方法的对象,args是执行该方法时传入该方法的参数。
示例一:

import java.lang.reflect.Constructor;
public class TestConstructor {
    public static void main(String[] args) throws Exception{
        Class<Student> c = Student.class;
        Constructor<Student> sClass =
                c.getDeclaredConstructor(int.class,
                        String.class, String.class);
        sClass.setAccessible(true);
        Student s = sClass.newInstance(2, "马爸爸", "爹");
        System.out.println(s);
    }
}

输出结果:
在这里插入图片描述
示例二:

import java.lang.reflect.Method;
public class TestMethod {
    public static void main(String[] args)throws Exception {
        Student s = TestStudent.getStudent();//构造对象
        Class<Student> c = Student.class;
        Method setStuId = c.getDeclaredMethod("setStuId", int.class);//获取方法
        setStuId.setAccessible(true);//权限
        setStuId.invoke(s, 3);//指定对象传入参数
        Method getStudId = c.getDeclaredMethod("getStuId");
        getStudId.setAccessible(true);
        Object stuId = getStudId.invoke(s);
        System.out.println(s);
        System.out.println(stuId);
    }
}

输出结果:在这里插入图片描述
示例三:

import java.lang.reflect.Field;//获取属性
public class TestField {
    public static void main(String[] args) throws Exception{
        Student s = TestStudent.getStudent();
        Class<Student> c = Student.class;
       Field stuId = c.getField("stuId");
        stuId.set(s, 11);
        Field stuName = c.getDeclaredField("stuName");
        stuName.setAccessible(true);
        stuName.set(s,"泡腾片");
        Field[] fields = c.getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
            System.out.println(field.get(s));
        }
        System.out.println(s);
    }
}

输出结果:在这里插入图片描述
示例四:

public class Student {
    public int stuId;
    private String stuName;
    String gender;
  private Student(){
    }
    public Student(int stuId, String stuName, String gender) {
        this.stuId = stuId;
        this.stuName = stuName;
        this.gender = gender;
    }
    private int getStuId() {
        return stuId;
    }
    private void setStuId(int stuId) {
        this.stuId = stuId;
    }
    public String getStuName() {
        return stuName;
    }
    public void setStuName(String stuName) {
        this.stuName = stuName;
    }
    public String getGender() {
        return gender;
    }
    @Override
    public String toString() {
        return "Student{" +
                "stuId=" + stuId +
                ", stuName='" + stuName + '\'' +
                ", gender='" + gender + '\'' +
                '}';
    }
    public void setGender(String gender) {
        this.gender = gender;
    }
}
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class TestStudent<T> {
    public static void main(String[] args) throws Exception {
        TestStudent s = new TestStudent();
//        //获取类对象的另一种方法
//       //① Class<? extends TestStudent> sC = s.getClass();
//        //1、获取类对象
//        Class<Student> stu=Student.class;
//       //② Class ss = Class.forName("cn.kgc.kb09.Student");
//        //2、通过对象获取构造方法
//        Constructor<Student> constructor = stu.getDeclaredConstructor();
//        constructor.setAccessible(true);
//        //3、通过构造方法创建对象
//        Student student = constructor.newInstance();
        //Student student =getStudent();
        TestStudent ts = new TestStudent();
        Student student=(Student) ts.getObject(Student.class);
//                student.stuId = 1;
//        student.gender = "男";
//        student.setStuName("王思聪");
        System.out.println(student);
    }
    //public T getObject(String classPath){
      public T getObject(Class<T> tClass){
        T t=null;
        try {
           // Class<T> tClass = (Class<T>) Class.forName(classPath);
            Constructor<T> c = tClass.getDeclaredConstructor();
            c.setAccessible(true);
            t = c.newInstance();
//        } catch (ClassNotFoundException e) {
//            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        return t;

    }


    public  static Student getStudent(){
        Class<Student> s = Student.class;
        Student stu=null;
        try {
            Constructor<Student> c = s.getDeclaredConstructor();
            c.setAccessible(true);
            stu = c.newInstance();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }return stu;
    }
}

输出结果:在这里插入图片描述

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值