JAVA语言之JavaSE-反射体系操作详解
小标 2018-12-19 来源 : 阅读 1148 评论 0

摘要:本文主要向大家介绍了JAVA语言之JavaSE-反射体系操作详解,通过具体的内容向大家展示,希望对大家学习JAVA语言有所帮助。

本文主要向大家介绍了JAVA语言之JavaSE-反射体系操作详解,通过具体的内容向大家展示,希望对大家学习JAVA语言有所帮助。


反射体系是Java中最有代表性的体系之一,反射是所有Java框架的基础,没有反射体系的话就没有任何JavaEE的框架。


什么是反射?通俗的来讲就是对象的反向处理操作,就是根据已有的类的实例化对象来反推类的组成。一般情况下我们采用的实例化方式是:类名 对象名 = new 构造方法();这是正向操作。


我们现在来观察一下正反两种操作的例子


import java.util.Date;

 

public class Main{

    public static void main(String[] args)throws Exception{

        Date date = new Date();//正向操作

        System.out.println(date);

        Class cls = Class.forName("java.util.Date");//反向操作

        System.out.println(cls.newInstance());

    }

}

   



这里有一个Class,是返向操作(反射)的核心。反向操作是根据对象来取得对象的来源信息,对象的来源信息,主要集中在Class类里,现在我们来介绍一下Class类。


Class类:


首先我们要分清Class和class的区别:class是关键字,Class是一个类,这个类是描述类的类,有点绕口。


可以举一个通俗的例子:对象是由类来创建的,我们可以把对象想象成产品,类是生产产品的图纸,那么,Class类就是画图纸和管理图纸的地方。Class类产生的对象,可以理解成产生产品的图纸。Class类的对象不是由用户自己,而是由JVM来创建的。类类装载的时候,JVM会产生唯一的Class类对象,就是生产出唯一的产品图纸。举个例子,假设用户的程序用到了4个类,那么在程序运行的时候,Class类对象就只有4个,Class类对象的个数与类对象的个数没有关系,就像有很多产品但却只有一份图纸。


我们有三种方法可以拿到某个类的Class对象。


1:Classcls = 已创建对象名.getclass();


public final native Class getClass();

   



这是getclass()方法的源码,它是Object下的方法,意味着所有的类都可以通过此方式拿到其Class对象。此方法返回一个Class对象,这个Class对象描述的就是调用此方法的对象的模板类。这个方法可以更好的体现反操作的本质:通过对象取得其来源的类。不过使用此方法的前提是必须要有一个已经创建好的对象。


2:Classcls = Class.forName(“完整的类名”);


@CallerSensitive

   public static Class forName(String className)

               throws ClassNotFoundException {

       Class caller = Reflection.getCallerClass();

       return forName0(className, true, ClassLoader.getClassLoader(caller), caller);

   }

   



以上是此方法的源码,同样的,这个方法返回一个Class对象,这种方式的好处是,不需要类的实例化对象就可以拿到Class对象,此方法在我们以后的开发中是最常见到的,因为此方法可以从任何地方拿到Class对象,总之我们现在必须对这个方法有所掌握。


3:Classcls = 类名称.class


这个好理解一点,相当于我们知道了类名程之后直接拿到Class对象,相当于直接赋值,在平时的编程中,这种方法也是最常用的一种。


现在我们拿到了Class对象,相当于我们已经拿到了产品的设计图纸,接下来,我们就要生产对象了。


当然,反射的重点根本就不是对象,而是对象的组成,我们可以通过反射拿到对象中的方法,属性,甚至我们可以对其成员无视权限的进行访问......


newInstance()方法


这个方法就是在我们取得Class对象后,实例化类的一个方法。我们先看一下源码。


@CallerSensitive

   public T newInstance()

       throws InstantiationException, IllegalAccessException

   



此方法返回类型为T,我们一般用Object来接收,在有一些情况下,我们会把返回类型强转为其他的类型。


要注意的是,这个方法实例化对象的时候调用的是默认的无参构造。如果Class对象中有其他的构造方法,这个方法就会失灵,我们就要取得该Class对象的构造方法然后才能实例化对象。所以为了方便起见,一般我们的POJO中都会有一个由用户自己提供的一个无参构造方法。


反射体系与类


我们通过反射创建了类的对象,我们就可以通过反射来做出一个对象所能做出所有行为。


取得父类的信息


所有的类都是有父类的,我们拿到Class类对象之后就可以获得其实现的接口或者继承的父类。

   

interface Brother{ }

interface Consin{ }

 

class Father{ }

 

class SonClass extends Father implements Brother,Consin{ }

 

public class Main{

    public static void main(String[] args){

        Class cls = SonClass.class;

        System.out.println(cls.getSuperclass());

        Class[] classes = cls.getInterfaces();

        for(Class c : classes){

            System.out.println(c);

        }

    }

}

   





因为实现的接口是可以有多个的,所以用数组来存放。


反射调用类的构造


一个类中的构造方法可以重载很多,所以如果我们要取得类中的构造方法,需要用到Class类中一些方法。


Constructor类:描述类中构造方法的类


getDeclareConstructor():取得类中指定构造,无视权限


   

@CallerSensitive

   public Constructor<t> getDeclaredConstructor(Class... parameterTypes)

       throws NoSuchMethodException, SecurityException {

       checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);

       return getConstructor0(parameterTypes, Member.DECLARED);

   }</t>

   



这个方法可以取得指定参数的,任何权限的构造方法,我们可以发现此方法的参数都是Class对象,所以我们传参时的参数应该是:类型名.class。这里和包装类没什么关系,比如“int.class”指的其实是描述基本类型int的Class类对象。


getConstructors()取得类中所有public权限构造


@CallerSensitive

   public Constructor[] getConstructors() throws SecurityException {

       checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);

       return copyConstructors(privateGetDeclaredConstructors(true));

   }

   



这个方法返回的时Constructor[]数组,它可以把一个类中的所有构造方法都返回存到一个数组里,这个方法只能把一个类中权限为public的构造方法返回,至于父类的构造方法,是无法获得的。


getDeclaredConstructors()取得类中所有构造,无视权限


@CallerSensitive

   public Constructor[] getDeclaredConstructors() throws SecurityException {

       checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);

       return copyConstructors(privateGetDeclaredConstructors(false));

   }

   



这个方法和getConstructors()差不多,唯一的区别就是它可以把类中的所有构造方法(无权限限制)全部返回。同样无法获得父类的构造方法。


我们拿到构造方法的时候,就要创建实例化对象了,这时候就要用到newInstance方法了,接下来看测试反射获取构造方法的代码的示范


import java.lang.reflect.Constructor;

 

class Person{

    int ss;

    public Person(){}

    public Person(int ss){

        this.ss = ss;

    }

 

}

 

class Student extends Person{

    private String name;

    private int age;

    public String grade;

    public Student(){}

    public Student(String name){

        this.name = name;

    }

    protected Student(String name, int age){

        this.name = name;

        this.age = age;

    }

    private Student(String name, int age, String grade){

        this.name = name;

        this.age = age;

        this.grade = grade;

    }

 

    @Override

    public String toString() {

        return this.name+this.age+this.grade;

    }

}

 

public class Main {

    public static void main(String[] args)throws Exception {

        Class cls4 = Student.class;

        Constructor constructor = cls4.getDeclaredConstructor(String.class,int.class);//取得某种构造方法,无权限限制

        Student student = (Student) constructor.newInstance("liu",20);//实例化对象

//        System.out.println(student);

        Constructor[] constructors = cls4.getConstructors();//拿到类中所有属性为public的构造,拿不到父类的

        for(Constructor c : constructors){

            System.out.println(c);

        }

        Constructor[] constructors1 = cls4.getDeclaredConstructors();//拿到类中所有构造,无权限限制,拿不到父类的

        for(Constructor c1 : constructors1){

            System.out.println(c1);

        }

    }

}

   



反射调用类的普通方法


既然我们可以通过反射调用构造方法,那么同样的,我们也可以调用普通方法,不过与调用构造方法不同的时,使用的类也不同了。我们在获取普通方法时用的是Method类,它用来描述类中的普通方法。


getMethods();取得本类以及父类中所有权限为public的普通方法


@CallerSensitive

   public Method[] getMethods() throws SecurityException {

       checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);

       return copyMethods(privateGetPublicMethods());

   }

   



该方法返回Method[]数组,存放了本类以及父类中的所有权限为public的普通方法,存放在一个Method[]数组里,该方法优先返回本类中的方法,就是说数组前面的元素是本类的普通方法,后面的是父类中的普通方法。


getDeclaredMethods();取得本类中所有普通方法,无视权限



本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注编程语言JAVA频道!

本文由 @小标 发布于职坐标。未经许可,禁止转载。
喜欢 | 1 不喜欢 | 0
看完这篇文章有何感觉?已经有1人表态,100%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式AI+学习就业服务平台 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved