关于java. Lang. Class类的理解
1.类的加载过程:
程序经过javac. exe命令以后,会生成-一个或多个字 节码文件(. class结尾)。接着我们使用java. exe命令对某个字节码文件进行解释运行。相当于将某个字节码文件加载到内存中。此过程就称为类的加载。加载到内存中的类,我们就称为运行时类,此运行时类,就作为Class的一个实例。
2.换句话说,Class的实例就对应着一个运行时类。
3.加载到内存中的运行时类,会缓存一定的时间。 在此时间之内,我们可以通过不同的方式来获取此运行时类。
哪些类型可以有Class对象?
(1) class:外部类,成员(成员内部类,静态内部类),局部内部类,匿名内部类
(2) interface: 接口
(3) []: 数组
(4) enum: 枚举
(5) annotation: 注解@interface
(6) primitive type:基本数据类型
(7) void 可以看做一个类型
public void test(){
Class c1 = 0bject.class; .
Class c2 = Comparable.class;
Class c3 = String[].class;
Class c4 = int[][].class ;
Class c5 = ElementType. class ;
Class c6 = Override. class;
Class c7 = int.class;
Class c8 = void. class;
Class c9 = Class.class;
int[] a = new int[10] ;
int[] b = new int[100];
Class c10 = a.getClass();
Class c11 = b. getClass();
只要数组的元素类型与维度一样,就是同一个Class
System. out.println(c10 == c11);
}
使用newInstance方法 创建运行时类的对象(Person可以看作一个运行时类),内部运用了运行时类的空参构造器
使用此方法时候能正常运行时的对象,要求:
1.运行时类b必须提供空参构造器
2.空参构造器的访问权限要有,如public
使用反射获取类的名字、方法、构造器、属性
package com.lrq.Reflection;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class ClassTest {
public static void main(String[] args) throws Exception, SecurityException {
String path = new String("com.lrq.Reflection.Person");
try {
Class clazz = Class.forName(path);
//获取类的名字
String name1 = clazz.getName();//获得包名加类名 com.lrq.Reflection.Person
String name2 = clazz.getSimpleName();//获得类名 Person
System.out.println(name1);
System.out.println(name2);
//获取类的方法
Method[] m1 = clazz.getMethods();//获得所有public的方法
Method[] m2 = clazz.getDeclaredMethods();//获得所有方法包括private声明的
/*
* 如果方法有参,必须传入参数类型对应的class对象
* 这样做是因为方法会有重载,这样的话就避免了重载,指定了一个
*/
Method m3 = clazz.getDeclaredMethod("setName",String.class);
Method m4 = clazz.getDeclaredMethod("getName",null);
System.out.println(m1);
for(Method m: m2) {
System.out.println("方法"+m);
}
//获取类的构造器
Constructor[] c1 = clazz.getConstructors();//获得所有构造器,但是private的不可以
Constructor[] c2 = clazz.getDeclaredConstructors();//获得所有构造器,包括private
Constructor c3 = clazz.getDeclaredConstructor(String.class);//获得指定构造器,
System.out.println(c1);
System.out.println(c3);
for(Constructor c: c2) {
System.out.println("构造器"+c);
}
//获取类的属性
Field[] f1 = clazz.getFields();//获得所有public的属性
Field[] f2 = clazz.getDeclaredFields();//获得包括有private的属性
clazz.getDeclaredField("name");//获得指定属性
System.out.println(f1.length);
for(Field f : f2) {
System.out.println("属性"+f);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
使用反射API操作属性和普通方法
package com.lrq.Reflection;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import org.junit.Test;
@SuppressWarnings("deprecation")
@Test
public void Test2() {
String path = new String("com.lrq.Reflection.Person");
try {
Class<Person> clazz = (Class<Person>)Class.forName(path);
Person P1 = clazz.newInstance();//其实是调用了Person的无参方法
System.out.println(P1);
Constructor<Person> c = clazz.getDeclaredConstructor(String.class,int.class);
Person P2 = c.newInstance("刘睿卿",22);
System.out.println(P2.getName());
//通过反射API调用普通方法
Person P3 = clazz.newInstance();
Method M1 = clazz.getDeclaredMethod("Show", null);
M1.invoke(P3, null);//相当于 P3.Show();
System.out.println(P3);
//通过反射API操作属性
Person P4 = clazz.newInstance();
Field F = clazz.getDeclaredField("name");
F.setAccessible(true);//这样设置就可以调用private 不要经过安全检查
F.set(P4,"刘睿卿");//通过反射直接写属性
System.out.println(P4.getName());//通过反射直接读属性的值
} catch (Exception e) {
e.printStackTrace();
}
}
}