---------------------- ASP.Net+Android+IOS开发、.Net培训、期待与您交流! ----------------------
一、java的反射机制概述
反射和类的关系:在程序运行状态中,对于任意一个类(指.class文件),都能够知道这个类所有的属性和方法
反射和类对象的关系:反射对于某个类的对象,都能够调用它的任意一个方法和属性
概念:动态获取类的信息以及动态调用类对象的方法和属性的功能称为java语言的反射机制
好处:提高了程序的扩展性
该好处与多态的好处比较:通过反射可以省略new子类对象这个步骤,直接将类名以字符串的形式传递到forName的参数列表中来创建此类实例
Java反射有什么作用呢?
假如我们有两个程序员,一个程序员在写程序的时候,需要使用第二个程序员所写的类,但第二个程序员并没完成他所写的类。那么第一个程序员的代码能否通过编译呢?这是不能通过编译的。利用Java反射的机制,就可以让第一个程序员在没有得到第二个程序员所写的类的时候,来完成自身代码的编译。
二、Class类对象的获取方法
1、java对字节码(.class)文件进行了抽象,用class类来描述
2、Class对象的源码:public final class Class<T>{.......}
final:表示该类不能够被继承
Class类是一个泛型类,T表示Class类对象所属哪个类
Class类没有构造方法,不能够new对象,这种方式是绝对错误的:Class c = new Class();
3、获取Class类对象的五种途径
- 非静态方法getClass():对象名.getClass()
缺点:此种方式创建类对象还需要明确类并创建对象
- 静态属性:class:属性名.class(属性可以是数组、字符串、基本数据类型、类等)
- 静态方法Class.forName():参数列表中传入某类的全类名(例如java.lang.Integer)
优点:仅仅需要类名以字符串的形式传入即可获得class类对象,这种方式最为常见,最为简单
- 非静态方法getSuperclass:对象名.getSuperclass()
- TYPE
面试题:以上方法的作用是?
作用:返回某个类的字节码文件对象,也就是Class对象
注意:
1、如果字节码文件已被加载,那么forName直接返回
2、如果字节码文件还未加载,那么JVM就指示类加载器去加载该文件,并把加载完的字节码文件放入缓冲区,再返回
3、Class对象的常用方法
八种基本数据类型对应八个Class实例对象
基本数据类型对应的Class实例对象不等于包装类对应的Class实例对象
只要是数据类型,就有对应的实例对象
1、获取空参数构造方法并创建对象实体
获取空参构造方法:public T newInstance() throws InstantiationException,IllegalAccessException;
InstantiationException异常:如果该类中没有空参构造 方法,则报该异常
IllegalAccessException异常:如果该类中默认空参构造方法的权限修饰符是private而不是public,则报该异常
public static void getConstructor1(){
try{
Stringname ="cn.itcast.Person";
Class clazz =Class.forName(name);
//调用newInstance方法时,会自动调用Person类的空参构造方法创建Person对象
Objectob j = clazz.newInstance();
}catch(ClassNotFoundException cnfe){
sop(cnfe.toString());
}catch(InstantiationException ite){
sop(ite.toString());
}catch(IllegalAccessException iae){
sop(iae.toString());
}
}
2、获取非空参数构造方法并创建爱你对象实体
获取非空参数构造方法:getConstructor方法 public Constructor<T> getConstructor(Class<?> ...parameterTypes) throws NosuchMethodWxception,SecurityException
package cn.itcast.ly;
import java.lang.reflect.*;
public class Demo {
public static void main(String[] args) throws Exception{
//第一步:创建Class对象实例
Class cla = Class.forName("cn.itcast.ly.Person");
//第二步:创建一个数组
Class[] clas = new Class[]{String.class,int.class};
//第三步:获取构造方法Class类实体
Constructor con = cla.getConstructor(clas);
//第四步:根据Constructor类的newInstance方法创建实体,
//源码:public T newInstance(Object... initargs)
Object[] objs = new Object[]{"Tom",20};
Object obj = con.newInstance(objs);
//第五步:打印
System.out.println(obj);
}
}
class Person{
public Person(String name,int age){
}
}
4、Constructor类中的方法
1、getConstructors()方法
该方法是获取该类中所有构造方法,返回Constructor数组
2、getConstructor()方法和newInstance()方法
该方法时获取到指定参数的构造方法
public class Demo {
public static void main(String[] args)throws Exception {
/*Constructor[] c = Class.forName("java.lang.String").getConstructors();
for(Constructor con : c){
System.out.println(con);
}*/
method();
}
public static void method() throws Exception{
/*
* 源码:
* Constructor<T> getConstructor(Class<?>... parameterTypes)
*
* public T newInstance(Object... initargs)
* throws InstantiationException,
* IllegalAccessException,
* IllegalArgumentException,
* InvocationTargetException
* */
//第一步:通过Class类对象调用getConstructor方法获取指定参数类型的构造函数
Constructor c = Class.forName("java.lang.String").getConstructor(StringBuffer.class);
//第二步:通过Constructor对象调用newInstance方法传入参数获取构造方法并实例化对象
String str = (String)c.newInstance(new StringBuffer("abc"));
System.out.println(str.charAt(2));
}
}
3、getConstructor(Class<?>... parameterTypes)方法
该方法时获取到多个参数的构造函数
public class ClassDemo{
public static void main(String[] args)throws Exception {
//第一步:获取到相应Class类对象
Class cla = Class.forName("cn.itcast.Class.Person");
//第二步:设置参数数组
Class[] clas = new Class[]{double.class,int.class};
//第三步:获取Constructor对象
Constructor con = cla.getConstructor(clas);
//第四步:设置参数数组
Object[] objs = new Object[]{3.1415,2};
//第五步:生成实例对象
Object obj = con.newInstance(objs);
//第六步:打印
System.out.println(obj);
}
}
class Person{
private double d;
private int i;
public Person(double d,int i){
this.d = d;
this.i = i;
}
}
5、Field类
1、Field类源代码:public final class reflect extends AccessibleObject implements Member{.....}
2、Field类属于java.lang.reflect包
3、Field类不能够被继承,不是泛型类,是AccessibleObject类的子类
六种方法:
一、getFields()方法:public Field[] getFields()throws SecurityException {…}
功能:获取类中public修饰的成员字段
二、getDeclaredFields()方法:public Field[] getDeclaredFields()throws SecurityException {…}
功能:获取类中所有修饰符的成员字段
三、getField(String name)方法:public Field getField(String name)throws NoSuchFieldException,SecurityException {…}
功能:根据给定的字段名获取类中public修饰的该字段对象
四、getDeclaredField(String name)方法:public Field getDeclaredField(String name) throws NoSuchFieldException,SecurityException {…}
功能:根绝给定的字段名获取类中所有修饰的该字段对象
五、set(Object obj, Object value)方法:public void set(Object obj, Object value) throws IllegalArgumentException,IllegalAccessException{…};
功能:设置该字段对象与Field关联的值
六、get(Object obj)方法:public Object get(Object obj) throws IllegalArgumentException,IllegalAccessException{…};
功能:获取该字段对象与Filed相关联的值
/*以下是获取属性*/
Class cla_2 = Class.forName("cn.itcast.ly.Person");
/*只能访问public修饰的
Field fie = cla_2.getField("name");
fie.set(obj,"liuyang");
Object str = fie.get(obj);
System.out.println((String)str);*/
Field fie = cla_2.getDeclaredField("name");
fie.setAccessible(true);
fie.set(obj, "liuyang");
Object str = fie.get(obj);
System.out.println((String)str);
}
}
class Person{
private String name;
public Person(String name,int age){
}
public static String method(String name,int age){
return name;
}
}
操作非公有字段的步骤:
1、首先调用getDeclaredField(String name)方法获取指定的字段对象
Filed filed = Class.forName("java.lang.String").getDeclaredField("abc");
2、在取消对反射的对象进行权限检查的机制:
field.setAccessible(true);
6、Method方法
1、Method方法源代码:public final class Method extends AccessibleObject implements …{…}
2、Field类属于java.lang.reflect包
3、Field类不能够被继承,不是泛型类,是AccessibleObject类的子类
五种方法:
一、getMethods()方法:public Field[] getFields()throws SecurityException {…}
功能:获取类中public修饰的成员字段
二、getDeclaredMethods()方法:public Field[] getDeclaredFields()throws SecurityException {…}
功能:获取类中所有修饰符的成员字段
三、getMethod(String name,Class<?>…parameterTypes)方法:public Field getField(String name)throws NoSuchFieldException,SecurityException {…}
功能:根据给定的字段名和参数列表获取类中public修饰的该字段对象(如无参数则为null)
四、getDeclaredMethod(String name,Class<?>…parameterTypes)方法:public Field getDeclaredField(String name) throws NoSuchFieldException,SecurityException {…}
功能:根据给定的字段名和参数列表获取类中所有修饰的该字段对象(如无参数则为null)
五、invoke(Object obj, Object... args)方法:public Object invoke(Object obj, Object... args)throws …;功能:获取指定的方法。参数列表中的第一个obj代表的是调用该方法的对象,
/*以下是获取方法的结果*/
Class cla_1 = Class.forName("cn.itcast.ly.Person");
Class[] clas_1 = new Class[]{String.class,int.class};
Method met = cla_1.getMethod("method", clas_1);
Object[] obj_1 = new Object[]{"haha",12};
//返回方法的结果
Object obj_2 = met.invoke(obj,obj_1);
System.out.println(obj_2);
}
}
class Person{
public Person(String name,int age){
}
public static String method(String name,int age){
return name;
}
}
操作非公有字段的步骤:
1、首先调用getDeclaredMethod(String name)方法获取指定的字段对象
Method method = Class.forName("java.lang.String").getDeclaredMethod("abc");
2、在取消对反射的对象进行权限检查的机制:
field.setAccessible(true);
调用静态方法:invoke方法第一个参数设为null即可
---------------------- ASP.Net+Android+IOS开发、.Net培训、期待与您交流! ----------------------
详细请查看:http://edu.csdn.net