反射

来源:互联网 发布:淘宝客建站软件 编辑:程序博客网 时间:2024/05/29 15:48

一、反射

     反射是Java程序开发语言的特征之一。它允许动态地发现和绑定类、方法、字段,以及所有其他的由语言所产生的元素

     Java反射所需要的类并不多,主要有java.lang.Class类和java.lang.reflect包中的FieldConstructorMethodArray类。

     Class类:Class类的对象表示正在运行的 Java 应用程序中的类和接口。

     Field类:提供有关类或接口的属性的信息,以及对它的动态访问权限。反射的字段可能是一个类属性或实例属性,简单的理解可以把它看成一个封装反射类的属性的类。

     Constructor类:提供关于类的单个构造方法的信息以及对它的访问权限。它封装了反射类的构造方法。 

      Method类:提供关于类或接口上单独某个方法的信息。所反映的方法可能是类方法或实例方法(包括抽象方法)。它是用来封装反射类方法的一个类。

      Array类:提供了动态创建数组和访问数组的静态方法。该类中的所有方法都是静态方法 

     一个类有多个组成部分,例如:成员变量,方法,构造方法等。反射就是加载类,并解剖出类的各个组成部分。

 

1加载类

Java中有一个Class类用于代表某一个类的字节码。

Class类即然代表某个类的字节码,它当然就要提供加载某个类字节码的方法:forName()。forName方法用于加载某个类的字节码到内存中,并使用class对象进行封另外两种得到class对象的方式

类名.class

对象.getClass() 

// 1、forName()加载类

    Class cls = Class.forName("cn.csdn.reflect.Student");

System.out.println(cls);

// 2、对象.getClass()加载类

Student stu = new Student();

Class cls1 = stu.getClass();

System.out.println(cls1);

// 3、类名.class加载类

Class cls2 = Student.class;

System.out.println(Student.class);

2解剖类

Class对象提供了如下常用方法:

(1)Public  Constructor  getConstructor(Class<?>... parameterTypes) 

    返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法。parameterTypes 参数是 Class 对象的一个数组,这些 Class 对象按声明顺序标识构造方法的形参类型。 如果此 Class 对象表示非静态上下文中声明的内部类,则形参类型作为第一个参数包括显示封闭的实

(2)Public  Method  getMethod(String name, Class<?>... parameterTypes) 

获得此 MethodDescriptor 封装的方法。

(3)Public  Field  getField(String name)

返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共成员字段。name 参数是一个 String,用于指定所需字段的简称。 

要反映的字段由下面的算法确定。设 为此对象所表示的类:

     1.如果 声明一个带有指定名的公共字段,则它就是要反映的字段。

     2.如果在第 步中没有找到任何字段,则该算法被递归地应用于 的每一个直接超接口。直接超接口按其声明顺序进行搜索。

     3.如果在第 1两步没有找到任何字段,且 有一个超类 S,则在 上递归调用该算法。如果 没有超类,则抛出 NoSuchFieldException

这些方法分别用于从类中解剖出构造函数、方法和成员变量(属性)。解剖出的成员分别使用Constructor、 Method 、 Field 对象表示。

// 解析:public Student()

@Test

public void test1() throws Exception{

// 1、加载类   ("cn.csdn.reflect.Student"为包名和类名)

Class cls = Class.forName("cn.csdn.reflect.Student");

// 2、通过无参数的构造器解析

Constructor constructor = cls.getConstructor(null);

// 3、创建类的实例

Student entity = (Student) constructor.newInstance(null);

        //4、调用对象的方法

entity.study();

}

//解析:public Student(String name,int age);

@Test

public void test2()throws Exception{

//1、加载类 ("cn.csdn.reflect.Student"为包名和类名)

Class cls = Class.forName("cn.csdn.reflect.Student");

//2、通过带有参数的构造器解析

Constructor constructor = cls.getConstructor(String.class,int.class);

//3、创建类实例

Student entity = (Student)constructor.newInstance("redarmy",90);

//4、调用方法

entity.study();

System.out.println(entity.getName());

}

//怎么知道 Student类中有哪些构造器

@Test

public void test3()throws Exception{

//1、加载类 ("cn.csdn.reflect.Student"为包名和类名)

Class cls = Class.forName("cn.csdn.reflect.Student");

//2、获取加载类中的所有的构造器

Constructor csr[] = cls.getConstructors();

//3、遍历构造器csr

for(Constructor c:csr){

//打印出构造器参数的类型及构造器名称

 System.out.println(c.toGenericString());

}

     //解析:public cn.csdn.reflect.Student(java.lang.String[])

@Test

public void test4()throws Exception{

//1、加载类

Class cls = Class.forName("cn.csdn.reflect.Student");

//2、根据构造器参数类型获取相应的构造器对象    

Constructor csr = cls.getConstructor(String[].class);

String str[]={"111","123"};

//3、创建实体对象

Student entity = (Student)csr.newInstance((Object)str);

//4、调用方法

entity.study();

}

@Test

public void test5()throws Exception{

//1、加载类

Class cls = Class.forName("cn.csdn.reflect.Student");

//2、根据构造器参数类型获取相应的构造器对象    

Constructor csr = cls.getDeclaredConstructor(List.class);

csr.setAccessible(true);

//3、创建实体对象

Student entity = (Student)csr.newInstance(new ArrayList());

//4、调用方法

entity.study();

}

(1)解析Student中的成员方法

@Test

public void test1() throws Exception{

//1加载类

Class c=Class.forName("cn.csdn.reflect.Student");

//2、解析构造器

Constructor csr=c.getConstructor(null);

//3、创建类的实例

Student entity=(Student) csr.newInstance(null);

/*//第二步解析构造器和第二步创建类的实例改写为

 *Student entity = (Student)cls.newInstance();

 *注意:在使用cls的newInstance()方法的时候必须确保Student类中有一个              无参数的构造器

 */

//返回一个包含某些 Method 对象的数组,这些对象反映此 Class 对象所表示的类或接口(包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口)的公共 member 方法

Method mds[]=c.getMethods();

for(Method m:mds){

System.out.println(m.getName());

System.out.println(m.toGenericString());

}

}

(2)解析Student中中公有的不带参数且无返回值的方法:public void study()方法

@Test

public void test2() throws Exception{

//1加载类

Class c=Class.forName("cn.csdn.reflect.Student");

Student entity=(Student)c.newInstance();

//2解析方法

Method md=c.getMethod("study",null);

//3、执行

Object obj=md.invoke(entity, null);

System.out.println(obj);

}

(3)解析Student中公有的带两个整型的参数且有返回值的方法:public int getSum(int i,int j)

@Test

public void test3() throws Exception{

//1加载类

Class c=Class.forName("cn.csdn.reflect.Student");

Student entity=(Student)c.newInstance();

//2解析方法

Method md=c.getMethod("getSum",int.class,int.class);

//3、执行

Object obj=md.invoke(entity, 10,90);

System.out.println((Integer)obj);

}

(4)解析Student中私有的带参数且无返回值的方法:private void display(String name,int age)

@Test

public void test4() throws Exception{

//1加载类

Class c=Class.forName("cn.csdn.reflect.Student");

Student entity=(Student)c.newInstance();

//2解析方法

Method md=c.getDeclaredMethod("display",  String.class,int.class);

md.setAccessible(true);

md.invoke(entity, "wang",100);

}

(5)解析Student中主方法:public static void main(String[] args)

@Test

public void test5() throws Exception{

//1加载类

Class c=Class.forName("cn.csdn.reflect.Student");

Student entity=(Student)c.newInstance();

//2解析方法

Method md=c.getMethod("main",String[].class);

//3、执行

String arr[]={"2","33","44"};

md.invoke(entity,(Object)arr);

}