反射
反射就是把java类中的各种成分映射成相应的java类。
一个类中的每个成员都可以用相应的反射API类的一个实例对象来表示,通过调用Class类的方法可以得到这些实例对象。
Field类
Field类代表某个类中的一个成员变量
问题:得到的FIeld对象时对应到类上面的成员变量,还是对应到对象上的成员变量?类只有一个,而该类的实例对象有多个,如果是对象关联,那关联的是哪个对象呢?所以字段fieldX代表的是x的定义,而不是具体的x变量
public class ReflectPoint{
private int x;
public int y;
public ReflectPoint(int x,int y){
super();
this.x=x;
this.y=y;
}
}
ReflectPoint pt1=new ReflectPoint(3,5);
Field fieldY=pt1.getClass(),getField("Y");
//fieldY的值不为5,fieldY并不是对象身上的变量,而是类上,要用它去取某个对象上对应的值。
System.out.println(fieldY.get(pt1));
作业:将任意一个对象中的所有String类型的成员变量所对应的字符串内容中的“b”改为“a”。
public class ReflectPoint{
private int x;
public int y;
public String str1="ball";
public String str2="basketball";
pbblic String str3="itcast";
public ReflectPoint(int x,int y){
super();
this.x=x;
this.y=y;
}
public String toString(){
return str1+":"+str2+":"+str3;
}
}
private static void changStringValue(Object obj) throw Exception{
Fild[] fields==obj.getClass.getField();
if(field.getType()==String.class){
String oldValue=(String)field.get(obj);
String newValue= oldValue.replace('b','a');
field.set(obj,newValue);
}
}
Method类
Method类代表某个类中的一个成员方法
可以用这个方法调用各个对象中的方法
调用//str1.charAt(1);
Method methodCharAt=String.class.getMethod("charAt",int.class);
methodCharAt.invoke(调用)(str1,1));invoke是调用方法中的方法
用反射的方式执行某个类中的main方法
写一个程序,这个程序能够根据用户提供的类名,去执行该类中的main方法。
问题:
启动Java程序的main方法的参数是一个字符串数组,即public static void main(String[] args),通过反射方式来调用这个main方法时,如何为invoke方法传递参数呢?
mainMethod.invoke(null,new Object[]){new String[]{"xxx"}});
mainMethod.invoke(null,(Object)new String[]{"xxx"});,编译器会作特殊处理,编译时不把参数当作数组看待,也就不会把数组打散成若干个参数了
数组的反射
int[] a1=new int[3]{1,2,3};
int[] a2=new int[4];
int[][] a3=new int[2][3];
String[] a4=new String[3]{};
System.out.println(a1.getClass()==a2.getClass());
System.out.println(a1.getClass()==a4.getClass());
System.out.println(a1.getClass()==a3.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(a1);
System.out.println(a4);
System.out.println(Arrays.asList((a1))//列表排序输出
System.out.println(Arrays.asList(a4))
数组的反射
具有相同维数和元素类型的数组属于同一个类型,即具有相同的Class实例对象
代表数组的Class实例对象的getSuperClass()方法返回的父类为Object类对应的Class。
基本类型的一维数组可以被当作Object类型使用,不能当作Object[]类型使用;非基本类型的一维数组,既可以当作Object类型使用,又可以当做Object[]类型使用。
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);
}
}
没有办法得到数组中元素的类型
可以得到数组中某一个元素的类型 没法得到整个的
通过 int[] a = new int[3]
a[0].getClass().getName();
pblic class ReflectTest2{
public static void main(String[] args){
}
}
HashCode 方法与 HashSet 类
一种算法 将类放在一个HashSet 集合中 有一个hashCode码 查找时 只要查找对象所在hashCode集合所在的区域就可以
反射的作用--实现框架功能
调用某个类的方法 但是还没有确定类的名称
使用别人做的类 两种方式:
你调用别人或别人调用你
框架与框架要解决的核心问题
框架与工具类有区别,工具类被用户调用,而框架则是调用用户提供的类。
框架要解决的核心问题
因为在写程序是无法知道要被调用的类名,所以,在程序中无法直接new某个类的实例对象,而要用反射方式来做。
getRealPath();得到真实路径
内省-- 了解JavaBean
JavaBean是一种特殊的Java类,主要用于传递数据信息,这种Java类中的方法主要用于访问私有的字段,且方法名符合某种命名规则。
如果要在两个模块之间传递多个信息,可以将这些信息封装到一个JavaBean中,这种JavaBean的实例对象通常称之为值对象(Value Object),这些信息在类中用私有字段来存取,如果读取或设置这些字段的值,则需要通过一些相应的方法来访问。