类Class
代表了一类事物,描述了类应该有的类名,构造方法,方法,变量,但并不包含他们的值
代表字节码(过程:从硬盘上变成class二进制代码,加载到内在中,再用字节码去操作对象)
Class.forName()的作用
1.将已经加载到内存的字节码,并返回字节码Class
2.字节码还未被加载到内在,则用类加载器加载,并放到虚拟机,并返回
得到字节码的方式
1、类的名字.class
2、类的对象的.getClass();
3、Class.forName("java.util.String"); 将类的名字放进去,类未被加载到内存,要加载到内存并返回加载成字节码
Class的预定对象
示例1:(同一个类的字节码相同)
String a1 = "a1";
Class c1 = a1.getClass();
Class c2 = String.class;
Class c3 = Class.forName("java.lang.String");
System.out.println(c1==c2);
System.out.println(c2==c3);
包装类取得其基础类型的方法 包装类.TYPE
Class(的对象).isPrimitive(); 基础类型判定
判定指定的 Class
对象是否表示一个基本类型
九个基础类型的Class对象,可以通过Class(中的对象的).isPrimitive(); 方法取得
数组用isArray()判断是否基础类型
反射
理解:一个JAVA类中的所有对象映射成为其相应的类。就是使用相应的方法,将相应内容变成相应的类;
好处:可以将一个类中所有的对象遍历出来,如果有私有的也可以通过暴力破解的方式读取出来
常用的方法
getMethod(String name,Class... parameterTypes); Method
getMethods(); Method[]
getPackage(); Package
getConstructor(Class... parameterTypes) ;Constructor
getConstructors(Class... parameterTypes) ; Constructor[]
构造反射
字节码对象.getConstructor 取得构造
字节码对象.newInstance()可以直接通过字节码新建一个无参构造,不能传参
构造.newInstance() 根据构造参数多少来选择构造方法
// 通过参数来选择构造方法,生成一个构造方法(编译时)
Constructor c2 = Demo31.class.getConstructor(String.class,
String.class);
// 通过构造方法对象newInstance来得到实例对象,并不知道得到的是哪个对象的,所以需要强制类型转换// (运行时)
Demo31 d31 = (Demo31) c2.newInstance("aa", "cc"); // 新建实例的时候必须参数对应。否则运行时会报错
d31.main(null);
方法反射
Method md = Demo31.class.getMethod("print", String.class); // 使用反射取得单个方法(第一个参数为方法名,第二个参数为方法的参数,可变参数<只是提供参数的字节码,并不是具体参数>)
md.invoke(Demo33.class.newInstance(), "aa"); // 调用方法第一个对象必须是类的实例对象,第二个为可变参数,为具体参数值
Method[] ms = Class.class.forName("Demo33").getMethods();
for (Method m : ms) {
System.out.println(m.getName());
}
字段反射
Class c1 = Class.class.forName("Demo33");
Field[] fs = c1.getDeclaredFields(); // 暴力取得参数,比如private的参数也可以取得
for (Field f : fs) {
System.out.println(f.getBoolean(c1));
f.setAccessible(true);
// 如果对方属性为私有,如果不设置权限会报错
f.get(c1); // 这里需要传入一下对象,取值是从每个对象上去取,并不是从类中取 }
}
Arrays
将一个object数组转换成一个List对象
int[] a = new int[] { 1, 2, 3 };
String[] b = new String[] { "a", "c", "b" };
System.out.println(Arrays.asList(a));
System.out.println(Arrays.asList(b));
打印结果
[[I@1bc4459]
[a, c, b]
数组反射(通过对象Array进行反射读取)
如果数组的位数(都是一维或二维)并且类型一致的话,那么这两个数组的字节码相同
基本类型不是Object类型,数组和String都是object类型,二维数组是Object类型,因为二维数组里面存放的一个数组,数组是object类型的
因为int是基础类型而不是Object类型,在jdk1.5中该方法要求传入一个Object数组,因为不是Object数组,所以会返回jdk1.4处理,并返回一个数组对象。
而String是object所以此方法会直接将String数组转换成List并打印出来
数组反射示例:
int[] a = new int[] { 1, 2, 3 };
String[] b = new String[] { "a", "c", "b" };
System.out.println(Arrays.asList(a));
System.out.println(Arrays.asList(b));
Class cl = a.getClass();
if (cl.isArray()) {
for (int i = 0; i < Array.getLength(a); i++) {
System.out.println(Array.get(a, i));
}
}