一、Class的理解
1.Class是反射的源头 (要想使用反射必先获取该类的Class对象)
2.Class本身也是一个类
3.Class 对象只能由系统建立对象
4.一个加载的类在 JVM 中只会一个Class实例
5.一个Class对象对应的是一个加载到JVM中的一个.class文件
6.每个类的实例都会记得自己是由哪个 Class 实例所生成
7.通过Class可以完整地得到一个类中的所有被加载的结构
8.Class类是Reflection的根源,针对任何你想动态加载、运行的类,唯先获得相应的Class对象
二、获取Class的实例
//1.获取Class实例的方式一 : 类名.class
Class clazz = Person.class;
//2.获取Class实例的方式二 :对象名.getClass()
Class clazz2 = new Person().getClass();
//3.获取Class实例的方式 : Class.forName(全类名)
Class clazz3 = Class.forName("com.atguigu.java2.Person");
//4.获取Class实例的方式四 : 类加器.loadClass(全类名) - 了解
ClassLoader c = this.getClass().getClassLoader();
Class clazz4 = c.loadClass("com.atguigu.java2.Person");
三、了解ClassLoader
四、反射的应用
/*
* 通过反射获取指定属性并赋值 - 需要掌握
*/
@Test
public void test3() throws Exception, Exception{
//创建Dog对象
Dog dog = new Dog();
Class clazz = Dog.class;
//获取指定属性
/*
* getField() : 只能获取public所修饰的属性
*/
// Field field = clazz.getField("dogAge");
//给属性赋值
/*
* setInt(对象名,属性值)
*/
// field.setInt(dog, 10);
System.out.println("------------------给私属性赋值----------------------------");
//获取指定的属性
/*
* getDeclaredField() : 可以获取任意权限修饰符修饰的属性
*/
Field declaredField = clazz.getDeclaredField("dogName");
//授权(设置是否允许访问
declaredField.setAccessible(true);
//给属性赋值
declaredField.set(dog, "中华田园犬");
dog.test();
}
/*
* 调用指定的方法 - 需要掌握
*/
@Test
public void test4() throws Exception, Exception{
Dog dog = new Dog();
Class clazz = Dog.class;
//获取指定的方法
/*
* 第一个参数 :方法名
* 第二个参数 : 形参类型
*/
// Method method = clazz.getMethod("dogSay", int.class);
//调用方法
/*
* 第一个参数 : 对象名
* 第二个参数 : 实参
*/
// method.invoke(dog, 10);
System.out.println("--------------------调用私的方法---------------------------");
//调用指定的方法 -
/*
* getDeclaredMethod(String name, Class<?>... parameterTypes) :
* 可以调用任意权限修饰符修饰的方法
* 第一个参数 : 方法名
* 第二个参数 : 形参的类型
*/
Method declaredMethod = clazz.getDeclaredMethod("dogInfo");
//允许访问
declaredMethod.setAccessible(true);
//调用方法
/*
* invoke(Object obj, Object... args) : 调用方法
* 第一个参数 : 对象名
* 第二个参数 : 实参
*/
declaredMethod.invoke(dog);
}
/*
* 通过反射获取属性
*/
@Test
public void test(){
//1.先获取Class对象
Class clazz = Dog.class;
//2.获取属性
/*
* getFields() : 获取本类及父类中所public修饰的属性
*/
Field[] fields = clazz.getFields();
//遍历
for (int i = 0; i < fields.length; i++) {
System.out.println(fields[i]);
}
System.out.println("--------------------------------------");
/*
* getDeclaredFields() : 获取本类中所的属性
*/
Field[] declaredFields = clazz.getDeclaredFields();
for (int i = 0; i < declaredFields.length; i++) {
System.out.println(declaredFields[i]);
}
}
/*
* 通过反射获取方法
*/
@Test
public void test2(){
//1.先获取Class对象
Class clazz = Dog.class;
//2.获取类中的方法
/*
* getMethods() : 获取本类及父类中所public修饰的方法
*/
Method[] methods = clazz.getMethods();
//遍历
for (int i = 0; i < methods.length; i++) {
System.out.println(methods[i]);
}
System.out.println("----------------------------------");
/*
* getDeclaredMethods() : 获取本类中所的方法
*/
Method[] declaredMethods = clazz.getDeclaredMethods();
for (int i = 0; i < declaredMethods.length; i++) {
System.out.println(declaredMethods[i]);
}
}
/*
* 通过反射获取父类
*/
@Test
public void test5(){
Class clazz = Dog.class;
//获取父类 - 获取的是父类的类信息
Class superclass = clazz.getSuperclass();
}
/*
* 通过反射获取注解
*/
@Test
public void test6() throws Exception, Exception{
Class clazz = Dog.class;
//获取的是类上的注解
// Annotation[] annotations = clazz.getAnnotations();
// for (int i = 0; i < annotations.length; i++) {
// System.out.println(annotations[i]);
// }
//获取属性上的注解 : ①先获取那个属性 ②再获取注解
Field field = clazz.getField("dogAge");
//获取属性上的注解
Annotation[] annotations2 = field.getAnnotations();
for (int i = 0; i < annotations2.length; i++) {
// System.out.println(annotations2[i]);
//如何获取注解上的那个值
Annotation annotation = annotations2[i];
MyAnn ma = (MyAnn) annotation;
String s = ma.name();
System.out.println(s);
}
}
/*
* 通过反获取构造器 - 通过反射创建对象
*/
@Test
public void test7() throws Exception, Exception{
Class clazz = Dog.class;
//获取指定构造器 - 获取的是空参构造器
// Constructor constructor = clazz.getConstructor();
//创建对象
// constructor.newInstance();
System.out.println("-----------------获取私带参构造器------------");
/*
* 获取指定构造器 - 任意权限修饰符
*
* getDeclaredConstructor(Class<?>... parameterTypes) : 方法形参是构造器形参的类型
*/
Constructor constructor2 = clazz.getDeclaredConstructor(int.class);
constructor2.setAccessible(true);
/*
* newInstance(Object ... initargs) : 方法的形参是往构造器中传的实参
*/
constructor2.newInstance(10);
}