java数据类型都有一个相应的Class对应。
对象是表示或封装一些数据。一个类被加载后,JVM会创建一个对应该类的Class对象,类的整个结构信息会放到对应的Class对象中。这个Class对象就像一面镜子一样,通过这面镜子我可以看到对应类的全部信息。
String path = "com.test.user";
Class clazz = Class.forName(path);
System.out.println(clazz.hashCode());
Class clazz2 = Class.forName(path); //一个类只对应一个Class对象
System.out.println(clazz2.hashCode());
Class strClazz = String.class;
Class strClazz2 = path.getClass();
System.out.println(strClazz==strClazz2);
两次hashcode相等,strClazz 等于strClazz 2,故java数据类型都只对应一个相应的Class对象。
对于数组而言,数组元素类型与维度一样,则对应的Class一样。
获取类的属性、方法和构造器
属性:
Field[] fields = clazz.getFields(); //只能获得public的field
Field[] fields = clazz.getDeclaredFields();//获得所有的field
Field f = clazz.getDeclaredField("uname");
加了Declared的方法都是获取的所有的,没加的只能获取public修饰的。
方法:
Method[] methods = clazz.getDeclaredMethods();
Method m01 = clazz.getDeclaredMethod("getUname", null);
构造器:
Constructor[] constructors = clazz.getDeclaredConstructors();
Constructor c = clazz.getDeclaredConstructor(int.class,int.class,String.class);
生成对象,操作方法属性
生成对象
Class<User> clazz = (Class<User>) Class.forName(path);
//通过反射API调用构造方法,构造对象
User u = clazz.newInstance(); //其实是调用了User的无参构造方法
Constructor<User> c = clazz.getDeclaredConstructor(int.class,int.class,String.class);
User u2 = c.newInstance(1001,18,"张三");
调用普通方法
User u3 = clazz.newInstance();
Method method = clazz.getDeclaredMethod("setUname", String.class);
method.invoke(u3, "张三"); //u3.setUname("张三");
操作属性
User u4 = clazz.newInstance();
Field f = clazz.getDeclaredField("uname");
f.setAccessible(true); //这个属性不需要做安全检查了,可以直接访问
f.set(u4, "李四"); //通过反射直接写属性
通过反射获取泛型信息
public class Demo04 {
public void test01(Map<String,User> map,List<User> list){
System.out.println("Demo04.test01()");
}
public Map<Integer,User> test02(){
System.out.println("Demo04.test02()");
return null;
}
public static void main(String[] args) {
try {
//获得指定方法参数泛型信息
Method m = Demo04.class.getMethod("test01", Map.class,List.class);
Type[] t = m.getGenericParameterTypes();
for (Type paramType : t) {
System.out.println("#"+paramType);
if(paramType instanceof ParameterizedType){
Type[] genericTypes = ((ParameterizedType) paramType).getActualTypeArguments();
for (Type genericType : genericTypes) {
System.out.println("泛型类型:"+genericType);
}
}
}
//获得指定方法返回值泛型信息
Method m2 = Demo04.class.getMethod("test02", null);
Type returnType = m2.getGenericReturnType();
if(returnType instanceof ParameterizedType){
Type[] genericTypes = ((ParameterizedType) returnType).getActualTypeArguments();
for (Type genericType : genericTypes) {
System.out.println("返回值,泛型类型:"+genericType);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
结果:
#java.util.Map<java.lang.String, com.test.bean.User>
泛型类型:class java.lang.String
泛型类型:class com.test.bean.User
#java.util.List<com.test.bean.User>
泛型类型:class com.test.bean.User
返回值,泛型类型:class java.lang.Integer
返回值,泛型类型:class com.test.bean.User
三种执行方法的效率差异比较
public class Demo5 {
public static void test01(){
User u = new User();
long startTime = System.currentTimeMillis();
for (int i = 0; i < 1000000000L; i++) {
u.getUname();
}
long endTime = System.currentTimeMillis();
System.out.println("普通方法调用,执行10亿次,耗时:"+(endTime-startTime)+"ms");
}
public static void test02() throws Exception{
User u = new User();
Class clazz = u.getClass();
Method m = clazz.getDeclaredMethod("getUname", null);
// m.setAccessible(true);
long startTime = System.currentTimeMillis();
for (int i = 0; i < 1000000000L; i++) {
m.invoke(u, null);
}
long endTime = System.currentTimeMillis();
System.out.println("反射动态方法调用,执行10亿次,耗时:"+(endTime-startTime)+"ms");
}
public static void test03() throws Exception{
User u = new User();
Class clazz = u.getClass();
Method m = clazz.getDeclaredMethod("getUname", null);
m.setAccessible(true); //不需要执行访问安全检查
long startTime = System.currentTimeMillis();
for (int i = 0; i < 1000000000L; i++) {
m.invoke(u, null);
}
long endTime = System.currentTimeMillis();
System.out.println("反射动态方法调用,跳过安全检查,执行10亿次,耗时:"+(endTime-startTime)+"ms");
}
public static void main(String[] args) throws Exception {
test01();
test02();
test03();
}
}
结果:
普通方法调用,执行10亿次,耗时:301ms
反射动态方法调用,执行10亿次,耗时:1546ms
反射动态方法调用,跳过安全检查,执行10亿次,耗时:911ms