13-1、反射简介
1、反射简介
-
1、为什么使用反射?
Java反射最大的好处就是能在运行期间,获得某个类的结构、成员变量,用来实例化。
在Java运行时环境中,对于任意一个类,可以知道这个类有哪些属性和方法。对于任意一个对象,可以调用它的任意一个方法。这种动态获取类的信息以及动态调用对象的方法的功能来自于Java 语言的反射(Reflection)机制。
例如:Servlet 利用反射 动态调用方法处理请求。 -
2、什么是反射?
Java的反射机制它知道类的基本结构,这种对Java类结构探知的能力,我们称为Java类的“自审”。例如:大家都用过Jcreator和eclipse。当我们构建出一个对象的时候,去调用该对象的方法和属性的时候。一按点,编译工具就会自动的把该对象能够使用的所有的方法和属性全部都列出来,供用户进行选择。这就是利用了Java反射的原理,是对我们创建对象的探知、自审。
-
3、反射的机制
Java的反射机制的实现要借助于4个类:Class,Constructor,Field,Method;- class代表的时类对 象,
- Constructor-类的构造器对象,
- Field-类的属性对象,
- Method-类的方法对象。
通过这四个对象我们可以粗略的看到一个类的各个组 成部分。
2、Class 类
-
1、Class 类简介
对象照镜子后可以得到的信息:某个类的数据成员名、方法和构造器、某个类到底实现了哪些接口。对于每个类而言,JRE 都为其保留一个不变的 Class 类型的对象。一个 Class 对象包含了特定某个类的有关信息。Class 对象只能由系统建立对象、一个类在 JVM 中只会有一个Class实例、每个类的实例都会记得自己是由哪个 Class 实例所生成
我们创建了一个类,通过编译(javac.exe)生成对应的.class文件。之后我们使用Java.exe加载(JVM的类加载器完成的)此.class文件,此.class文件加载到内存以后,就是一个运行时类,存在在缓存区。那么这个运行时类本身就是一个Class的实例!
有了Class的实例以后,我们才可以进行如下的操作:
1)创建对应的运行时类的对象。
2)获取对应的运行时类的完整结构(属性、方法、构造器、内部类、父类、所在的包、异常、注解、...)。
3)调用对应的运行时类的指定的结构(属性、方法、构造器)。
4)反射的应用:动态代理。 -
2、获取Class 对象的方式
- 3、Class 类的常用方法
3、Java 类的加载机制
- 1、JVM 类加载过程
- 2、类加载器 ClassLoader 介绍
ClassLoader loader1 = ClassLoader.getSystemClassLoader();//系统类加载器
System.out.println(loader1);
ClassLoader loader2 = loader1.getParent();//扩展类加载器
System.out.println(loader2);
ClassLoader loader3 = loader2.getParent();//引导类加载器获取不到
System.out.println(loader3);//null
Class clazz1 = Person.class;//自定义的类由系统类加载器加载
ClassLoader loader4 = clazz1.getClassLoader();
System.out.println(loader4);
String className = "java.lang.String";//引导类加载器加载
Class clazz2 = Class.forName(className);
ClassLoader loader5 = clazz2.getClassLoader();
System.out.println(loader5);
ClassLoader的用途
//掌握如下:如何加载配置文件
//法一:加载包下的
ClassLoader loader = this.getClass().getClassLoader();
InputStream is = loader.getResourceAsStream("com\\atguigu\\java\\jdbc.properties");//一个类的加载器可以获取输入流
//法二:加载工程目录下的使用文件输入流
FileInputStream is = new FileInputStream(new File("jdbc1.properties"));
Properties pros = new Properties();
pros.load(is);
String name = pros.getProperty("user");
System.out.println(name);
String password = pros.getProperty("password");
System.out.println(password);
4、掌握 Constructor、Method、Field 类的用法
- 1、获取Class的实例(3种)
- 2、创建对应的运行时类的对象
- 3、通过反射获取类的完整结 Field、Method、Constructor、Superclass、Interface、Annotation
Class clazz = Person.class;
//1.getFields():只能获取到运行时类中及其父类中声明为public的属性
Field[] fields = clazz.getFields();
for(int i = 0;i < fields.length;i++){
System.out.println(fields[i]);
}
//2.getDeclaredFields():获取运行时类本身声明的所有的属性
Field[] fields1 = clazz.getDeclaredFields();
for(Field f : fields1){
System.out.println(f.getName());
}
//3.获取属性的各个部分的内容。权限修饰符 变量类型 变量名
Class clazz = Person.class;
Field[] fields1 = clazz.getDeclaredFields();
for(Field f : fields1){
//1.获取每个属性的权限修饰符
int i = f.getModifiers();
String str1 = Modifier.toString(i);
System.out.print(str1 + " ");
//2.获取属性的类型
Class type = f.getType();
System.out.print(type.getName() + " ");
//3.获取属性名
System.out.print(f.getName());
System.out.println();
}
获取运行时类的方法Method
1.获取方法
Class clazz = Person.class;
//1.getMethods():获取运行时类及其父类中所有的声明为public的方法
Method[] m1 = clazz.getMethods();
for(Method m : m1){
System.out.println(m);
}
System.out.println();
//2.getDeclaredMethods():获取运行时类本身声明的所有的方法
Method[] m2 = clazz.getDeclaredMethods();
for(Method m : m2){
System.out.println(m);
}