反射技术(一)
在反射中,有个Class类,被称为反射的基石,注意此处的C为大写。
例如在Person类中
Person p1= new Person();
那么就有
Class p1=Person.class();
p1就表示Person 类在内存中存储的字节码文件,该字节码的类型为Class
获取类字节码的方式有三种(那Person类举例):
1.Class p1=Person.class ;
2.p1.getClass();根据对象p1获取对象p1所在对象的字节码
3.Class.forName("类名");在实际开发中类名一般为变量,,开发中使用这一种方式做反射。
Class.forName("类名")方法分为两种情况,一种情况是类已经被加载到虚拟机内存,那么就可以直接返回字节码,另外一种,没有加载,那么就先加载进虚拟机,然后返回字节
码。
在Class中,有九个预定义的实例对象,包括八个基本数据类型,和一个void类型
数组类型的Class实例对象:
数组类型的Class实例对象,用的是Class.isArray()
总之只要在源程序中出现的数据类型,又有各自对应的实例对象。
反射定义:就是把Java类中的各种成分映射成相应的Java类。
反射的内容包括四个:Field,Method,constructor,package
1.Constructor
首先来看看怎么反射Constructor,其他几个反射的内容都是类似,依葫芦画瓢。
Constructor类为构造方法类,作用:
可以通过Constructor得到某个类的所有的构造方法
eg;Constructor constructor[]=Class.forName("java.lang.String").getConstructor();
首选需要创建实例对象:
(1)通常方式:String str =new String(new StringBuffer("abc"));
(2)反射方式:String str=(String)constructor.new Instance(new StringBuffrer("abc"));
Constructor类的基本方法:
getName();得到Constructor所属类的名字;
hashCode();返回此Constructor的哈希值
newInstance*(); 使用此 Constructor
对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。
toString();返回描述此 Constructor
的字符串。
思想和步骤:
1) Constructor constructor=String.classgetConstructor(StringBuffer.class);
第一步获得String的所属类的字节码,表示选择哪个构造方法
2)String str=(String)constructor.newInstance(new StringBuffer("abc"));
第二部把获取的方法强制转换为String类型
此处需要注意:得到方法的时候需要类型;用方法的时候传递的类型要和第一步的保持一致。
使用映射的实例:
package cn.itcast.day1;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;
public class ReflectTest
public static void main(String[] args) throws Exception {
String str1 = "abc";
Class cls1 = str1.getClass();
Class cls2 = String.class;
Class cls3 = Class.forName("java.lang.String");
System.out.println(cls1.isPrimitive());
System.out.println(int.class == Integer.class);
System.out.println(int.class == Integer.TYPE);
System.out.println(int[].class.isPrimitive());
System.out.println(int[].class.isArray());
Constructor constructor1 = String.class
.getConstructor(StringBuffer.class);
String str2 = (String) constructor1
.newInstance(new StringBuffer("abc"));
System.out.println(str2.charAt(2));
ReflectPoint pt1 = new ReflectPoint(3, 5);
Field fieldY = pt1.getClass().getField("y");
System.out.println(fieldY.get(pt1));
Field fieldX = pt1.getClass().getDeclaredField("x");
fieldX.setAccessible(true);
System.out.println(fieldX.get(pt1));
changeStringValue(pt1);
System.out.println(pt1);
Method methodCharAt = String.class.getMethod("charAt", int.class);
System.out.println(methodCharAt.invoke(str1, 1));
System.out.println(methodCharAt.invoke(str1, new Object[] { 0 }));
String startingClassName = args[0];
Method mainMethod=Class.forName(startingClassName).getMethod("main",String[].class);
mainMethod.invoke(null,new Object[]{new String[] { "2", "33", "55" }});
int [] a1=new int[]{1,2,3};
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 aObj1=a1 ;
Object aObj2=a4 ;
Object[] aObj4=a3 ;
Object[] aObj5=a4 ;
System.out.println(Arrays.asList(a1));
System.out.println(a1);
System.out.println(a4);
System.out.println(Arrays.asList(a1));//因为是int类型,jdk1.5 Obkect没法处理int类型
System.out.println(Arrays.asList(a4));
printObject(a4);
printObject("xyz");
}
private static void printObject(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");
} }
private static void changeStringValue(Object obj) throws Exception {
Field[] fields = obj.getClass().getFields();
for (Field field : fields) {
if (field.getType() == String.class) {
String oldValue = (String) field.get(obj);
String newValue = oldValue.replace('b', 'a');
field.set(obj, newValue);
}
}}
}
class TestArguments {
public static void main(String args[]) {
for (String arg : args) {
System.out.println(arg);
}}}
自我学习心得:在学习机制中,学习到反射是用来反射出类字节码中的Field(成员字段),Method,constructor,package一系列信息,是一个很强大的技术,真正的去理解反射是用来做什么的,在上述中有示例代码中的Constructor类的反射,其他的几个也是类似,基本思想是一样的。