1.反射的定义
Java中的成分映射成Java类。
2.Class类
(1) Class 没有公共构造方法。Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的 defineClass 方法自动构造的,因此不能显式地声明一个Class对象。基本的 Java 类型(boolean、byte、char、short、int、long、float 和 double)和关键字 void 也都对应一个 Class 对象。每个数组属于被映射为 Class 对象的一个类,所有具有相同元素类型和维数的数组都共享该 Class 对象。
(2)获取Class类的三种方法:
A:MyObject x;
Class c1 = x.getClass();
B:Class c2=Class.forName("MyObject");
C: Class cl2 = int.class;
代码:String str1="abc"; //定义一个String类
Class cls1=String.class; //获取String类的第一种方法
Class cls2=str1.getClass(); //获取String类的第二种方法
Class cls3=Class.forName("java.lang.String");// 获取String类的第三种方法
System.out.println(cls1==cls2); //如果是true 则第一种方法和第二种方法相同
System.out.println(cls1==cls3); //如果输出是true 第一种方法和第三种方法相同
System.out.println(cls1);
(3)Class类的常用方法
A:getName()
B:newInstance()
C:isArray()
3.Constructor类
(1)表示一个类中的构造方法
(2)作用:获得所有或者某个构造方法。
(3)代码:Constructor constructor=String.class.getConstructor(StringBuffer.class);//获取StringBuffer类的构造方法
4.Field类
(1)定义:代表某个类中的成员变量。
(2)把String类型中的c改为d
代码:public String str1="ball";
public String str2="basketball";
public String str3="itcast";
public String toString(){
return str1+":"+str2+":"+str3;
}
public class ReflectTest {
public static void main(String[] args)throws Exception{
ReflectPoint rp=new ReflectPoint();
changeStringValue(rp);
System.out.println(rp);
}
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);
}
}
}
}
5.Method类
(1)定义:Method类代表类中的成员方法。
(2)得到类中的某一个方法:
Method m=Class.forName("java.lang.String").getMethod("chatAt",int.class);
(3)调用方法:
invoke方法。
(4)代码:String str1="abc";
Method method1=String.class.getMethod("abcd", int.class);
System.out.println(method1.invoke(str1, 1));
6.用反射的方式执行某个类中的main方法
(1)问题
启动JAVA程序的main方法的参数是一个字符串数组,即public static void main(String [] args),通过反射方式来调用这个main方法时,如何为invoke方法传递参数呢?按jdk1.5的语法,整个数组是一个参数,而按jdk1.4的方法,数组中的每个元素对应该一个参数,当把一个字符串组作为参数给invoke方法时,javac会到底按照哪种语法进行处理呢?
(2)解决办法
mainMethod.invoke(null,new Object[]{new String[]{"xxx"}});
mainMethod.invoke(null,(Object)new String[]{"xxx"};);,编译器会作特殊处理,编译时不把参数当作数组看待,也就不会数组打散成若干个参数了。
7.数组的反射
(1)代码:
final int []a = {10,12,13,14,15}; //定义一个数组
Object o = a;
System.out.println(Array.getLength(o)); //输出数组的长度
for(int i=0;i<Array.getLength(o);i++) {
System.out.print(Array.get(o, i)+" "); // 输出数组
}
System.out.println();
Array.setInt(o, 4, 16); //把O中第5个数字改为16
for(int i=0;i<Array.getLength(o);i++) {
System.out.print(Array.get(o, i)+" "); //最后一个数子改为16
}
System.out.println();
8.HashCode分析
(1)hashCode的存在主要是用于查找的快捷性,如Hashtable,HashMap等,hashCode是用来在散列存储结构中确定对象的存储地址的;
(2)如果两个对象相同,就是适用于equals(java.lang.Object) 方法,那么这两个对象的hashCode一定要相同;
(3)如果对象的equals方法被重写,那么对象的hashCode也尽量重写,并且产生hashCode使用的对象,一定要和equals方法中使用的一致,否则就 会违反上面提到的第2点;
(4)两个对象的hashCode相同,并不一定表示两个对象就相同,也就是不一定适用于equals(java.lang.Object) 方法,只能够说明这两个对象在散列 存储结构中,如Hashtable,他们“存放在同一个篮子里”
9.反射的用途
(1)作用:可以通过一个类名来探察这个类里面的信息,比如说类的属性名,属性名的修饰符,方法名,方法返回值,方法修饰符等等,反射还可以 生成类的实例,通过这个实例定义属性,调用方法,特别是能调用私有的属性和私有的方法。(2)实现框架功能,调用与被调用