java基础篇第十一版答案,java基础篇第十一版第七章答案
事实上,我们在日常发展中很少写反思。我们只知道有这么个东西,却对为什么要用它知之甚少。事实上,这个概念在我们的框架中被广泛使用。比如,当我们需要获取某个包下的类并统一处理时,需要知道这些类的名字,通过new创建实例对象;但是如果我们不知道类是什么,或者如果我们只是在最底层打包代码,根本不知道用户定义的类名,那么反射就开始起作用了。我们来学习一下Java动态获取的信息,以及动态调用对象的方法的反射机制。
一、反射概述*反射(Reflection):反射(Reflection)是一种机制,通过这种机制可以对一个类进行解剖,在程序运行过程中可以对一个类中的所有成员(成员变量、成员方法、构造方法)进行操作。*如果看上面对反射的定义,就不太好理解什么是反射了。一般来说,我们在日常开发中使用一个类的时候,一定要知道它是什么类,是用来做什么的。所以我们直接实例化这个类,然后用这个类对象来操作。
苹果apple=新苹果();//直接初始化
apple . set price(4);这样初始化类对象可以理解为“正字法”。反映就是一开始不知道自己要初始化的类对象是什么,自然不能用new关键字来创建对象。此时,我们使用JDK提供的反射API进行反射调用:
class clz=class . forname( com . chenshuyi . reflect . apple );
method method=clz . get method( set price ,int . class);
Constructor构造函数=clz . get constructor();
object object=constructor . new instance();
method.invoke(对象,4);上面两个代码的执行结果其实是完全一样的。但想法完全不同。第一段代码在运行之前已经确定了要运行的类(Apple),第二段代码在运行时通过字符串值知道要运行的类(com.chenshuyi.reflect.Apple)。
那么什么是反思呢?反射只是在运行时知道要操作的类是什么,它可以获取类的完整结构,并在运行时调用相应的方法。
1.1反思过程*反思过程描述:
首先会有一个java文件,然后它会被编译成一个. class文件,字节码文件(将包含当前类中的所有数据信息)会被加载到内存中。
JVM负责管理。为了管理方便,它会为每个加载的类文件生成一个对应的类对象。对应的类型是字节码生成前的java文件。
对应于类名类型,这个类对象代表了对应的类(java文件),所以我们可以通过这个类对应的类对象来获取这个类中的数据信息。
(成员变量、成员方法、构造方法)
结论:我们在使用反射的时候,实际上是获取一个类的类对象,然后通过这个类对象处理(调用和执行)这个类的成员数据!
1.2反射前提我们必须得到这种字节码文件(。类文件)===类对象。
Class:它是一个类,Class的实例表示正在运行的Java应用程序中的类和接口。我们所有的类都是内存中的字节码,然后JVM会为每个类对应的字节码生成一个类对象!然后就可以通过这个类对象访问类中的所有信息了!
Java类和类对象之间的对应关系:
Class======类对象
类中的成员变量====Field对象(在程序运行时为类中的成员变量赋值或获取值)
类中的成员方法====方法对象(类中的成员方法在程序运行时执行)
类中的一个构造方法====一个构造函数对象(在程序运行阶段创建当前类的一个实例对象)。第二,如何获取类对应的类对象。方法一:传递类的静态方法//参数:类的全限定类名(包括包名和类名)。
静态类?forName(字符串类名)//返回与给定字符串名称的类或接口相关联的班级对象10 .上课?clazz=class。forname( com。我是IMA。演示01 _反射。学生);//给定类的全限定类名书写错误,会导致异常!ClassNotFoundException2.2方式二:通过类的对象的对象名方法//先获得到某个类的对象
学生学生=新生();
//通过对象调用方法获得班级对象!
班级?扩展学生类1=学生。getclass();//getClass()方法是从目标继承过来的2.3 方式三:通过类名的静态属性class//通过类名。班级获得班级对象!
班级学生clazz=学生。类;2.4类别对象的常用功能* String get simplename();//获得类名字符串:类名
* String getName();//获得类全名:包名类名
* T new instance();//创建班级对象关联类的对象(公有构造方法)公共静态void main(String[] args)引发异常{
//获得学生类对应的班级对象
班级?clazz=class。forname( com。我是IMA。演示01 _反射。学生);
系统。出去。println(clazz。get simplename());//学生
系统。出去。println(clazz。getname());//com.itheima.demo01_反射。学生
object obj=clazz。新实例();//com.itheima.demo01_反射。学生@1647C
}三、通过班级对象操作构造方法3.1 获得构造器对象建造师?[] getConstructors() //通过班级对象获得类中所有的公有的构造方法对象
建造师?[] getDeclaredConstructors() //通过班级对象获得类中所有的构造方法对象(公有私有,全都要)
构造函数T getConstructor(类?parameterTypes) //通过班级对象获得类中指定公有的构造方法对象!【】
构造函数T getDeclaredConstructor(类?parameterTypes) //通过班级对象获得类中指定的构造方法!(公有私有,全都要)公共静态void main(String[] args)抛出ClassNotFoundException,NoSuchMethodException {
//获得学生类对应的班级对象
班级?clazz=class。forname( com。我是IMA。演示01 _反射。学生);
/////////////////////通过班级对象获得学生类中构造方法对应的构造器对象!///////////////////
//获得类中所有的公共的构造方法对应的对象数组
建造师?[]构造函数=clazz。获取构造函数();
系统。出去。println(数组。tostring(构造函数));//
//获得类中所有的构造方法对应的对象数组(包括私有的!)
建造师?[]DC=克拉兹。getdeclaredconstructors();
系统。出去。println(数组。托斯特林(DC));
//获得类中指定构造方法对应的对象
//构造函数?C1=克拉兹。get构造函数();
建造师?C1=克拉兹。getdeclaredconstructor();
系统。出去。println(C1);
建造师?C2=克拉兹。getdeclaredconstructor(字符串。class,int。类);
系统。出去。println(C2);
}3.2 通过构造方法对象创建类的实例对象T newInstance(对象.initargs)使用由此构造器对象表示的构造函数,使用指定的初始化参数来创建和初始化构造函数的声明类的新实例公共静态void main(String[] args)引发异常{
//获得学生类对应的班级对象
班级?clazz=class。forname( com。我是IMA。演示01 _反射。学生);
//获得学生类中指定的构造方法对象!
建造师?构造函数=clazz。get构造函数();
//根据构造方法对象创建学生类的实例对象!
对象o=构造函数。新实例();
系统。出去。println(o);//com.itheima.demo01_反射。学生@14ae5a5
学生s=(学生)o;
}注意:一旦类中的构造方法使用私人的修饰,那么通过构造方法对象创建了的实例对象就要发生变化!
公共静态void main(String[] args)引发异常{
//获得学生类对应的班级对象
班级?clazz=class。forname( com。我是IMA。演示01 _反射。学生);
//获得学生类中指定的构造方法对象!
建造师?构造函数=clazz。getdeclaredconstructor();//有变动!
//暴力访问!
constructor . set accessible(true);//有变化!
//根据构造函数对象创建学生类的实例对象!
object o=constructor . new instance();
system . out . println(o);//com . ithe IMA . demo 01 _ reflection . student @ 14 ae5a 5
学生s=(学生)o;
}四。获取方法对象方法getmethod(字符串名,类?parameterTypes) //返回指定的公共方法对象!【】
Method[] getMethods() //返回所有公共方法对象的数组,包括由类或接口声明的对象以及从超类和超接口继承的类。
方法getDeclaredMethod(字符串名,类?parameterTypes)//返回指定的方法对象!(私人的也可以玩)
Method[] getDeclaredMethods() //返回所有方法对象的数组,包括公共、受保护、默认(包)访问和私有方法,但不包括继承的方法。公共静态void main(String[] args)引发异常{
//获取学生类对应的类对象
班级?clazz=class . forname( com . ithe IMA . demo 01 _ reflection . student );
//获取学生类及其父类(接口)中的所有公共成员方法
method[]methods 1=clazz . get methods();
for(方法方法:方法1) {
System.out.println(方法);
}
system . out . println(==============================);
//获取学生类中的所有成员方法(包括私有方法)
method[]method 2=clazz . getdeclaredmethods();
for(方法方法:方法2) {
System.out.println(方法);
}
system . out . println(==============================);
//获取指定的方法(不带参数的公共方法)
方法show 1=clazz . get method( show 1 );
//获取指定的方法(私有无参数)
方法show 2=clazz . getdeclaredmethod( show 2 );
//获取指定的方法(公共波段参数)
方法method 1=clazz . get method( method 1 ,string . class);
//创建类的对象
Object obj=clazz.getConstructor()。new instance();
//获取成员方法对象,以便执行此成员方法。
object result=show 1 . invoke(obj);//参数1:当前方法所属的对象!2:show1方法的参数值(如果没有参数定义show 1方法,这里就不写内容了)
System.out.println(结果);//null[定义show1方法时没有返回值]
system . out . println(====================);
//用参数执行公共成员方法
Object o=method1.invoke(obj, 666 );
system . out . println(o);
}4.2通过方法对象/*执行指定的方法
参数obj:当前方法对象所属的类的对象!【实际对象值!】
参数args:给方法对象的参数赋一个值(如果方法对象对应的方法定义没有参数,可以留空;它是可变参数)
返回值对象:当前方法的返回结果!
*/
ObjectInvoke (Objectobj,object.args)//使用指定的参数调用指定对象上由该方法对象表示的基础方法。【】公共静态void main(String[] args)抛出异常{
//获取学生类对应的类对象
班级?clazz=class . forname( com . ithe IMA . demo 01 _ reflection . student );
//创建类的对象
Object obj=clazz.getConstructor()。new instance();
//获取指定的方法(不带参数的公共方法)
方法show 1=clazz . get method( show 1 );
//获取指定的方法(公共波段参数)
方法method 1=clazz . get method( method 1 ,string . class);
//获取成员方法对象,以便执行此成员方法。
object result=show 1 . invoke(obj);//参数1:当前方法所属的对象!2:show1方法的参数值(如果没有参数定义show 1方法,这里就不写内容了)
System.out.println(结果);//null[定义show1方法时没有返回值]
system . out . println(====================);
//用参数执行公共成员方法
Object o=method1.invoke(obj, 666 );
system . out . println(o);
} 5.get Field object public static void main(string[]args)通过用类对象{
//获取学生类对应的类对象
班级?clazz=Student.class
//获取该类的实例
//Object obj=clazz . new instance();
学生s=(学生)clazz . new instance();
//获取公共成员变量对应的字段对象(many)
field[]fields=clazz . get fields();
system . out . println(arrays . tostring(field));
//获取指定的公共成员变量
field name=clazz . get field( name );
System.out.println(名称);
//获取所有成员变量(公共或私有)对应的字段对象
field[]declared fields=clazz . getdeclaredfields();
system . out . println(arrays . tostring(declared fields));
//获取指定的成员变量(公共和私有)
field age=clazz . getdeclaredfield( age );
System.out.println(年龄);
}5.2获取成员变量的值或设置值public static void main(string[]args)throws exception {
//获取学生类对应的类对象
班级?clazz=Student.class
//获取该类的实例
//Object obj=clazz . new instance();
学生s=(学生)clazz . new instance();
///////////////////////////////操作公共成员变量/////////////////
//获取指定的公共成员变量
field name=clazz . get field( name );
//设置公共成员变量的值
system . out . println(s . getname());//null
name.set(s, jack );
//获取指定公共成员变量的值
system . out . println(name . get(s));//插孔
system . out . println(s . getname());//插孔
/////////////////////////////操作私有成员变量/////////////////
//获取指定的成员变量(公共和私有)
field age=clazz . getdeclaredfield( age );
//暴力访问
age . set accessible(true);
//获取值
system . out . println(age . get(s));//0
//设置值
age.set(s,38);
system . out . println(age . get(s));//38
}6在postscript开发过程中,我们不会通过反射机制得到对象,主要是因为反射的代码不容易阅读和理解。其次,代码的维护并不容易。我们将在系统架构期间将其用于底层代码封装或定制工具类。此外,在开发中很少使用反射。
版权归作者所有:原创作品来自博主小二上九8,转载请联系作者取得转载授权,否则将追究法律责任。
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。