黑马程序员——高新技术——反射

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

反射

反射技术:Java反射机制是在运行状态中,对任意一个类,都还能知道它的所有属性和方法,能调用任意一个对象的任意方法和属性,这种动态获取信息和动态调用对象方法的功能就是Java怨言的反射机制,总的来说,反射技术可以对类进行解刨。

程序如何使用后期出现的功能类?

通常会提供一个配置文件,用来实现程序的类的扩展功能。对外提供配置文件,将后期出现的子类直接将名字配置到配置文件中就可以了,该应用程序读取配置文件中的内容,并查找和给定名称相同的类文件。操作:1.加载这个类2.创建该类的对象3.调用该类中的内容。应用程序使用的类不确定时,可以通过提供配置文件,让使用者将具体的子类存储到配置文件中,然后该程序通过反射技术,对指定的类进行内容的获取。

好处:

反射技术大大提高了程序的扩展性。

概念:

反射就是把Java类中的各种成分映射成相应的Java类。

Class类

所有的类文件都有共同的属性,所以可以向上抽取,把这些共性内容封装成一个类,这个类就是Class(用来描述字节码文件的对象)。

Class中包含属性有field(字段)、method(方法)、construction(构造函数)

field中有修饰符、类型、变量名等复杂的描述内容,因此也可以将字段封装称为一个对象。用来获取类中field的内容,这个对象的描述叫Field。同样的方法与构造函数封装成对象为Method、Constructor。要想对一个类进行内容的获取,必须要先获取该字节码文件的对象。该对象是Class类型、

Class类描述的信息:类的名字,类的访问属性,类所属于的包名,字段名称的列表,方法名称的列表等,每个字节码就是class的地理对象。

什么叫字节码?

当源程序中用到类时,首先要从硬盘吧这个类的那些二进制代码调到内存中,一个类编译成class放在硬盘上的就是一些二进制代码,要把这些二进制代码加载到内存中来,用这些字节码去复制一个一个对象来。

Class和class的区别:

1.class:Java中的类用于描述一类事物的共性,该类事物有什么属性,对于这个属性的值是什么,有此类的实力对象确定,不同的实力对象有不同的属性值。

2.Class:指的是naval程序中的各个Java类是属于同一类事物,都是Java程序的类,这些类称为Class。是Java程序中各个Java类的总称,它是反射的基石,通过Class类来使用反射。

获取Class对象的三种方式

加载**.class文件进内存时就被封装成了对象,该对象 就是字节码文件对象。

方式一:通过对象的getClass()获取。麻烦处:每次都需要具体的类和该类的对象。以及调用getClass()。

方式二:任何数据类型都具备一个静态的属性class,这个属性直接获取到该类的对应Class对象。

方式三:只要知道类的名称,eg. Class clazz = Class.forName("包名.类名");

九个预定义i的Class:

八种基本数据类型(byte、short 、int、long、float、double、char、Boolean、)的字节码对象和void

Integer.TYPE是Integer类的一个常量,他代表此包装类型包装的基本类型的字节码,所以是int.class相等的。基本数据类型的字节码都可以用与之对应的包装类中的TYPE常量表示。

只要是在源程序中出现的类型都有各自的Class实力对象。数组类型的Class实例对象,可以用Class.isArray()判断是否为数组类型

通过Class对象获取类实例

因为Class没有构造方法,因此只能通过方法获取类实例对象,创建对象的做法:

1.查找并加载**.class文件进内存,并将该文件封装成Class对象

2.在依据Class对象创建该类具体的实例。

3.调用构造函数对对象进行初始化。

用Class对象来获取类实例对象的做法:

1.查找并加载指定名字的字节码文件进内存,并封装成Class对象。

2.通过Class对象的newInstance()创建该类Class对象的类实例。

3.调用newInstance()会使用该类的空参数构造函数进行初始化

例子:


constructor类

如果指定的类中没有空参数的构造函数,或者要创建类对象需要通过指定的构造函数进行初始化。这是就不能使用Class中的newInstance()了。既然要指定的构造函数进行初始化,就必须先获取这个构造函数——constructor。Constructor代表某个类的构造方法。

获取构造方法:

1.得到某个类所有的构造方法:getConstructors()

2.得到某个类的一个构造方法:getConstructor()

创建实例对象:

1.通常方式:Person p = new Person(“zhang”,29);

2.反射方式:Person p = (Person)con.newInstance(“zhang”,29);

注意:

1.创建实例时newInstance方法中的参数列表必须与获取Constructor的方法getConstructor方法中的参数列表一致。

2.newInstance():构造出一个实例对象,每调用一次就构造一个对象。

3.利用Constructor类来创建类实例的好处是可以指定构造函数,而Class类只能利用无参构造函数创建类实例对象。

例子;


Method类

Method类代表某个类中的一个成员方法

专家模式:谁调用这个数据,就是谁在调用它的专家。

常用方法:

getMethods();只获取公共和父类中的方法

getDecharedMethods();获取本类中包含私有。

getMethod();参数是.class

invoke(Object obj);调用方法。如果方法是静态,invoke方法中的对象参数可以为null

获取某个类中的方法

1.通常方式:str.charAt(1)

2.反射方式:Method charAtMethod = Class.forName("java.lang.String").getMethod("charAt",int class);

charAtMethod.invoke(str,1);

说明:如果传递给Method对象的invoke()的第一个参数为null,说明Method对象对应的是一个静态方法。

用反射方式执行某个main方法:

首相明确,在写源程序时,不知使用者的类名,但是这个类有main方法,通过使用者传入的类名,内部通过传入的类名获取main方法,然后执行该类

例子:


会出现的问题:

启动Java程序的main方法的参数是一个字符串数组,通过反射调用main方法时,给invoke传递参数按JDK1.5语法,整个数组都是一个参数,JDK1.4则是数组每个元素是一个参数,因兼容的原因,所以会把数组变成若干单独的参数,所以不能用代码mainMethod.invoke(null,new String[]{“xxx”}),会出现类型不对的问题。

解决时可以用:

mainMethod.invoke(null,new Object[]{new String[]{"xxx"}});

mainMethod.invoke(null,(Object)new String[]{"xxx"});

例子:


注意:

运行时,需要在Run As——RunConfigurations——Arguments——Program arguments中添加要执行的类名。

数组的反射:

维数类型相同得到的字节码是同一份,所以是属于同一个类型,有i相同的Class实例对象。数组字节码的名字:有[和数组对应类型的缩写。

Object[]与String[]没有父子关系,Object 和String有父子关系,所以Object[]与String[]不能强转。

代表数组的Class实例对象的getSuperclass()返回父类为Object类对应的class

Array工具类用于完成对数组的反射操作。

Arrays.asList()方法处理int[]和String[]时的差异。 打印Arrays.asList(a1);还是跟直接打印a1是一样的打印Arrays.asList(a4);就会把a3的元素打印出来。 这是因为此方法在JDK1.4版本中,接收的Object类型的数组,而a3可以作为Object数组传入。但是a1不可以作为Object数组传入,所以只能按照JDK1.5版本来处理。 在JDK1.5版本中,传入的是一个可变参数,所以a1就被当作是一个object,也就是一个参数, 而不是数组传入,所以打印的结果还是跟直接打印a1一样。 



反射的作用:

实现框架的功能。

框架与工具类的区别:

工具类被用户的类调用,框架是调用用户提供的类。

框架要解决的核心问题:

1.框架程序调用以后写的类

2.因写程序时无法知道被调用的类名,无法new,所以反射实现

简单框架程序的步骤:

1.点击File创建一个配置文件,然后写入配置信息。注意,要以键值对的形式写入

2.代码实现,加载配置文件

2.1将文件读取到读取流中,写文件的绝对路径

2.2用Properties类的Load()将流中数据存入集合

2.3关流

3.通过getProperty()获取className,配置的值,就是某个类名。

4.用反射创建对象newInstance()

5.执行程序主体

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值