通过某种机制,动态得到这个类所有信息(属性,方法,构造方法...), 也可以动态的调用这个类所有的属性,方法,构造方法... 这种机制就是所谓的反射
反射的核心: 类的镜子, 类的字节码文件 对应的类: Class类
每一个类, 它的Class类的对象, 唯一一个, 类的Class对象, 在这个类的字节码文件加载到内存时候,JVM就会为该类的字节码文件创建一个Class对象
1.得到某个类的Class对象
(1)类名.class 得到该类的Class对象
//第一种方式: 类名.class
Class clazz = Student.class;
(2)类的对象.getClass()
//第二种方式: 类的对象.getClass()
Student stu = new Student();
//Student本类, 子类 上界
Class clazz2 = stu.getClass();
(3)通过Class类的static方法: forName(类的全限定名); 类的全限定名: 包名.类名
//第三种: 通过Class类的static方法: forName(类的全限定名)
Class> clazz3 = Class.forName("com.fs.Student");
//得到的同一个对象
System.out.println(clazz == clazz2);//true
System.out.println(clazz == clazz3);//true
2.通过Class对象获取某个类所有的属性,方法,构造方法,并使用和调用它
(1)获取属性
//1.得到反射的核心对象: Class
Class> clazz = Class.forName("com.fs.Student");
//2.得到属性
//1.根据属性名获取公开属性
// 抛出NoSuchFieldException异常: 没有匹配的属性
Field nameFiled = clazz.getField("name");
//打印属性名 getName()
System.out.println("属性名:"+nameFiled.getName());
System.out.println("访问修饰符:"+nameFiled.getModifiers());
System.out.println("属性数据类型:"+nameFiled.getType());
//给属性赋值 set()
//获取属性的值 get()*/
//根据属性名获取属性, 不管是私有还是公开
Field nameFiled = clazz.getDeclaredField("name");
//打印属性名 getName()
System.out.println("属性名:"+nameFiled.getName());
// 0: 缺省的 1: public 2: private 4:protected
System.out.println("访问修饰符:"+nameFiled.getModifiers());
System.out.println("属性数据类型:"+nameFiled.getType());
//给属性赋值 set(Object obj, Object value)
//obj: 对象 value: 属性值
Student stu = (Student)clazz.newInstance();
//给stu对象的name属性赋"王五"的值
//设置private允许访问
nameFiled.setAccessible(true);
nameFiled.set(stu,"王五");
//底层: stu.name ="王五"
System.out.println(stu);
//获取属性的值 Object get(Object obj) //底层: stu.name
System.out.println("属性值:"+nameFiled.get(stu));
System.out.println("==============================");
//获取所有的属性
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
System.out.println("属性名:"+field.getName());
}
(2)获取方法
//1.得到反射的核心对象: Class
Class> clazz = Class.forName("com.fs.Student");
//2.获取公开的方法
//根据方法名获取指定方法名的方法
//NoSuchMethodException: 没有匹配的方法
/*Method studyMethod = clazz.getMethod("study");
System.out.println("方法名:"+studyMethod.getName());
System.out.println("返回值类型:"+studyMethod.getReturnType());
System.out.println("参数列表类型:"
+studyMethod.getParameterTypes());
System.out.println("参数个数:"
+studyMethod.getParameterCount());
System.out.println("访问修饰符:"
+studyMethod.getModifiers());*/
//获取所有的公开方法,包括从父辈类继承
Method[] methods = clazz.getMethods();
for (Method method : methods) {
System.out.println(method);
}
//回获取所有访问修饰符修饰的方法,
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
System.out.println(method);
}
Method studyMethod = clazz.getDeclaredMethod("study");
//创建Student对象
Student stu = (Student)clazz.newInstance();
studyMethod.setAccessible(true);
Object rs = studyMethod.invoke(stu);
System.out.println(rs);
(3)获取构造方法
//1.得到该类Class对象
Class clazz = Student.class;
//2.得到公开的构造方法
//指定参数类型的构造方法
// NoSuchMethodException异常: 没有匹配的方法的异常
Constructor c1 = clazz.getConstructor(int.class);
//打印
//getName() 得到方法名
System.out.println(c1.getName());
//getModifiers() 访问修饰符
System.out.println(c1.getModifiers());*/
//得到所有的公开的构造方法
Constructor[] constructors = clazz.getConstructors();
for (Constructor constructor : constructors) {
System.out.println(constructor);
}
//得到所有的 不管是公开还是私有
Constructor c1 = clazz.getDeclaredConstructor(int.class,String.class);
//打印
//getName() 得到方法名
System.out.println(c1.getName());
//getModifiers() 访问修饰符 1 public 2 private
System.out.println(c1.getModifiers());
Constructor[] constructors = clazz.getDeclaredConstructors();
for (Constructor constructor : constructors) {
System.out.println(constructor);
}
//创建类对象
//1.调用Class的newInstance() 调用公开的无参构造
//IllegalAccessException 无法访问的异常: 无参构造方法是private修饰
Student stu = clazz.newInstance(); // new Student()
System.out.println(stu);
//2.私有Constructor的newInstance()方法
Constructor c1 = clazz.getDeclaredConstructor(int.class,String.class);
Student stu2 = c1.newInstance(1, "张三");
System.out.println(stu2);
//如果构造方法是private修饰的
Constructor c2 = clazz.getDeclaredConstructor(int.class);
//如果是private修饰,默认无法访问.
//可以设置允许访问private的 setAccessible(true)
c2.setAccessible(true);
Student stu3 = c2.newInstance(1);
System.out.println(stu3);
关于注解的相关的方法:
判断 元素上是否包含某个注解: Class,Filed,Method...
// boolean isAnnotation() 如果此 类对象表示注释类型,则返回true。
获取元素上的注解 Class,Filed,Method...
getAnnotation()
Class:
getName() 获取的全限定名: 包名.类名
getSimpleName() 获取的简单名: 类名
反射: 动态操作类的方法,属性,创建对象.... 框架底层使用
如果创建对象, 确定的类, 使用 new 构造方法()