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

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

 

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

 

一、概述

  JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

  反射把Java类中的各种成分映射成相应的Java类,例如一个Java类中用一个Class类的对象表示,一个类中的组成部分:成员变量,方法,构造方法,包等等信息也用一个个的Java类来表示。表示Java的Class类要提供一系列的方法,来获得其中的变量、方法、构造方法,修饰符、包等信息,这些信息就是用相应的类的实例对象来表示,他们是Field、Method、Contructor、Package等等。

 

二、正文

1Class

      java的Class类是java反射机制的基础,通过Class类我们可以获得关于一个类的相关信息。 虚拟机为每种类型管理一个独一无二的Class对象。也就是说,每个类(型)都有一个Class对象。运行程序时,Java虚拟机(JVM)首先检查是否所要加载的类对应的Class对象是否已经加载。如果没有加载,JVM就会根据类名查找.class文件,并将其Class对象载入。

      下面是获得Class对象的三种方式:

  1. 用Object类的getClass()方法来得到Class对象,这也是最常见的产生Class对象的方法。例如: Class c1 = x.getClass();
  2. 使用Class类的中静态forName()方法获得与字符串对应的Class对象。例如: Class c2=Class.forName("某个类的完整类名”)
  3. 获取Class类型对象的第三个方法非常简单。如果T是一个Java类型,那么T.class就代表了匹配的类对象。例如:    Class cl2 = int.class;

  下面是Cl14ass类的方法:

1. public static Class<?> forName(String className) :natice 方法,动态加载类。非常重要

2. public T newInstance() :根据对象的class新建一个对象,用于反射。非常重要

3. public ClassLoader getClassLoader() :获得类的类加载器

4. public String getName() :获取类或接口的名字

5. public native Class getSuperclass():获取类的父类,继承了父类则返回父类,否则返回

6. public java.net.URL getResource(String name) :根据字符串获得资源

7. public boolean isEnum() :判断是否为枚举类型

8. public native boolean isArray() :判断是否为数组类型

9. public native boolean isPrimitive() :判断是否为基本类型

10. public native int getModifiers() : 反射中获得修饰符

11. public Field getField(String name):反射中获得域成员

12. public Field[] getFields() :获得域数组成员

13. public Method[] getMethods() :获得方法

14. public Constructor<?>[] getConstructors() :获得所有的构造函数

  

2Constructor

  Constructor 类是各种类的构造方法的反射类。Constructor 反射类对象的获得,例如:

  Constructor constructor=String.class.getConstructor(StringBuffer.class);

  构造方法可以用于构造实例对象,例如:

  String str=(String)constructor.newInstance(new StringBuffer("abc"));

  Class本身也还有newInstance方法,可以直接调用,例如:

  String obj=(String)String.class.newInstance(); //类似于调用无参的构造方法。

  下面是一段简单的示例代码:

//通过Constructor对象来创建类实例方法



public static void ConstructorDemo() throws Exception{



       //获取Test类的Class对象



       String className = "cn.itheima.Test";



       Class clazz = Class.forName(className);



             



       //获取指定构造函数的类实例



       Constructor con = clazz.getConstructor(String.class,int.class);



       Test p = (Test) con.newInstance("lisi",30);



       System.out.println(p.toString());



}

 

3Filed

      Java通过Class对象的getFileds()或getField()方法可以获取该类所包括的全部Field或指定的Filed。下面是两种方法来读取或设置Field的值:

1. getXxx(Object obj):获取obj对象该Field的属性值。此处的Xxx对应8个基本类型,如果该属性的类型是引用类型,则取消get后面的Xxx。

2. setXxx(Object obj,Xxx val):将obj对象的该Field设置成val值。此处的Xxx对应8个基本类型,如果该属性的类型是引用类型,在取消set后面的Xxx。

  下面是一段简单的示例代码:

public class Test {



       public final int a=5;



       public static void main(String[] args) {



              Test test = new Test();



              try {  



                      //指定要获取的字段名



                            Field field = Test.class.getField("a");



                            //从Test对象中获取一个整形值;



                            System.out.println(field.getInt(test));



                            //如果不能确定是什么数据类型可以返回一个Object



                            Object obj = field.get(test);



                            System.out.println(obj);



                            //获取对象的数据类型



                            System.out.println(obj.getClass().getName());



  } catch (Exception e) {



              e.printStackTrace();



  }



 }



}

 

 

4、操作数组

      在java.lang.reflect包下提供了一个Array类,Array对象可以代表所有的数组。程序可以通过使用Array来动态地创建数组,操作数组元素等。Array提供了如下几类方法:

1. static Object newInstance(Class<?> componentType,int…length):创建一个具有指定的元素类型、指定维度的新数组

2. Static xxx getXxx(Object array,int index):返回array数组中第index个元素。其中xxx是各种基本数据类型,如果数组元素是引用类型,则该方法变为       get(Object array,int index)

3. static void setXxx(Object array,int index,xxx val):将array数组中第index个元素的值设为val。其中xxx是各种数据类型,如果数组元素是引用类         型,则该方法变成set(Object array,int index,xxx val)

  下面是一段代码:打印传入对象,如果为单一对象,直接打印,如果为数组,则逐一打印数组元素(对数组对象的判断应用)

public void printObject(Object obj){



       Class cla=obj.getClass();



      



       if(cla.isArray()){



       int len=Array.getLength(obj);



      



       for(int i=0;i<len;i++){



              System.out.println(Array.get(obj,i));



  }



  } else{



    System.out.println(obj);



      }



}

 

5Method

      当获得某个类对应的Clss对象后,就可以通过该Class对象的getMethods()方法或者getMethod()方法来获取全部方法或指定方法(这两个方法的返回值是Method数组),或者Method对象。

      具体方法如下:

1. Method[] getMethods(); //只获取公共和父类中的方法



2. Method[] getDeclaredMethods(); //获取本类中包含私有



3. Method  getMethod("方法名",参数.class(如果是空参可以写null))



4. Object invoke(Object obj ,参数); //该方法obj是执行该方法的主调,后面的是实参

  下面是一段示例代码:得到类中的某一个方法。

public class ReflectMethod{



    public static void main(String args[]) throws Exception{



      



          //new String[]{new String("abc"),new String("xyz"),new String("mn")}; //String数组



       //new Object[]{new String("abc"),1}; //Object数组



     



         String str1 = "abcd";



      



          //str1.chatAt(1);



      



          Method methodCharAt = String.class.getMethod("charAt",int.class);



      



          char c = (Character)methodCharAt.invoke(str1,new Object[]{2});



           //使用jdk1.4的语法调用,传一个Object数组进去



      



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



    }



}

 

三、总结

  本文简单的讲述了反射的基本概念,以及反射的基础Class的三种获取方式和常用的方法,还讲述了和反射相关的四个类Filed、Method、Array和Constructor的简单应用。

你可能感兴趣的:(程序员)