反射
主要部分
1.理解反射的机制,为什么java语言中会有反射,为什么会有反射的概念。
2.反射中class对象的常见方法的基本使用。
3.熟悉和理解反射在java中的重要应用场景。
一.概念题
-
反射的概念。
Reflection(反射),是java被视为动态语言的关键,反射机制允许程序在执行期间借助于Reflection API 取得任何类的内部信息,并能直接操作任何对象的内部属性及其方法。
-
了解反射产生的原因,并简要概述。
Java属于先编译再运行的语言,程序中对象的类型在编译期就确定下来了,而当程序在运行时可能需要动态加载某些类,这些类因为之前用不到,所以没有被加载到JVM。而通过反射,可以在运行时动态地创建对象并调用其属性,不需要提前在编译期知道运行的对象是谁。
用途:
1、反编译:.class–>.java
2、通过反射机制访问java对象的属性,方法,构造方法等
3、当我们在使用IDE,比如Ecplise时,当我们输入一个对象或者类,并想调用他的属性和方法时,一按点号,编译器就会自动列出他的属性或者方法,这里就是用到反射。
4、反射最重要的用途就是开发各种通用框架。比如很多框架(Spring)都是配置化的(比如通过XML文件配置Bean),为了保证框架的通用性,他们可能需要根据配置文件加载不同的类或者对象,调用不同的方法,这个时候就必须使用到反射,在运行时动态加载需要的加载的对象。
-
反射的机制,简要概述反射机制在创建对象的原理。
加载完类之后,在堆内存放的方法区中就产生了一个Class类型的对象(一个类只有一个Class对象)这个对象就包含了完整的类的结构信息。我们可以通过这个对象看到类的结构。这个对象就像是一面镜子,透过这面镜子看到类的结构,所以,我们形象的称之为:反射
正常方式:引入需要的包类名称---->通过new实例化---->取得实例化对象
反射方式:实例化对象---->getClass()方法----->得到完整的包类名称
二.编程题
编写一个student类,通过反射机制获取其实例并将实例对象中的所有数据输出到student.txt文件中,
源码中创建student类的对象时不允许通过new关键字创建对象。
public class demo01 {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
//获得一个对象
Class c1 = Class.forName("java0019.Student");
//通过构造器创建对象
Constructor declaredConstructor = c1.getDeclaredConstructor(String.class, int.class, int.class);
Student s1 = (Student) declaredConstructor.newInstance("小明", 001, 18);
try {
// 创建一个打印输出流,输出的目标为"F:\\QQGG\\Student.txt"
PrintStream f1 = new PrintStream("F:\\QQGG\\Student.txt");
//把创建的打印输出流赋给系统,向f1输出
System.setOut(f1);
System.out.println(s1.getName()+","+s1.getId()+","+s1.getAge());
f1.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
class Student {
private String name;
private int id;
private int age;
public Student() {
}
public Student(String name, int id, int age) {
this.name = name;
this.id = id;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", id=" + id +
", age=" + age +
'}';
}
}
三.挑战题
将上述问题改写,不允许出现任何类中任何的原方法在main函数中,只能使用反射包中的方法完成对对象的创建和操作,同时完成操作。
public class demo01 {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
//获得一个对象
Class c1 = Class.forName("java0019.Student");
//通过构造器创建对象
Constructor declaredConstructor = c1.getDeclaredConstructor(String.class, int.class, int.class);
Student s1 = (Student) declaredConstructor.newInstance("小明", 001, 18);
try {
// 创建一个打印输出流,输出的目标为"F:\\QQGG\\Student.txt"
PrintStream f1 = new PrintStream("F:\\QQGG\\Student.txt");
//把创建的打印输出流赋给系统,向f1输出
System.setOut(f1);
System.out.println(s1.toString());
f1.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
class Student {
private String name;
private int id;
private int age;
public Student() {
}
public Student(String name, int id, int age) {
this.name = name;
this.id = id;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return
"name=" + name +
", id=" + id +
", age=" + age ;
}
}
### 补充:
反射机制:
加载完类之后,在堆内存放的方法区中就产生了一个Class类型的对象(一个类只有一个Class对象)这个对象就包含了完整的类的结构信息。
我们可以通过这个对象看到类的结构。这个对象就像是一面镜子,透过这面镜子看到类的结构,所以我们形象地称之为:反射
反射机制在创建对象的原理:
正常方式:引入需要的包类名称---->通过new实例化---->取得实例化对象
反射方式:实例化对象---->getClass()方法----->得到完整的包类名称
反射应用
Java反射机制主要提供了以下功能:
在运行时判断任意一个对象所属的类;
在运行时构造任意一个类的对象;
在运行时判断任意一个类所具有的成员变量和方法;
在运行时调用任意一个对象的方法;
生成动态代理。
用途:
1、反编译:.class-->.java
2、通过反射机制访问java对象的属性,方法,构造方法等
3、当我们在使用IDE,比如Ecplise时,当我们输入一个对象或者类,并想调用他的属性和方法时,一按点号,编译器就会自动列出他的属性或者方法,这里就是用到反射。
4、反射最重要的用途就是开发各种通用框架。比如很多框架(Spring)都是配置化的(比如通过XML文件配置Bean),为了保证框架的通用性,他们可能需要根据配置文件加载不同的类或者对象,调用不同的方法,这个时候就必须使用到反射,在运行时动态加载需要的加载的对象。
--------------------------------------------------------------------------------
java.lang.class :代表整个字节码文件,代表一个类型
java.lang.reflect.Method :代表字节码中的方法字节码
java.lang.reflect.Constructor :代表字节码中的构造方法字节码
java.lang.reflect.Field :代表字节码中的属性字节码
获取java.lang.Class实例的三种方式
方式一:Class c = Class.forName(“完整类名带包名”);
方式二:Class c = 引用getClass();
方式三:Class c = 任何类型.class;