小标
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
您输入的评论内容中包含违禁敏感词
我知道了

请输入正确的手机号码
请输入正确的验证码
您今天的短信下发次数太多了,明天再试试吧!
我们会在第一时间安排职业规划师联系您!
您也可以联系我们的职业规划师咨询:
版权所有 职坐标-一站式AI+学习就业服务平台 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
沪公网安备 31011502005948号