--------------------- android培训、java培训、期待与您交流! ----------------------
1、反射就是把Java类中的各个成分映射成相应的Java类
2.Constructor类
Constructor类
|---获得某个类所有的构造方法
|--例子:Constructor[] constructors=Class.forName("java.lang.String").getConstructors();
|--获得某一个构造方法
|--例子:Constructor[] constructors=Class.forName("java.lang.String").getConstructors(StringBuffer.class);
|--这里要用到类型
|--创建实例对象
|--通常方式:String str=new String(new StringBuffer("abc"));
|--反射方式:String str=(String)constructor.newinstance(new StringBuffer("abc"));
|--这里要用到上面相同类型的实例对象
|--Class.newInstance()方法
|--例子:String obj=(String)Class.forName("java.lang.String").newInstance();
|--该方法内部先得到默认的构造方法,然后该构造方法创建实例对象
|--该方法内部的具体代码用到了缓存机制来保存默认构造方法的实例对象
把类的构造方法映射成Constructor的对象
一个类通过Class类加载到内存,由这个类的字节码就可以获得这个类的各种信息,比如String类,
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
public class Test {
public static void main(String[] args){
//获得String类的所有的构造方法的列表
Constructor[] cons = String.class.getConstructors();
for(Constructor con:cons){
//循环打印出String类的所有的构造方法的列表
System.out.println(con);
}
//获得String类的所有的方法的列表
Method[] methods = String.class.getMethods();
for(Method method:methods){
//循环打印出String类的所有的方法的列表
System.out.println(method);
}
}
}
一个类会有多个构造方法的,如果要获得单个的构造方法就要根据构造方法的参数列表给反射传递相应的参数,
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class Test {
public static void main(String[] args) throws SecurityException, NoSuchMethodException,IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException{
//获得String类的参数是一个String的对象的构造方法,参数传递一个String对象
//抛出异常SecurityException, NoSuchMethodException
Constructor stringcon = String.class.getConstructor(String.class);
//反射一个String对象,初始化为1350995917ding
//抛出异常IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException
String str = (String)stringcon.newInstance("1350995917ding"/*传入的这个对象一定要和传入的类型一致*/);
//打印出这个字符串
System.out.println(str);
}
}
成员变量的反射
有这么一个类
public class Test0 {
private int x;
public int y ;
public Test0(int x, int y) {
super();
this.x = x;
this.y = y;
}
}
和这个类
import java.lang.reflect.Field;
public class Test {
public static void main(String[] args) throws NoSuchFieldException{
Test0 test0 = new Test0(3,5);
Field fieldy = test0.getClass().getField("y");
//fieldy的只是多少呢?5吗?不是的。
//fieldy代表的是test0.getClass()这个字节码创建出来的一个成员变量y,这个成员变量 //之时在test0是5,这个值与fieldy无关。
//所以fieldy不是对象的变量而是类上的变量,要用它取对象上对应的值
System.out.println(fieldy.get(test0));//这个是5
}
}
第二个类改变一下
import java.lang.reflect.Field;
public class Test {
public static void main(String[] args) throws NoSuchFieldException{
Test0 test0 = new Test0(3,5);
Field fieldx = test0.getClass().getField("x");
System.out.println(fieldx);
}
}
这就会报错Exception in thread "main" java.lang.NoSuchFieldException: x
at java.lang.Class.getField(Class.java:1520)
at test.Test.main(Test.java:36)
(没有这个字段)
这是因为x是私有的
要获取私有字段应该这样
import java.lang.reflect.Field;
public class Test {
public static void main(String[] args) throws NoSuchFieldException{
Test0 test0 = new Test0(3,5);
//看到声明的变量,只要是声明过的就能看到
Field fieldx = test0.getClass().getDeclaredField("x");
//设置可获取的属性为true,否则只能看到不能获取()
fieldx.setAccessible(true);
System.out.println(fieldx.get(test0));
}
}
3、总结
1、具有相同维数和元素类型的数组属于同一个类型,即具有相同的Class实例对象
2、代表数组的Class实例对象的getSuperClass()方法返回的父类为Object类对应的Class
3、基本类型的一维数组可以被当做Object类型来使用,不能当做Object[]来使用,因为int
属于基本类型.非基本类型的一维数组既可以当做Object类型使用有可以当做Object[]来使用
4、Arrays.asList()方法处理int[]和String[]时的差异:
|--在jdk1.4中asList方法的定义:public static List asList(Object[] a);
|--在jdk1.5中asList方法的定义:public static List<T> asList(T ... a);
|--当我们传递a1的时候,因为a1是一个int[]不能转化为Object[],所以不能满足jdk1.4中方法参数的
|--定义标准,转而交给jdk1.5所定义的方法来处理,在jdk1.5的定义中参数是一个可变的参数列表,会把
|--a1看成是一个对象,所以转化为List之后打印出来就是[[I@de6ced],而传递a4的时候因为a4是String[],他符合jdk1.4方法
|--中定义的参数类型Object[],因为jdk1.5要兼容1.4所以会首先按照jdk1.4所定义的方法来执行转换成List后
|--打印结果为:[a, b, c]
|--System.out.println(Arrays.asList(a1));
|--System.out.println(Arrays.asList(a4));//[a, b, c]
--------------------- android培训、java培训、期待与您交流! ----------------------