AVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
反射的功能有:
示例1:获取对象的类型名称。
package heima; public class ReflectionTest1{//获取对象的类型名称 public static void main(String[] args){ Foo f = new Foo();//创建一个Foo类实例对象 System.out.println(f.getClass().getName());//通过 getClass方法获取对象的类名称 } } class Foo {//定义类Foo public void print() { System.out.println("abc"); } }
输出:
示例2:调用未知对象的方法。
在下列代码中,设想对象的类型是未知的。通过反射,我们可以判断它是否包含print方法,并调用它。
package heima; import java.lang.reflect.Method; public class ReflectionTest2 { public static void main(String[] args){ Foo2 f = new Foo2();//创建一个Foo类实例对象 Method method; try {//注意这个方法会有异常,要抛出异常 method = f.getClass().getMethod("print", new Class<?>[0]);//判断f的类有没有print方法,有就返回方法 method.invoke(f);//调用放回的print方法 } catch (Exception e) { e.printStackTrace(); } } } class Foo2 { public void print() { System.out.println("abc"); } }
输出:
示例3:创建对象
package heima; public class ReflectionTest3 { public static void main(String[] args) { Class<?> c = null; try{//抛出异常 c=Class.forName("heima.Foo3");//获取类Foo3的字节码 }catch(Exception e){ e.printStackTrace(); } // 创建Foo实例 Foo3 f = null; try {//抛出异常 f = (Foo3) c.newInstance();//创建字节码是c的类的实例对象 } catch (Exception e) { e.printStackTrace(); } f.print();//调用Foo3中的print方法 } } class Foo3 { public void print() { System.out.println("abc"); } }
运行结果:
示例4:获取构造函数,并创建对象。
package heima; import java.lang.reflect.Constructor; public class ReflectionTest4 { public static void main(String[] args){ // 创建Class实例 Class<?> c = null; try{ c=Class.forName("heima.Foo4");//获取类Foo4的字节码 }catch(Exception e){ e.printStackTrace(); } // 创建Foo4实例 Foo4 f1 = null; Foo4 f2 = null; Constructor<?> cons[] = c.getConstructors(); // 获取所有的构造函数, try { f1 = (Foo4) cons[0].newInstance();//用无参构造函数fl实例并赋值 f2 = (Foo4) cons[1].newInstance("abc");//用参数是String的构造函数创建f2实例并赋值 } catch (Exception e) { e.printStackTrace(); } f1.print(); f2.print(); } } class Foo4 { String s; public Foo4(){} public Foo4(String s){ this.s=s; } public void print() { System.out.println(s); } }
输出:
此外,你可以通过Class实例来获取该类实现的接口、父类、声明的属性等。
示例5:通过反射来修改数组的大小。
package heima; import java.lang.reflect.Array; public class ReflectionTest5 { public static void main(String[] args) { int[] arr = { 1, 2, 3, 4, 5 };//创建数组 int[] newArr = (int[]) changeArraySize(arr, 10); print(newArr); String[] atr2 = { "a", "b", "c", "d", "e" }; String[] str1 = (String[]) changeArraySize(atr2, 10); print(str1); } public static Object changeArraySize(Object obj, int len) { // 修改数组的大小 Class<?> arr = obj.getClass().getComponentType();//获取传入数组的类型, Object newArray = Array.newInstance(arr, len);//创建一个长度为len类型是arr的数组,用于保存改变后的数组 int co = Array.getLength(obj);// 复制数组 System.arraycopy(obj, 0, newArray, 0, co); return newArray; } public static void print(Object obj) {// 打印数组长度,并打印数组中的元素 Class<?> c = obj.getClass(); if (!c.isArray()) {//判断是否是数组类型 return; } System.out.println(" 数组长度: " + Array.getLength(obj)); for (int i = 0; i < Array.getLength(obj); i++) {//循环获取数组中的元素,注意这里的Array.toString方法起作用了,因为传入的参数是object类型,而不是arrag类型 System.out.print(Array.get(obj, i) + " "); } System.out.println( ); } }
输出:
Java
反射相关的API简介:
位于java。lang。reflect包中
Filed类:代表类的成员变量
Constructor类:代表类的构造方法
Class类
在
java 的Object类中的申明了数个应该在所有的java类中被改写的methods:hashCode(),
equals(),clone(),toString(),getClass()等,其中的getClass()返回一个Class类型的对象。
Class类十分的特殊,它和一般的类一样继承自Object,其实用以表达java程序运行时的 class和 interface,也用来表达 enum,array,primitive,Java Types 以及关键字void,当加载一个类,或者当加载器(class loader)的defineClass()被JVM调用,便产生一个Class对象, Class是Reflection起源,针对任何你想探勘的class(类),唯有现为他产生一个Class的对象,接下来才能经由后者唤起为数十多个的反射API。
Java允许我们从多种途径为一个类class生成对应的Class对象。
Class。getSuperclass():Class类中的方法,返回该Class的父类的Class
Class:类名.class
运行时调用Field内容
变更Field不需要参数和自变量,首先调用Class的getField()并指定field名称,获得特定的Field对象后,便可以直接调用Field的
get(Object obj)和set(Object obj,Object value)方法
运行时生成instance
想生成对象的实体,在反射动态机制中有两种方法,一个针对无变量的构造方法,一个针对带参数的构造方法,,如果想调用带参数的构造方法,就比较的麻烦,不能直接调用Class类中的newInstance(),而是调用Constructor类中newInstance()方法,首先准备一个Class[]作为Constructor的参数类型。然后调用该Class对象的getConstructor()方法获得一个专属的Constructor的对象,最后再准备一个Object[]作为Constructor对象昂的newInstance()方法的实参。
在这里需要说明的是
只有两个类拥有newInstance()方法,分别是Class类和Constructor类Class类中的newInstance()方法是不带参数的,而Constructro类中的newInstance()方法是带参数的需要提供必要的参数。
例:
Class
c=Class.forName("DynTest");
Class[] ptype=new
Class[]{double.class,int.class};
Constructor
ctor=c.getConstructor(ptypr);
Object[] obj=new
Object[]{new Double(3.1415),new Integer(123)};
Object object=ctor.newInstance(obj);
System.out.println(object);
原文:http://www.cnblogs.com/hansheng1988/p/3729059.html