在JAVA中,一切都是对象,那么你新建的一个class也是对象吗?
是的,新建的class也是对象,它是java.lang.Class的实例对象。
class A{}
A a = new A();
1,Class c1 = a.class; // c1表示A这个类的类类型(小a是A的实例对象) ,这也说明了每一个类都有一个静态成员class;
2,Class c2 = a.getClass(); // c2表示A这个类的类类型 ,通过该A类的对象a的getClass()方法获取。
c1 == c2 //它们都是A类的类类型,一个类只可能是Class类的一个实例对象。
3, Class c3 = null;
c3 = Class.forName("com.wjb.A"); //括号里写的是全类名
c2 == c3
所以,完全可以通过类类型(c1 , c2 , c3)创建A的实例对象;
A a = (A)c1.newInstance(); // 注意A类一定要有无参的构造方法
编译时加载的类是:静态加载类
运行时加载的类是:动态加载类
知道了类类型后,可以通过c1.获取类的一些信息,方法的一些信息,成员变量的一些信息。
集合的泛型也是一种反射,但是只在编译时有效,运行时就没有泛型了。
Class,method,field(类,方法,成员变量)的操作都是绕过编译的一些操作。
package javaReflect;
import java.lang.reflect.Method;
import java.util.ArrayList;
/**
* Created by wjb on 2017/3/6.
*/
public class Demo {
public static void main(String[] args) {
String s = "Hello";
ClassUtis.printMessage(s);
ArrayList list1 = new ArrayList();
ArrayList<String> list2 = new ArrayList<String>();
list2.add("hello");
Class c = list2.getClass();
try {
Method method = c.getMethod("add", Object.class);
method.invoke(list2,20); // 调用方法,绕过编译就绕过泛型了。
System.out.println(list2.size());
System.out.println(list2);
} catch (Exception e) {
e.printStackTrace();
}
}
}
list2的泛型是String类型,按道理是不能加入20的,但是绕过了编译,可以加进去。说明泛型只在编译时有效。
对于内部类的反射使用:
Office office = new Office();
//获取所有的内部类
Field[] fields = office.getClass().getDeclaredFields();
for (Field f : fields) {
//设置属性可以访问
f.setAccessible(true);
//获取每一个内部类属性的全路径名
String name = f.getType().getName();
//所有内部类里面的属性名
Field[] fields2 = Class.forName(name).getDeclaredFields();
for (Field fid : fields2) {
//设置属性可以访问
fid.setAccessible(true);
//获取内部类属性上的注解,这里的注解是自定义的
XlsMeta xlsMeta = fid.getAnnotation(XlsMeta.class);
//获取注解里面定义的required
String required = xlsMeta.required();
//首选属性检查
// if (required.equals("Preferred")) {
// list1.add("属性:" + fid.getName() + "\t建议不要为空\n");
// }
//必填属性检查
// if (required.equals("Required")) {
// list2.add("属性:" + fid.getName() + "\t不能为空\n");
// }
}
}
网友评论