目录
1.反射机制是什么?
2.反射机制能干什么?
3.反射相关的类
编辑
4.Class类(反射机制的起源 )
5.反射机制相关的API
1.(重要)常用获得类相关的方法
2.常用获得类中属性相关的方法(以下方法返回值为Field相关
3.(了解)获得类中注解相关的方法
4.(重要)获得类中构造器相关的方法(以下方法返回值为Constructor相关)
编辑 5.(重要)获得类中方法相关的方法(以下方法返回值为Method相关)
6.反射示例
1.获得Class对象的三种方式
2.反射的使用
1.产生对象
方法一:调用类的无参构造,且该构造方法必须是public权限!!
方法二:通过Constructer类来调用构造方法产生对象
2.通过反射操作类中的方法
7、反射优点和缺点
1.反射机制是什么?
Java反射是指在程序运行期间,可以动态的获取到任意一个类的相关信息,并且调用任意对象的属性或方法,这种动态获取类的信息的方式和动态调用对象方法的功能称之为Java对象的反射机制
Java文件被编译后,生成了.class文件,JVM此时就要去解读.class文件 ,被编译后的Java文件.class也被JVM解析为一个对象,这个对象就是 java.lang.Class .这样当程序在运行时,每个java文件就最终变成了Class类对象的一个实例。我们通过Java的反射机制应用到这个实例,就可以去获得甚至去添加改变这个类的属性和动作,使得这个类成为一个动态的类
2.反射机制能干什么?
通过Java语言中的反射机制可以操作字节码文件,还可以操作代码片段(class文件)
Java反射机制的相关类都在Java.long.reflect.*;包下
3.反射相关的类
4.Class类(反射机制的起源 )
Java文件被编译后,生成了.class文件,JVM此时就要去解读.class文件 ,被编译后的Java文件.class也被JVM解析为 一个对象,这个对象就是 java.lang.Class .这样当程序在运行时,每个java文件就最终变成了Class类对象的一个实 例。我们通过Java的反射机制应用到这个实例,就可以去获得甚至去添加改变这个类的属性和动作,使得这个类成 为一个动态的类 .
5.反射机制相关的API
1.(重要)常用获得类相关的方法
2.常用获得类中属性相关的方法(以下方法返回值为Field相关
- getField(String name) :获得某个公有的属性对象
- getFields() :获得所有公有的属性对象
- getDeclaredField(String name) :获得某个属性对象
- getDeclaredFields() :获得所有属性对象
3.(了解)获得类中注解相关的方法
4.(重要)获得类中构造器相关的方法(以下方法返回值为Constructor相关)
5.(重要)获得类中方法相关的方法(以下方法返回值为Method相关)
- getMethod(String name, Class...<?> parameterTypes) :获得该类某个公有的方法
- getMethods() :获得该类所有公有的方法
- getDeclaredMethod(String name, Class...<?> parameterTypes) :获得该类某个方法
- getDeclaredMethods() :获得该类所有方法
6.反射示例
1.获得Class对象的三种方式
第一种 ,使用 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));
}
}
2.反射的使用
1.产生对象
方法一:调用类的无参构造,且该构造方法必须是public权限!!
// 产生对象
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类来调用构造方法产生对象
Constructer类就是Java中利用反射操作构造方法的类
- getConstructor(参数):获取该类的所有public 权限的构造方法
- getDeclareConstructor:获取该类的所有权限的构造方法,包括私有权限
// 产生对象
public static void reflectNewInstance2() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
// 获取Class对象
Class<Student> classStudent = Student.class;
// 获得所有的构造方法
Constructor<Student>[] constructors = (Constructor<Student>[]) classStudent.getDeclaredConstructors();
System.out.println(Arrays.toString(constructors));
// 获取私有的有参构造
Constructor<Student> constructor = classStudent.getDeclaredConstructor(String.class,Integer.class);
// 破坏封装性·
constructor.setAccessible(true);
// 通过私有构造方法创建对象
Student student = constructor.newInstance("锦鲤",18);
System.out.println(student);
}
反射可以获得所有的不论公有私有的方法和属性,他会破坏封装性,只在当前JVM进程中可见
2.通过反射操作类中的方法
// 操作方法
public static void reflectByMethod() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
// 获取Class对象
Class<Student> 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);
}
7、反射优点和缺点
- 1. 对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法
- 2. 增加程序的灵活性和扩展性,降低耦合性,提高自适应能力
- 3. 反射已经运用在了很多流行框架如:Struts、Hibernate、Spring 等等。
- 1. 使用反射会有效率问题。会导致程序效率降低。具体参考这里:http://www.imooc.com/article/293679
- 2. 反射技术绕过了源代码的技术,因而会带来维护问题。反射代码比相应的直接代码更复杂
反射的讲解就到这里啦!
下篇博客见~