黑马程序员--java基础加强-反射

来源:互联网 发布:电脑超频软件 编辑:程序博客网 时间:2024/05/01 14:02

------------------- <a href="http://edu.csdn.net"target="blank">ASP.Net+Android+IO开发S</a>、<a href="http://edu.csdn.net"target="blank">.Net培训</a>、期待与您交流! ----------------------


一、反射的基石--Class类

Java类用于描述一类事物的共性,该类事物有什么属性,没有什么属性,至于这个属性的值是什么,则是由这个类的实例对象来确定,不同的实例对象有不同的属性值。Java程序中的各个Java类属于同一类事物,描述这类事物的Java类名就是Class.


Class类描述了类的名字,类的访问属性,类所属的包名,字段名称的列表,方法名称的类表等。

Class 类的实例表示正在运行的 Java 应用程序中的类和接口。枚举是一种类,注释是一种接口。每个数组属于被映射为 Class 对象的一个类,所有具有相同元素类型和维数的数组都共享该 Class 对象。基本的 Java 类型(boolean、byte、char、short、int、long、float 和 double)和关键字 void 也表示为 Class 对象。这里要特别注意:String是一个类而不是一个基本类型。总之,只要是在源程序中出现的类型,都有各自的Class实例对象。

 Class 没有构造方法。Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的 defineClass 方法自动构造的。


如何得到实例对象对应所的各个字节码呢?主要有三种方法,如下

(1)类名.Class

(2)对象.getClass()

(3)Class.forName("完整类名"),如Class.forName("java.lang.String")。

注:对于Class.forName("完整类名")这种方式有两种意思:第一种,如果这个字节码已经加载到内存在,就直接返回。第二种,如果JVM中还没有这个字节码,用类加载器加载,给字节码缓存,然后返回刚刚加载的字节码。


Class类的几个常用方法:

(1)Constructor  getConstructor(Class <?>... parameterTypes)返回一个Consructor对象,它反映此Class对象所表示的类的指定公共构造方法。

(2)Field  getField(String name)返回一个对象,它反映此Class对象所表示的类或接口的指定公共成员字段。

(3)Field  getDeclareField(String name)返回一个Field对象,该对象反映此Class对象所表示的类或接口的指定已声明字段。

(4)Method  getMethod(String name,Class<?>... parameterTypes)Method返回一个Method对象,它反映此Class对象所表示的类或接口的指定公共成员方法。

(5)Package  getPackage()获取此类的包。

(6)boolean  isPrimitive()判定指定的Class对象是否表示一个基本类型。

(7)T newInstance()创建此Class对象所表示的类的一个新实例。

(8)Class<? super T> getSuperClass()返回表示此Class所表示的实体(类、接口、基本类型或 void)的超类的Class


二、反射

反射就是把Java类中的各种成分映射成相应的java类。例如:一个java类用一个Class类的对象来表示,一个类中的组成部分:成员变量,方法,构造方法,包等信息也是用一个个的Java类来表示。这些信息就是用相应类的实例对象来表示,它们是Field,Method,Contructor,Package等等。


1.Constructor

Constructor类代表某个类中的一个构造方法。

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

例,Constructor[]  constructors = Class.forName(“java.lang.String”).getConstructor();

(2)得到某一个构造方法

例,Constructor  constructor = Class.forName(“java.lang.String”).getConstructor(StringBuffer.class);

注:获得方法时要用到类型。

(3)创建实例对象

通常方法:String  str = new String(new StringBuffer("abc"));

反射方式:String str =(String)constructor.newInstance(new StringBuffer("abc"));

(4)Class.newInstance()方法

例,String obj=(String)Class.forName(“java.lang.String”).newInstance();

该方法内部先得到默认的构造方法,然后用该构造方法创建实例对象。

该方法内部的具体代码,用到了缓存机制来保存默认构造方法的实例对象。


2.Field

Field类提供有关类或接口的单个字段的信息,以及对他的动态访问权限,反射的字段可能是一个类(静态)字段或者实例字段。

例子,

import java.lang.reflect.Field;public class ReflectPoint {private int x;public int y;public ReflectPoint(int x, int y) {super();this.x = x;this.y = y;}}public class Reflect {public static void main(String[] args)throws Exception {ReflectPoint pt1 = new ReflectPoint(3,5);Field fieldY=pt1.getClass().getField("y");System.out.println(fieldY.get(pt1));Field fieldX=pt1.getClass().getDeclaredField("x");//因为变量是私有的,//这里不能直接用getField("x")fieldX.setAccessible(true);//设置可访问System.out.println(fieldX.get(pt1));}}

3.Method

Method代表某个类中的一个成员。

(1)得到类中的某一个方法:

例,Method methodCharAt=Class.forName(“java.lang.String”).getMethod("charAt", int.class);

(2)调用方法:

通常方式:System.out.println(str.charAt(1));

反射方式:System.out.println(CharAt.invoke(str, 1));

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


例,写一个程序,这个程序能够根据用户提供的类名,去执行该类中的main方法。

import java.lang.reflect.Method;public class Reflect {public static void main(String[] args)throws Exception {String startingClassName=args[0];Method mainMethod =Class.forName(startingClassName).getMethod("main", String[].class);mainMethod.invoke(null, (Object)new String[] { "123", "456","789" });}}class TestArguments{public static void main(String[] args){for(String arg:args)System.out.println(arg);}}

4.数组的反射

(1)具有相同维数和元素类型的数组属于同一个类型,即具有相同的Class实例对象。

(2)代表数组的Class实例对象的getSuperClass()方法,返回的父类为Object类对应的Class。

(3)基本数据类型的一维数组可以被当作Object类型使用,不能当作Object[]类型使用;非基本类型的一维数组,既可以当作Object类型使用,又可以当作Object[]类型使用。

(4)Array,asList()方法处理int[]和Sting[]是存在差异的。

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

import java.lang.reflect.Array;import java.util.Arrays;public class Reflect {public static void main(String[] args)throws Exception {int[] a1 = new int[]{1};int[] a2 = new int[4];int[][] a3 = new int[2][3];String[] a4 = new String[]{"a","b","c"};System.out.println(a1.getClass() == a2.getClass());System.out.println(a1.getClass().getName());System.out.println(a1.getClass().getSuperclass().getName());System.out.println(a4.getClass().getSuperclass().getName());Object obj1=a1;Object obj2=a4;Object[] obj3=a3;Object[] obj4=a4;//Object[] obj=a1;System.out.println(a1);System.out.println(a4);System.out.println(Arrays.asList(a1));System.out.println(Arrays.asList(a4));//Object obj=nullprintObj(a4);printObj("xyz");}private static void printObj(Object obj) {Class clazz = obj.getClass();if(clazz.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);}}}

-------------------- <a href="http://edu.csdn.net"target="blank">ASP.Net+Android+IOS开发</a>、<a href="http://edu.csdn.net"target="blank">.Net培训</a>、期待与您交流! ----------------------