框架基础-反射
1、静态语言VS动态语言
1-1静态语言:运行时结构不可变的语言:JAVA、C、C++,java称为准动态语言,可以利用反射机制获得类似动态语言的特征,让编程更加灵活。但也会牺牲安全性。
1-2动态语言:在运行时代码可以根据某些条件改变自身结构:C#、JavaScript、PHP、python等
2、反射概念:
2-1反射机制允许程序在执行期借助Reflection API获取任何类的内部信息,并能直接操作任意对象的内部属性及方法。(可以理解为A:idea怎么做到提示、联想。B:demo.java编译后称为demo.class,依然能够改变demo.class的内部)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-83nJQ24N-1691724936488)(assets/反射机制.png)]
3、反射用法:
3-1获取Student类的Class实例:
-
Class c1=Student.class;
-
Class c2=stu1.getClass();
-
Class c3=Class.forName(“包名.Student”);
-
一个类的Class实例在虚拟机里有且仅有一个 Class studentClass1 = Student.class;// cn.bdqn.cn.Student.class Class studentClass2 = new Student().getClass(); Class studentClass3 = Class.forName("cn.bdqn.cn.Student"); System.out.println(studentClass1.hashCode()); System.out.println(studentClass2.hashCode()); System.out.println(studentClass3.hashCode()); 三个Class实例实际是同一个对象,哈希值相同
3-2通过Class实例获取Student类的基本信息
"类全名称:"+studentClass1.getName()
"类简单名称:"+studentClass1.getSimpleName()
"类所在的包名称:"+studentClass1.getPackage().getName()
"父类全名称:"+studentClass1.getSuperclass().getName()
"修饰符对应的常量:"+studentClass1.getModifiers()
3-3通过Class实例操作Student类的Constructor实例
3-3-1获取Constructor实例
//1、获取所有public 修饰的构造函数
Constructor[] constructors1 = studentClass.getConstructors();
//2、获取所有构造函数,没有修饰符限制
Constructor[] constructors2 = studentClass.getDeclaredConstructors();
//3、获取 public 修饰的 指定参数列表的构造函数
Constructor constructor3 = studentClass.getConstructor(String.class, int.class);
//4、获取指定参数列表的构造函数 没有修饰符限制
Constructor constructor4 = studentClass.getDeclaredConstructor(String.class, int.class);
3-3-2获取每个Construtor实例的访问修饰符
for (Constructor constructor : constructors2) {
String xiuShiFu = "";//修饰符
int modifier = constructor.getModifiers(); // 1 7
if ((modifier & Modifier.PUBLIC) == Modifier.PUBLIC) {
xiuShiFu = "PUBLIC";
} else if ((modifier & Modifier.PROTECTED) == Modifier.PROTECTED) {
xiuShiFu = "PROTECTED";
} else if ((modifier & Modifier.PRIVATE) == Modifier.PRIVATE) {
xiuShiFu = "PRIVATE";
} else if ((modifier & Modifier.FINAL) == Modifier.FINAL) {
xiuShiFu = "FINAL";
}
System.out.println("该构造函数的访问修饰符:" + xiuShiFu);
}
3-3-3获取每个Construtor实例的参数列表
for (Constructor constructor : constructors2) {
//获得参数列表的各个类型
Class[] paramTypesClass = constructor.getParameterTypes();//参数列表的类型Class实例
if (paramTypesClass.length == 0) {
System.out.println("无参构造,没有参数列表");
} else {
//有参构造 1个 或多个
System.out.println("该构造函数的参数列表类型为:");
for (int i = 0; i < paramTypesClass.length; i++) {
System.out.print(paramTypesClass[i].getSimpleName() + " ");
}
System.out.println();
}
}
3-4通过Class实例操作Student类的Field实例
3-4-1获取Field实例
//1、获取所有的public修饰的属性
Field [] studentFields1=studentClass.getFields();
//2、获取所有属性 没有public 限制
Field [] studentFields2=studentClass.getDeclaredFields();
//3、获取指定名称的 public修饰的属性
Field studentField3=studentClass.getField("name");
//4、获取指定名称的属性 没有public限制
Field studentField4=studentClass.getDeclaredField("name");
3-4-2获取每个Field实例的基本信息(属性名、属性数据类型、属性访问修饰符)
//获取Student类中的所有属性:修饰符、类型、名称
System.out.println("展示所有属性的信息");
for (int i = 0; i <studentFields2.length ; i++) {
int modifiers=studentFields2[i].getModifiers();
System.out.println("int modifiers:"+modifiers);
System.out.println("属性名:"+studentFields2[i].getName());
System.out.println("属性类型:"+studentFields2[i].getType());
String xiuShiFu="";
if((modifiers&Modifier.PUBLIC)== Modifier.PUBLIC){
xiuShiFu="PUBLIC";
}else if((modifiers&Modifier.PRIVATE)== Modifier.PRIVATE){
xiuShiFu="PRIVATE";
}else if((modifiers&Modifier.PROTECTED)== Modifier.PROTECTED){
xiuShiFu="PROTECTED";
}
System.out.println("访问修饰符:"+xiuShiFu);
if((modifiers&Modifier.FINAL)== Modifier.FINAL){
xiuShiFu="FINAL";
System.out.println("访问修饰符:"+xiuShiFu);
}else if((modifiers&Modifier.STATIC)== Modifier.STATIC){
xiuShiFu="STATIC";
System.out.println("访问修饰符:"+xiuShiFu);
}
System.out.println("===========");
}
3-5通过Class实例操作Student类的Method实例
3-5-1获取Method实例
//1、获取所有的public修饰的方法
Method[] studentMethod1 = studentClass.getMethods();
//2、获取所有方法 没有public 限制
Method[] studentMethod2 = studentClass.getDeclaredMethods();
//3、获取指定名称和参数列表的 public修饰的方法
Method studentMethod3 = studentClass.getMethod("setName", String.class);
//4、获取指定名称的方法 没有public限制
Method studentMethod4 = studentClass.getDeclaredMethod("setName", String.class);
3-5-2获取每个Method实例的基本信息(方法名、返回值类型、参数列表类型、访问修饰符)
//展示所有方法信息1、方法名2、返回值类型3、访问修饰符4、抛出异常种类
for (Method method : studentMethod2) {
System.out.println("方法名:" + method.getName());
System.out.println("返回值类型:" + method.getReturnType().getSimpleName());
System.out.println("参数列表类型:");
Class[] paramClasses = method.getParameterTypes();
for (Class paramClass : paramClasses) {
System.out.print(paramClass.getSimpleName() + " ");
}
System.out.println();
int modifiers = method.getModifiers();
String xiuShiFu = "";
if ((modifiers & Modifier.PUBLIC) == Modifier.PUBLIC) {
xiuShiFu = "PUBLIC";
} else if ((modifiers & Modifier.PRIVATE) == Modifier.PRIVATE) {
xiuShiFu = "PRIVATE";
} else if ((modifiers & Modifier.PROTECTED) == Modifier.PROTECTED) {
xiuShiFu = "PROTECTED";
}
System.out.println("访问修饰符:" + xiuShiFu);
if ((modifiers & Modifier.FINAL) == Modifier.FINAL) {
xiuShiFu = "FINAL";
System.out.println("访问修饰符:" + xiuShiFu);
} else if ((modifiers & Modifier.STATIC) == Modifier.STATIC) {
xiuShiFu = "STATIC";
System.out.println("访问修饰符:" + xiuShiFu);
}
System.out.println("\n===========");
}
3-5-3获取每个Method实例的抛出异常种类
Class[] exceptionClasses = method.getExceptionTypes();
if(exceptionClasses.length>0){//该方法有异常
for (Class exceptionClass:exceptionClasses) {
System.out.print(exceptionClass.getSimpleName()+"\t");
}
}
3-6通过Constructor实例,创建类的对象
//通过ublic 无参构造函数 创建对象
Constructor constructor1 = Student.class.getConstructor();
Object object1 = constructor1.newInstance();
//通过 有参 public 的构造函数 创建对象
Constructor constructor2 = Student.class.getConstructor(String.class, int.class);
Object object2 = constructor2.newInstance("李四", 18);
//通过 有参 private 的构造函数 创建对象
Constructor constructor3 = Student.class.getDeclaredConstructor(String.class);
constructor3.setAccessible(true);//将私有的构造函数设置为可访问
Object object3 = constructor3.newInstance("李四");
3-7通过Field实例,给对象的属性,设置/获取值
Class studentClass = Student.class;
//创建Student实例
Student student = (Student) studentClass.newInstance();
//通过Field对象对实例的属性获取值和设置值
Field nameField = studentClass.getDeclaredField("name");
nameField.setAccessible(true);
//通过Field对象获取name属性值
System.out.println("name属性赋值前的值:" + nameField.get(student));
//通过Field对象设置name属性值
nameField.set(student,"张三");
System.out.println("name属性赋值后的值:" + nameField.get(student));
3-8通过Method实例,作用到对象,实现对象调用方法
Class studentClass = Student.class;
//创建Student实例
Object object = studentClass.newInstance();
//获取Method对象
Method setNameMethod = studentClass.getMethod("setName", String.class);
// public void setName(String name) {
// this.name = name;
// }
setNameMethod.setAccessible(true);//如果是私有的方法/成员,设置为可访问的
//通过调用setName()方法为obj的属性赋值
setNameMethod.invoke(object, "张三");//invoke:调用 method对象.invoke(对象,实参)
System.out.println(object.toString());
Method showMethod = studentClass.getDeclaredMethod("show");
showMethod.invoke(object);
//如果是私有的方法/成员,设置为可访问的
//通过调用setName()方法为obj的属性赋值
setNameMethod.invoke(object, “张三”);//invoke:调用 method对象.invoke(对象,实参)
System.out.println(object.toString());
Method showMethod = studentClass.getDeclaredMethod(“show”);
showMethod.invoke(object);