目录
1.反射机制是什么?
2.反射机制能干什么?
3.反射相关的类
编辑
4.Class类(反射机制的起源 )
5.反射机制相关的API
1.(重要)常用获得类相关的方法
2.常用获得类中属性相关的方法(以下方法返回值为Field相关
3.(了解)获得类中注解相关的方法
4.(重要)获得类中构造器相关的方法(以下方法返回值为Constructor相关)
编辑 5.(重要)获得类中方法相关的方法(以下方法返回值为Method相关)
6.反射示例
1.获得Class对象的三种方式
2.反射的使用
1.产生对象
方法一:调用类的无参构造,且该构造方法必须是public权限!!
方法二:通过Constructer类来调用构造方法产生对象
2.通过反射操作类中的方法
7、反射优点和缺点
Java反射是指在程序运行期间,可以动态的获取到任意一个类的相关信息,并且调用任意对象的属性或方法,这种动态获取类的信息的方式和动态调用对象方法的功能称之为Java对象的反射机制
Java文件被编译后,生成了.class文件,JVM此时就要去解读.class文件 ,被编译后的Java文件.class也被JVM解析为一个对象,这个对象就是 java.lang.Class .这样当程序在运行时,每个java文件就最终变成了Class类对象的一个实例。我们通过Java的反射机制应用到这个实例,就可以去获得甚至去添加改变这个类的属性和动作,使得这个类成为一个动态的类
通过Java语言中的反射机制可以操作字节码文件,还可以操作代码片段(class文件)
Java反射机制的相关类都在Java.long.reflect.*;包下
Java文件被编译后,生成了.class文件,JVM此时就要去解读.class文件 ,被编译后的Java文件.class也被JVM解析为 一个对象,这个对象就是 java.lang.Class .这样当程序在运行时,每个java文件就最终变成了Class类对象的一个实 例。我们通过Java的反射机制应用到这个实例,就可以去获得甚至去添加改变这个类的属性和动作,使得这个类成 为一个动态的类 .
第一种 ,使用 Class.forName(" 类的全路径名 "); 静态方法。前提:已明确类的全路径名。第二种 ,使用 类名称.class 方法。说明:仅适合在编译前就已经明确要操作的 Class第三种 ,使用类任意对象的 getClass() 方法
package com.example.reflect.model;
public class Student {
// 共有属性name
private String name;
// 私有属性age
private Integer age;
// 不带参数的构造方法
public Student() {
}
// 带参数的构造方法
private Student(String name, Integer age) {
this.name = name;
this.age = age;
System.out.println("Student(String,name)");
}
private void eat(){
System.out.println("i am eat");
}
public void sleep(){
System.out.println("i am pig");
}
private void function(String str) {
System.out.println(str);
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
class TeatReflect {
public static void main(String[] args) {
/**
* 1.通过getClass获取Class对象
*/
Student student = new Student();
Class c = student.getClass();
/**
* 2.直接通过 类名.class 的方式得到,该方法最为安全可靠,程序性能更高
* 这说明任何一个类都有一个隐含的静态成员变量 class
*/
Class c2 = Student.class;
/**
* 3、通过 Class 对象的 forName() 静态方法来获取,用的最多,
* 但可能抛出 ClassNotFoundException 异常
*/
Class c3 = null;
try {
c3 = Class.forName("com.example.reflect.model.Student");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
//一个类在 JVM 中只会有一个 Class 实例,即我们对上面获取的
//c1,c2,c3进行 equals 比较,发现都是true
System.out.println(c.equals(c2));
System.out.println(c3.equals(c2));
System.out.println(c3.equals(c));
}
}
// 产生对象
public static void reflectNewInstance() {
try {
Class> classStudent = Class.forName("com.example.reflect.model.Student");
// 调用的是无参构造,且必须是公有的
Object objectStudent = classStudent.newInstance();
Student student = (Student) objectStudent;
System.out.println("获得学生对象:"+student);
} catch (Exception e) {
e.printStackTrace();
}
}
如果使私有的无参构造那么就会报错了,就像下面这样:
此时我们通过无参构造去获取对象:
Constructer类就是Java中利用反射操作构造方法的类
// 产生对象
public static void reflectNewInstance2() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
// 获取Class对象
Class classStudent = Student.class;
// 获得所有的构造方法
Constructor[] constructors = (Constructor[]) classStudent.getDeclaredConstructors();
System.out.println(Arrays.toString(constructors));
// 获取私有的有参构造
Constructor constructor = classStudent.getDeclaredConstructor(String.class,Integer.class);
// 破坏封装性·
constructor.setAccessible(true);
// 通过私有构造方法创建对象
Student student = constructor.newInstance("锦鲤",18);
System.out.println(student);
}
反射可以获得所有的不论公有私有的方法和属性,他会破坏封装性,只在当前JVM进程中可见
// 操作方法
public static void reflectByMethod() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
// 获取Class对象
Class classStudent = Student.class;
Method[] methods = classStudent.getDeclaredMethods();
System.out.println(Arrays.toString(methods));
// 通过反射来调用普通方法和静态方法
// 调用普通方法首先要产生对象
Student student = classStudent.newInstance();
// 通过反射拿到fun方法的反射方法
Method methodFun = classStudent.getMethod("fun", String.class);
// 通过Method反射对象调用fun方法, 传入调用该方法的对象以及需要传入的参数
methodFun.invoke(student, "锦鲤");
// 调用静态方法
Method methodTest = classStudent.getMethod("test");
methodTest.invoke(null);
}
反射的讲解就到这里啦!
下篇博客见~