前言
早在学习Java基础部分就听过,了解过反射这个概念,但是它的具体作用和使用方法没有很明白。刚好最近在学习反射这部分,学完后有了点自己的想法。如下:
一、反射是什么?
概念:反射是Java的一种机制,让我们可以在运行时就能够获取类的信息。
二、作用
在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;它是一种动态获取的信息和动态调用对象的方法的机制。
三、使用方法
1.获取class对象
举例代码:
package com.etime.reflex.demo;
//学生类
public class Student {
private String name;
private String sid;
private int age;
//后面的get/set等省略
....
package com.etime.reflex.demo;
public class GetClazz {
public static void main(String[] args) {
//获取class对象的三种方式
Student stu1= new Student ("aa", "123", 12);
Student stu2= new Student ("bb", "456", 11);
方法一:利用getClass()方法获取对象的class 对象
//1、利用getClass()方法获取对象的class 对象
Class c1 = stu1.getClass();
Class c2 = stu2.getClass();
System.out.println(c1==c2);
方法二:利用类名.class这种获取方式只有在编译前已经声明了该类的类型才能获取到 Class 对象
//2、利用class属性获取字节码文件(
//类.class:需要输入一个明确的类,任意一个类型都有一个静态的class属性)
Class c3 = Student.class;
System.out.println(c1==c3);
方法三:利用Class.forName()获取–最常用的方式
//3、利用Class.forName()获取--最常用的方式
//通过Class类的一个forName(String className)静态方法返回一个Class对象,
//className必须是全路径名称;
//Class.forName()有异常:ClassNotFoundException,这里没抛
Class c4 = Class.forName("com.etime.reflex.demo.Student");
2.通过反射实例化对象
方法一:Class 对象调用newInstance()方法
Object obj = c3.newInstance();
//一般这个Object要转换为对应的具体对象即 Student obj = (Student)c3.newInstance();强转一下
System.out.println(obj.toString())
注意:通过Class对象的newInstance()方法来创建Class对象对应类的实例。这个方法是使用Class对象对应类的默认构造器创建对象,这就要求Class对象对应类必须要有默认构造器(无参数的构造方法)。
方法二:调用Constructor对象的newInstance()方法来创建Class对象对应类的方法
Constructor construct =c3.getConstructor(String.class,String.class,int.class);
Object obj = construct.newInstance("cc","567",13);
System.out.println(obj.toString());
注意:调用Constructor对象的newInstance()方法来创建Class对象。这个方法当Class对象有默认构造器(无参构造方法)时,仍可以使用,把getConstructor()的参数不写即可。
3.通过反射获取类的所有信息
方法一:Field:反编译一个类的属性
//获取class对象
Class c1 = Class.forName("com.etime.reflex.demo.Student");
//反射创建类的实例
Student stu= (Student) c1.newInstance();
//获取公有属性
Field[] fileds = c1.getFields();
for(Field f :fileds){
System.out.println("公有属性:"+f.getName());
}
//获取私有属性
Field[] fileds2 = c1.getDeclaredFields();
for(Field f :fileds2){
System.out.println("私有属性:"+f.getName());
}
注意:
Field[] getFields():获取类中所有被public修饰的所有变量
Field[] getField(String name):根据变量名获取类中的一个变量,该变量必须被public修饰
Field[] getDeclaredFields():获取类中所有的变量,但无法获取继承下来的变量
Field[] getDeclaredField(String name):根据姓名获取类中的某个变量,无法获取继承下来的变量
方法二:Method:获取类中的方法
Class c2= Class.forName("com.etime.reflex.demo.Student");
// 创建对象
Object obj = c2.newInstance();
// 获取Method
Method method = c2.getDeclaredMethod();
Object res = method.invoke();//注:方法返回值是void 结果是null
System.out.println(resValues);
注意:
Method[] getMethods():获取类中被public修饰的所有方法
Method getMethod(String name, Class…<?>paramTypes):根据名字和参数类型获取对应方法,该方法必须被public修饰
Method[] getDeclaredMethods():获取所有方法,但无法获取继承下来的方法
Method getDeclaredMethod(String name, Class…<?>paramTypes):根据名字和参数类型获取对应方法,无法获取继承下来的方法
方法三:Constructor:获取类的构造器
Class c2= Class.forName("com.etime.reflex.demo.Student");
Constructor obj1 = c2.getDeclaredConstructor();
Object obj2 = obj.newInstance();
System.out.println(obj2);
注意:
Constuctor[] getConstructors():获取类中所有被public修饰的构造器
Constructor[] getConstructor(Class…<?> paramTypes):根据参数类型获取类中某个构造器,该构造器必须被public修饰
Constructor[] getDeclaredConstructors():获取类中所有构造器
Constructor[] getDeclaredConstructor(class…<?> paramTypes):根据参数类型获取对应的构造器
总结
写的时候感觉自己越写越蒙,特别是和同学们讨论了一下后发现自己还是有很多东西不是很理解。所以我知道我上面所述肯定有很多错误,希望大佬指正。