----------------------android培训、java培训、期待与您交流! ----------------------
反射的基本使用方法如何获取构造方法,字段,method 等其他应用
使用反射得到构造方法:通过字节码可以调用getConstructor(Class<?>... parameterTypes) 就可以得到带参数的构造方法其中parameterTypes为参数的字节码类型
其中newInstance()如果不传递参数就是获取无参的构造方法
Point p1=new Point(3,4);
Class clzz=Class.forName("com.nanlove.Test.Point");
//得到构造方法
Constructor constructor=clzz.getConstructor(int.class,int.class);
Point pc=(Point)constructor.newInstance(4,5);
System.out.println(pc.getX());
通过反射获取字段其中getDeclaredField(字段名称)是获取private属性的字段在访问的时候需要设置暴力反射就是setAccessable(true)
Field FieldX=clzz.getDeclaredField("x");
FieldX.setAccessible(true);//当为private的时候就要setAccessable(true);
FieldX.set(p1, 5);
System.out.println(p1.getX());
反射方法,需要传入方法的名称和这个方法的产生如String类中的CharAt()
Methodmethod=Class.forName("java.lang.String").getDeclaredMethod("charAt",int.class);
String str="abc";
System.out.println(method.invoke(str, 2)); //打印出C说明反射成功了
//反射某个类的main方法
StringstartMain=args[0];//传入要反射的类
MethodmainMethod=Class.forName(startMain).getDeclaredMethod("main",String[].class);
mainMethod.invoke(null,(Object)new String[]{"111","fa","123"});//因为main方法是静态的所以不需要传入对象invoke方法的第一个参数就为null
反射main方法出现的问题 main(String args[]) main接受的参数是字符串类型的数组,当你传入一个数组的时候会出现java.lang.IllegalArgumentException:无效参数异常为什么呢?明明传入的就是String的数组,从数组角度上传入的确实是一个String数组的参数但是jdk1.5为了兼容1.4当把引用类型的数组当做是object的数组,不会把他当做一个参数,然会自动拆开每一个元素当做参数,方法需要的是一个参数,而拆开后就成了多个参数了如何处理这个问题有两种解决的方法第一种是把这个数组强转为一个object的对象,这时候就不会拆包了,二是 new Object[]{} 里面在放一个String的数组此时拆包的时候拆到的是一个String的数组然后穿进去就没有错误了
/数组的反射
在反射里面凡是具有相同的元素类型,具有相同的维度每一个数组都属于同一个class
int a[]={1,2};
int b[]={1,4};
System.out.println(a.getClass()==b.getClass());//结果为true所以为同一个class
String str1[]={"afd","bc"};
System.out.println(Arrays.asList(a)); //打印结果是[[I@14318bb]
System.out.println(Arrays.asList(str1));//[afd, bc]
为什么这两个数组打印的结果不一样呢?
对于应用类型的数组打印的是数组里面的内容,基本数据类型的数组打印的是一个地址
愿因是,jdk1.5为了兼容1.4 ,在1.4里面asList ()jdk 接受的是object的数组 而基本数据类型的数组是一个object的对象不是object的数组,在1.5 asList(T... a)接受的是一个可变参数不符合1.4的规则就交给1.5处理!然后打印这个int数组,就是一个地址
那如何打印类似这样子的数组呢使用Array.get(obj,i));就可以获取里面的每一个元素
//打印数组
public static void printArray(Object obj)
{ Class clzz=obj.getClass();
if(clzz.isArray())
{
System.out.println("数组长度"+Array.getLength(obj));
for(int i=0;i<Array.getLength(obj);i++)
{
System.out.println(Array.get(obj, i));
}
}else
{
System.out.println(obj);
}
}
javaBean的操作获取属性和设置属性,
1. //获取bean的属性
public static Object getProperty(Object obj,String propertyName) throws Exception
{
PropertyDescriptor pd= new PropertyDescriptor(propertyName,obj.getClass());
Method methodGetX=pd.getReadMethod();
return methodGetX.invoke(obj);
}
//设置bean的属性
private static void setProperty(Object obj, String propertyName, int value)throws Exception
{
PropertyDescriptor pd= new PropertyDescriptor(propertyName,obj.getClass());
Method methodSetX=pd.getWriteMethod();
methodSetX.invoke(obj,value);
}
对任意一对象中所有的String成员变量的对应的字符“b”改成“a”,思路是这个样子的传入要反射的对象得到这个对象的字节码obj.getClass(),然后通过Class.getFields()这个方法就可以获取所有的字段,迭代所有的字段判断字段的类型的字节码是否为String.class 如果属于就把值取出来field.get(对象),在使用replace()方法替换。
public static void changeStringValue(Object obj)throws Exception
{
Class clzz=obj.getClass();
Field[] fields=clzz.getFields();
for(Field field:fields)
{
if(field.getType()==String.class)
{
String oldValue=(String)field.get(obj);
String newValue=oldValue.replace('b', 'a');
System.out.println(newValue);
}
}
}
通过反射获得泛型的实际类型参数,在框架中,会自动生成一些类主要使用的就是反射和泛型人家是怎么得到这个返回数据类型的因为在编译成字节码的时候参数类型被擦出了
假如有这样子的方法public static voidapplyVercor(Vector<Date> v1){}
我们就来实现如何获取泛型里面的类型
Method appMethod=ReflectTest.class.getMethod("applyVercor", Vector.class);
Type []types=appMethod.getGenericParameterTypes();
ParameterizedType ptype=(ParameterizedType) types[0];
System.out.println(ptype.getRawType());//原始类型
System.out.println(ptype.getActualTypeArguments()[0]);//所有参数列表类型的第一个,有时候是两个参数的
----------------------android培训、java培训、期待与您交流! ----------------------