反射
Class类
java.lang.Class类的理解:
1、类的加载过程
程序经过javac.exe命令以后 会生成一个或多个字节码文件 (.class)接着我们使用java.exe命令对某个字节码文件进行解释运行 相当于将某个字节码文件加载到内存中 此过程称为类的加载。加载到内存中的类 我们就称为运行时类 此运行时类就作为Class的一个实例
获取Class类实例的4种方式
方式一 调用运行时类的属性
Class clazz1 = Person.class;
方式二 通过运行时类的对象
Person p1 = new Person();
Class clazz2 = p1.getClass();方式三 调用Class静态方法 forName(String classPath)
Class clazz3 = Class.forName(“com.lili.Person”);
方式四 使用类的加载器
ClassLoader classLoader = ReflectionTest.class.getClassLoader();
Class clazz4 = classLoader.loadClass(“com.lili.Person”);System.out.println(clazz1==clazz2);//true
加载到内存中的运行时类 会缓存一段时间 在此时间段内 可以通过不同的方式来获取此运行时类
哪些类可以获取Class对象
1、class:
内部类 成员(成员内部类 静态内部类) 局部内部类 匿名内部类
2、interface
3、[]数组
4、enum 枚举
5、annotation 注解
6、primitive type 基本数据类型
7、voidClass c1=Object.calss;
Class c2 = Comparable.class;
Class c3 = String[].class;
Class c4 = Override.class;
Class c5 = int.class;
Class c6 = void.class;int[] a = new int[10];
int[] b = new int[100];
Class c10 = a.getClass();
Class c11 = b.getClass();
System.out.println(c10==c11);//true
只要数组的元素类型与纬度相同 就是同一个Class
读取properties文件
1、新建jdbc.properties文件 文件内容为:
user=lili
password=mysql方式一 文件默认在当前module下
Properties pros = new Properties();
FileInputStream fis = new FileInputStream(“jdbc.properties”);
pros.Load(fis);**方式二 使用ClassLoader 默认位置在src下
ClassLoader classLoader = ClassLoaderTest.class.getClassLoader();
InputStream is = classLoader.getResourceAsStream(“jdbc.properties”);
pros.load(is);String user = pros.getProperties(“user”);
创建运行时类的对象
Class<Person> clazz = Person.class;
//内部调用的是无参构造器
//要求:
//1、运行时类必须提供空参构造器
//2、空参构造器访问权限得够 通常设置为public
Person obj = clazz.newInstance();
//在javabean 中要提供一个public 空参构造器原因:
//1、便于通过反射 创建运行时类对象
//2、便于子类继承此类 默认调用super()保证父类由有此构造器
获取运行时类的属性和方法
Class clazz = Person.class;
//getFields() 获取当前运行时类及其父类中声明为public访问权限的属性
Field[] fields = clazz.getFields();
//getDeclaredFields() 获取当前运行时类中声明的所有属性 不包括父类中的属性
Field[] dfields = clazz.getDeclaredFields();
//getMethods() 获取当前运行时类及其父类中声明为public访问权限的方法
Method[] methods = clazz.getMethods();
//getDeclaredFields() 获取当前运行时类中声明的所有方法 不包括父类中的方法
Method[] dmethods = clazz.getDeclaredMethodss();
//getConstructors() 获取当前运行时类及其父类中声明为public访问权限的构造器
Constructor[] constructors = clazz.getConstructors();
//getDeclaredConstructors() 获取当前运行时类中声明的所有构造器 不包括父类中的构造器
Constructor[] dconstructors = clazz.getDeclaredConstructors();
//获取运行时类的父类
Class superClass=clazz.getSuperclass();
//获取运行时类带泛型的父类
Type genericSuperClass=clazz.getGenericSuperclass();
//获取运行时类实现的接口
Class[] interfaces =clazz.getInterfaces();
//获取运行时类所在包
Package pack=clazz.getPackage();
//获取运行时类声明的注解
Annotation[] annotations=clazz.getAnnotations();
//以下了解即可
for(Field f:dfields){
//1 权限修饰符
int modifier =f.getModifiers();
System.out.println(Modifier.toString(modifier)+"\t");
//2、数据类型
Class type = f.getType();
System.out.println(type.getName());
//3、变量名
String fname=f.getName();
}
for(Method m:dmethods){
//1 权限修饰符
int modifier =m.getModifiers();
System.out.println(Modifier.toString(modifier)+"\t");
//2、返回值类型
Class type = m.getReturnType();
System.out.println(type.getName());
//3、获取方法声明的注解
Annotation[] annos=m.getAnnotations();
for (Annotation a :annos){
System.out.println(a);
}
//4、获取方法名
System.out.println(m.getName());
//5、获取形参列表
Class[] parameterTypes=m.getParameterTypes();
if(!(parameterTypes==null && parameterTypes.length==0)){
for(Class p :parameterTypes){
System.out.println(p.getName());
}
}
}
获取指定属性、方法和构造器
Pserson p =(Person) clazz.newInstance();
//要求属性声明为public
Field id = clazz.getField("id");
//不要求属性声明为public
Field id2 = clazz.getDeclaredField("id");
id.set(p,1001);
int pid = id.get(p);
//不要求属性声明为public
Field name = clazz.getDeclaredField("name");
name.setAccessible(true);//设置为true才能修改
name.set(p,"lili");
//参数1 指明获取方法的名称 参数2 指明获取的方法的形参列表
Method show = calzz.getDeclaredMethod("show",String.class);
show.setAccessible(true);//保证当前方法可访问
//参数1 方法的调用者 参数2 给方法形参赋值的实参
Object returnValue=show.invoke(p,"CHN");
***************************
//调用静态方法 调用静态属性也类似
Method showDesc = clazz.getDeclaredMethod("showDesc");//无参方法
showDesc.setAccessible(true);
//如果运行时类的方法无返回值 则invoke返回null
Obejct returnValue = showDesc.invoke(Person.class);
***************************
//调用治党构造器
Constructor constructor = clazz.getDeclaredConstructor(String.class);
//保证构造器是可访问的
constructor.setAccessible(true);
//调用此类创建对象
Person per =(Person) constrructor.newInstance("Tom");