Java中的反射
认识反射
一、反射是什么,有什么作用?
反射---在程序运行的过程中,我们可以得到某个类的对象,可以调用某个类中的任何一个变量/方法,这种动态获取信息的过程就是反射。
当我们在没有见过某个类的情况下,仅凭一个完整的类名,就可以获取到整个类的所有信息。
反射的使用场景:
- jdbc加载数据库驱动
- Servlet的web.xml配置
- Spring框架
二、实例对象与反射对象的相互转换?
实例对象-----就是我们通过类创建的对象
反射对象-----通过反射机制得到的类对象
例如:
反射就是一面镜子,镜子前面的你就是实例对象,通过镜子得到的镜子里面的你就是反射对象。
反射对象是一个Class类型的对象
Class---不是创建类的关键字,表示一个类,所以反射对象是一个Class类型的对象
public final class Class<T>
通过实例对象得到反射对象
package com.wangxing.test1;
public class TestMain {
public static void main(String[] args) {
//得到反射对象
//1.通过实例对象得到反射对象[getClass()]
Student stu =new Student();
Class stuclass=stu.getClass();
//2.通过Class类的forname(类名【包名+类名】)
try {
Class stuclass2=Class.forName("com.wangxing.test1.Student");
} catch (Exception e) {
e.printStackTrace();
}
}
}
通过反射对象得到实例对象
package com.wangxing.test1;
public class TestMain {
public static void main(String[] args) {
//通过反射对象得到实例对象[newInstance()]
//Student stu=new Student();
//stu.test1();
try {
Class stuclass=Class.forName("com.wangxing.test1.Student");
Student student=(Student) stuclass.newInstance();
student.test1();
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
}
三、通过反射对象得到构造方法\成员变量\成员方法
Constructor<?>[] | getConstructors() 得到构造方法 | |
Field[] | getDeclaredFields() 得到成员变量 | |
Method[] | getDeclaredMethods() 得到成员方法 | |
Class<?>[] | getInterfaces() 得到接口。 | |
Class<? super T> | getSuperclass() 得到父类。 | |
Package | getPackage() 得到包对象。 | |
int | getModifiers() Java语言修饰符 Modifier的toString(int mod) | |
String | getName() 得到类名称 |
四、反射的应用
//Student类
package com.wangxing.test1;
public class Student extends Person implements MyTestInterface {
private String stuname;
private int stuage;
public Student(){
}
public Student(String name){
this.stuname=name;
}
public void test1(){
System.out.println("Student类的实例方法");
}
public String testString(String args){
return "Hello";
}
}
//Person类
package com.wangxing.test1;
public class Person {
}
//MyTestInterface 类
package com.wangxing.test1;
public interface MyTestInterface {
}
//反射应用,通过反射得到与Student类一样的java类
package com.wangxing.test1;
import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
/**
* 通过反射得到与Student类一样的java类
* @author 14336
*
*/
public class TestMain2 {
private static String testName(String name) {
String classname=name.substring(name.lastIndexOf(".")+1);
return classname;
}
public static void main(String[] args) throws Exception {
Class stuclass= Class.forName("com.wangxing.test1.Student");
//得到Student类的包名
String packname=stuclass.getPackage().getName();
String packageinfo="package "+packname+";";
System.out.println(packageinfo);
//得到Student类的定义信息
//Modifier 类提供了 static 方法和常量,对类和成员访问修饰符进行解码。修饰符集被表示为整数,用不同的位位置 (bit position) 表示不同的修饰符。
//getModifiers()返回此类或接口以整数编码的 Java 语言修饰符。修饰符由 Java 虚拟机的 public、protected、private、final、static、abstract 和 interface 对应的常量组成;它们应当通过 Modifier 类的方法来解码。
String classxiushifu=Modifier.toString(stuclass.getModifiers());
//getName()以 String 的形式返回此 Class 对象所表示的实体(类、接口、数组类、基本类型或 void)名称。
// 如果此类对象表示的是非数组类型的引用类型,则返回该类的二进制名称
//如果此类对象表示一个基本类型或 void,则返回的名字是一个与该基本类型或 void 所对应的 Java 语言关键字相同的 String
//如果此类对象表示一个数组类,则名字的内部形式为:表示该数组嵌套深度的一个或多个 '[' 字符加元素类型名。
/*
* 元素类型 编码
boolean Z
byte B
char C
类或接口 Lclassname;
double D
float F
int I
long J
short S
*/
String leiming=testName(stuclass.getName());
//getSuperclass()返回表示此 Class 所表示的实体(类、接口、基本类型或 void)的超类的 Class。如果此 Class 表示 Object 类、一个接口、一个基本类型或 void,则返回 null。如果此对象表示一个数组类,则返回表示该 Object 类的 Class 对象。
String supername=testName(stuclass.getSuperclass().getName());
//getInterfaces()确定此对象所表示的类或接口实现的接口,如果此对象表示一个类,则返回值是一个数组,它包含了表示该类所实现的所有接口的对象。数组中接口对象的顺序与此对象所表示的类的声明的 implements 子句中的接口名顺序一致
Class interfacearr[]=stuclass.getInterfaces();
//取出接口名称
StringBuilder interinfo=new StringBuilder();
for (Class inter : interfacearr) {
String intername=testName(inter.getName());
interinfo.append(intername+",");
}
interinfo.deleteCharAt(interinfo.length()-1);
String classinfo=classxiushifu+" class "+leiming+" extends "+supername+" implements "+interinfo.toString()+"{";
System.out.println(classinfo);
//得到类中的成员变量
//getDeclaredFields()
/*返回 Field 对象的一个数组,这些对象反映此 Class
* 对象所表示的类或接口所声明的所有字段,
* 包括公共、保护、默认(包)访问和私有字段,
* 但不包括继承的字段。返回数组中的元素没有排序,
* 也没有任何特定的顺序。如果该类或接口不声明任何字段,
* 或者此 Class 对象表示一个基本类型、一个数组类或 void,则
* 此方法返回一个长度为 0 的数组。
*/
//类中成员变量的修饰符
Field fieldarr[]=stuclass.getDeclaredFields();
for (Field field : fieldarr) {
String fieldxiu=Modifier.toString(field.getModifiers());
/* getType()---Field中的方法
* Field 提供有关类或接口的单个字段的信息,以及对它的动态访问权限。反射的字段可能是一个类(静态)字段或实例字段。
* 返回一个 Class 对象,它标识了此 Field 对象所表示字段的声明类型。
返回:标识此对象所表示字段的声明类型的 Class 对象
*/
//数据类型
String fieldleixing=testName(field.getType().getName());
//名称
String fieldname=field.getName();
//
String fieldinfo=fieldxiu+" "+fieldleixing+" "+fieldname+";";
System.out.println("\t"+fieldinfo);
}
//得到类中的构造方法
//getConstructors()返回一个包含某些 Constructor 对象的数组,这些对象反映此 Class 对象所表示的类的所有公共构造方法。如果该类没有公共构造方法,或者该类是一个数组类,或者该类反映一个基本类型或 void,则返回一个长度为 0 的数组。
/*
* Constructor 提供关于类的单个构造方法的信息以及对它的访问权限。
Constructor 允许在将实参与带有基础构造方法的形参的 newInstance() 匹配时进行扩展转换,但是如果发生收缩转换,则抛出 IllegalArgumentException
*/
//通过反射获得类中的构造方法,
Constructor constructorarr[]=stuclass.getConstructors();
for (Constructor constructor : constructorarr) {
String conxiu=Modifier.toString(constructor.getModifiers());
String conname=testName(constructor.getName());
//一个可变的字符序列
StringBuilder canshu=new StringBuilder();
//Constructor中的方法 getParameterTypes()按照声明顺序返回一组 Class 对象,这些对象表示此 Constructor 对象所表示构造方法的形参类型。如果基础构造方法不带任何参数,则返回一个长度为 0 的数组。
//返回:此对象表示的构造方法的参数类型
Class conpyte[]=constructor.getParameterTypes();
if (conpyte.length!=0) {
for (Class typeclass : conpyte) {
String typename=testName(typeclass.getName());
canshu.append(typename+" name,");
}
canshu.deleteCharAt(canshu.length()-1);
}
String coninfo=conxiu+" "+conname+"("+canshu.toString()+"){}";
System.out.println("\t"+coninfo);
}
//得到实例方法
//getDeclaredMethods()
/*返回 Method 对象的一个数组,
* 这些对象反映此 Class 对象表示的类或接口声明的所有方法,
* 包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。
* 返回数组中的元素没有排序,也没有任何特定的顺序。
* 如果该类或接口不声明任何方法,或者此 Class 对象表示一个基本类型、
* 一个数组类或 void,则此方法返回一个长度为 0 的数组。
* 类初始化方法 <clinit> 不包含在返回数组中。
* 如果该类声明带有相同参数类型的多个公共成员方法,
* 则它们都包含在返回的数组中。
* 返回:表示此类所有声明方法的 Method 对象的数组
*/
//Method
//Method 提供关于类或接口上单独某个方法(以及如何访问该方法)的信息。所反映的方法可能是类方法或实例方法(包括抽象方法)。
//Method 允许在匹配要调用的实参与基础方法的形参时进行扩展转换;但如果要进行收缩转换,则会抛出 IllegalArgumentException。
Method methodarr[]=stuclass.getDeclaredMethods();
for (Method method : methodarr) {
String mothxiu=Modifier.toString(method.getModifiers());
//getReturnType()返回一个 Class 对象,该对象描述了此 Method 对象所表示的方法的正式返回类型。
String tereturn=testName(method.getReturnType().getName());
//方法名
String methname=method.getName();
//
StringBuilder canshu=new StringBuilder();
//getParameterTypes() 按照声明顺序返回 Class 对象的数组,这些对象描述了此 Method 对象所表示的方法的形参类型。如果基础方法不带参数,则返回长度为 0 的数组。
//返回:此对象所表示的方法的参数类型
Class methodptype[]=method.getParameterTypes();
if (methodptype.length!=0) {
for (Class canshutypeclass : methodptype) {
String typename=testName(canshutypeclass.getName());
canshu.append(typename+" args,");
}
canshu.deleteCharAt(canshu.length()-1);
}
String methodinfo=mothxiu+" "+tereturn+" "+methname+"("+canshu.toString()+"){}";
System.out.println("\t"+methodinfo);
}
System.out.println("}");
}
}