---------------------- android培训、java培训、期待与您交流! ----------------------
一.反射的概念
反射就是把Java类中的各种成分映射成相应的java类,Java反射机制主要提供了以下功能:在运行时判断任意一个对象所属的类;在运行时构造任意一个类的对象;在运行时判断任意一个类所具有的成员变量和方法;在运行时调用任意一个对象的方法。类是程序的一部分,每个类都有一个Class对象。换言之,每当编写并且编译了一个新类,就会产生一个Class对象(恰当地说,是被保存在一个同名 的。class文件中)。在运行时,当我们想生成这个类的对象时,运行这个程序的Java虚拟机(JVM)首先检查这个类的Class对象是否已经加载。如果尚未加载,JVM就会根据类名查找。class文件,并将其载入,例如Person类代表人,它的实例对象就是张三,李四这样一个个具体的人, Java程序中的各个Java类属于同一类事物,描述这类事物的Java类名就是Class。
Class类代表java类,它的各个实例对象就是对应各个类在内存中的字节码文件,要得到各个字节码所对应的字节码文件可以有以下方法:类名.class,对象.getClass(),Class.forName((包名)类名)。
Class类中定义了一些固定的方法来获取相应的成员的字节码,例如变量,方法,构造方法,修饰符,包等信息,这些信息就是用相应类的实例对象来表示,它们是Field、Method、Contructor、Package等等。
九种预定义的Class对象:表示八个基本类型和 void。这些类对象由 Java虚拟机创建,与其表示的基本类型同名,即boolean
、byte
、char
、short
、int
、long
、float
和double
,分别等价于Boolean.TYPE,Byte.TYPE,Character.TYPE,Short.TYPE,Integer.TYPE,Long.TYPE,Float.TYPE,Double.TYPE,Void.TYPE。
二.构造方法的反射
得到某个类所有的构造方法,例如:
Constructor [] constructors= Class.forName("java.lang.String").getConstructors();
得到某一个构造方法,例如:
Constructor constructor = Class.forName(“java.lang.String”).getConstructor(StringBuffer.class);
得到构造方法后,即可用构造方法直接获取对象:
通常方式:String str = new String(new StringBuffer("abc"));
反射方式:String str = (String)constructor.newInstance(new StringBuffer("abc"));
三.成员变量的反射
ReflectPoint point = new ReflectPoint(1,7);
Field y = Class.forName("cn.itcast.corejava.ReflectPoint").getField("y");//获得字段y的字节码
System.out.println(y.get(point));//获得指定对象point的y的值
Field x = Class.forName("cn.itcast.corejava.ReflectPoint").getDeclaredField("x");
Field即代表某个类中的一个成员变量,即字节码中的一个变量
实例:获取某个类的字段
/*
需求:获取一个类的所有字段
思路:先获取类的字节码文件,再利用getDeclaredFields方法获取所有的变量
*/
import java.lang.reflect.*;
public class Field1 {
private double d;
public static final int i = 37;
String s = "testing";
String[] s1=new String[]{"0","1","jk"};
int[] in={1,2,3};
public static void main(String args[]) {
try {
Class cls = Class.forName("Field1");
Field fieldlist[] = cls.getDeclaredFields(); //获取给定类所有字段即变量
for (int i = 0; i < fieldlist.length; i++) {
Field fld = fieldlist[i];
System.out.println("name = " + fld.getName());
System.out.println("decl class = " + fld.getDeclaringClass());
System.out.println("type = " + fld.getType());
int mod = fld.getModifiers(); //以整数形式返回由此 Field 对象表示的字段的 Java 语言修饰符
System.out.println("modifiers = " + Modifier.toString(mod)); //Modifier,对类和成员方法,变量解码,把整数形式的java修饰符变成字符串
System.out.println("-----");
System.out.println(Modifier.FINAL);
System.out.println(Modifier.ABSTRACT);
System.out.println(Modifier.isFinal(mod));
System.out.println("-----");
}
}
catch (Throwable e) {
System.err.println(e);
}
}
}
四.成员方法的反射
Method
提供关于类或接口上单独某个方法(以及如何访问该方法)的信息。
实例:用反射调用某对象的方法
/*
需求:用反射机制直接调用特定对象的某方法
思路:先获取类的字节码文件,利用getmethod方法获取特定参数类型的方法,再利用Method类中的invoke方法执行特定对象,特定参数的方法。
*/
package cn.pengpan.day2;
import java.lang.reflect.*;
public class Method1
{
public int meth1(int x,int y)
{
return x*y;
}
public int meth2(int x,int y,int z)
{
return x*y*z;
}
public static void main(String[] args)
{
try {
Class cls=Class.forName("day5.Method1");
Class cl1[]=new Class[2];//新建一个数组装入字节码文件
cl1[0]=Integer.TYPE;
cl1[1]=Integer.TYPE;
Method me1=cls.getMethod("meth1", cl1);//得到指定参数列表的方法
Method1 me2=new Method1();
Object[] cl2=new Object[2];
cl2[0]=new Integer(2);
cl2[1]=new Integer(5);
Object obj=me1.invoke(me2, cl2);//利用invoke方法执行指定对象指定参数
Integer in1=(Integer)obj;
System.out.println(in1.intValue());
} catch (Throwable e) {
System.err.println(e);
}
}
}
用反射的方式执行某个类中的main方法:
class TestArguments{
public static void main(String[] args){
for(String arg : args){
System.out.println(arg);
}
}
}
class ReflectTest
{
public static void main(String[] args) throws Exception {
TestArguments.main(new String[]{"111","222","333"});
String startingClassName = args[0];//代表要执行的类名,从控制台输入
Method mainMethod = Class.forName(startingClassName).getMethod("main", String[].class);
mainMethod.invoke(null, (Object)new String[]{"111","222","333"});//编译器别打散字符串数组,当成一个对象
}
}
五.数组的反射
Array工具类用于完成对数组的反射操作,提供了动态创建和访问 Java 数组的方法。具有相同维数和元素类型的数组属于同一个类型,即具有相同的Class实例对象。代表数组的Class实例对象的getSuperClass()方法返回的父类为Object类对应的Class。基本类型的一维数组可以被当作Object类型使用,不能当作Object[]类型使用;非基本类型的一维数组,既可以当做Object类型使用,又可以当做Object[]类型使用。Arrays.asList()方法处理int[]和String[]时的差异:int类型会输出哈希码,String类型会直接打印。
实例:通过反射建立一个string类型的数组
import java.lang.reflect.*;
public class Array1 {
public static void main(String args[]) {
try {
Class cls = Class.forName("java.lang.String"); //得到String的字节码文件
Object arr = Array.newInstance(cls, 10); //得到数组对象
Array.set(arr, 5, "this is a test"); //设值
String s = (String) Array.get(arr, 5); //得到指定角标位的值
System.out.println(s);
}
catch (Throwable e) {
System.err.println(e);
}
}
}
---------------------- android培训、java培训、期待与您交流! ----------------------