一、反射
1.什么是反射
反射是指在程序运行期间,能够观察和修改类或者类的对象的属性和行为的特性
2.为什么用反射
在java中有动态和静态的概念
静态是指在java中所有的类都编写好编译通过运行
动态是在在编写好类,编译运行中动态获取类的信息修改类的属性叫做反射.
例如:在已经运行的大项目中需要修改代码,如果项目处于运营,停止项目会带来损失,所以用反射来达到修改代码的作用
3.怎么用反射
Java反射机制提供了以下的功能
在运行时获取类的修饰符,包名,类名,实现的接口,继承的父类
在运行时获取类的所有属性名,修饰符,属性类型
在运行时获取所有方法,方法的返回值类型,方法名,方法参数数量,方法参数类型
在运行时调用加载类的方法
4.反射的练习
创建父类Preson
package dome; public class Preson { private int age; public String name; public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Preson() { System.out.println("Person的空构造"); } public Preson(int age, String name) { this.age = age; this.name = name; System.out.println("Person的有参构造"); } private void say() { System.out.println("Person的私有Say方法"); } public void talk() { System.out.println("Person的共有方法"); } }
创建子类Student
package dome; public final class Student extends Preson implements Runnable{ public int stuid; private String sex; public String nameString; public int getStuid() { return stuid; } public void setStuid(int stuid) { this.stuid = stuid; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public String getNameString() { return nameString; } public void setNameString(String nameString) { this.nameString = nameString; } public Student(int stuid, String sex, String nameString) { super(); this.stuid = stuid; this.sex = sex; this.nameString = nameString; } public Student() { super(); } public Student(int age, String name) { super(age, name); } private String sleep(String name) { return "通过反射我被执行了"; } @Override public void run() { // TODO Auto-generated method stub } @Override public String toString() { return "Student [stuid=" + stuid + ", sex=" + sex + ", nameString=" + nameString + "]"; } }
创建测试类
package dome; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.Arrays; public class Test { public static void main(String[] args) throws Exception { /* * 获取class类的对象 */ System.out.println(" =========================通过反射获得类构造================== "); //方法一: System.out.println("***********************************************************"); Student s1=new Student(); Class c1=s1.getClass(); System.out.println("方法一获取Student的构造"); //方法二: System.out.println("**********************************************************"); Class c2=Student.class; System.out.println("方法二获得的Student构造"); //方法三:(最常用) System.out.println("*******************************"); Class c3 = Class.forName("dome.Student"); System.out.println("方法三(最常用)获得Student构造"); /* * 获取类的构造函数 */ System.out.println("************获取构造函数***********************"); System.out.println("**********************或取当前类所有构造方法*********"); Constructor[] con1=c3.getConstructors(); for (Constructor constructor : con1) { System.out.println(constructor); } //应用构造方法来创建对象的值 System.out.println("通过构造方法我创建了一个对象:"); Constructor con2=c3.getConstructor(int.class, String.class, String.class); Object object=con2.newInstance(13,"aa","bb"); s1=(Student)object; System.out.println(s1); /* * 获取类的信息 */ System.out.println(" =========================通过反射获得类的相关信息================== "); //获取类的名字 System.out.println("*******************************************************************"); System.out.println("通过getname()获取Student类的全称:"+c3.getName()); System.out.println("通过getSimplename()获取Student类的简称:"+c3.getSimpleName()); //获取类的修饰符 获取的对应数字转换为十进制 System.out.println("****************************************************************"); System.out.println("通过getmodifier()获得Student类的修饰符是:"+Modifier.toString(c3.getModifiers())); //查看父类 System.out.println("***************************************"); System.out.println("通过getsuperclass()获得Student的父类并查看名字:"+c3.getSuperclass().getName()); //获取类实现的接口 System.out.println("*********************************************************"); System.out.println("通过getinterface()获得Student的接口"); Class []class5=c3.getInterfaces(); for (Class class1 : class5) { System.out.println(class1); } /* * 获取属性的信息 */ //获取父类和子类的所有属性 System.out.println(" =========================通过反射获得属性相关信息============================ "); Field [] fields=c3.getFields(); System.out.println("通过getFies()获得父类和子类的所有共有属性: "); for (Field field : fields) { System.out.println(field); } System.out.println("***************************************************************"); //获取当前类的所有共有属性 System.out.println("通过getFies()当前类的所有属性(不论私有共有): "); Field[] fields1=c3.getDeclaredFields(); for (Field field : fields1) { System.out.println(field); } System.out.println("**************************************************************"); //获得指定属性 Field field3=c3.getDeclaredField("sex"); System.out.println("获得私有指定的属性:"+field3); Field field4=c3.getField("nameString"); System.out.println("获得共有指定的属性:"+field4); //给指定共有属性赋值 Student student=(Student) c3.newInstance(); field4.set(student, "张三"); System.out.println("给共有属性对象名字赋值:"+student); //给指定私有属性赋值 //打开private的开关 之后才能操作数据 //此处应该应该注意设置值的类型是否和定义属性的类型一致 否则代码编译通过,而运行出错切记切记!!!! field3.setAccessible(true); field3.set(student, "男"); System.out.println("给私有属性对象年龄赋值:"+student); /* * 获取类的方法信息 */ //获取子类和父类的所有公有方法 System.out.println(" ================================获取类中方法的信息======================== "); System.out.println("***********获取子类和父类的所有公有方法****************************"); Method [] methods=c3.getMethods(); for (Method method : methods) { System.out.println(method); } //获取当前类方法 System.out.println("***********获取当前类方法*******************************************"); Method [] methods2=c3.getDeclaredMethods(); for (Method method : methods2) { System.out.println(method); } //获得指定无参方法 System.out.println("***********获取当前类方法*******************************************"); Method method3=c3.getMethod("toString"); System.out.println("获取的指定方法:"+method3); System.out.println("方法的名字:"+method3.getName()); System.out.println("方法的修饰符:"+Modifier.toString(method3.getModifiers())); System.out.println("获得方法的返回值类型:"+method3.getReturnType().getName()); System.out.println("获取方法的参数:"+Arrays.toString(method3.getParameterTypes())); //获得指定带参方法 Method method4=c3.getDeclaredMethod("sleep", String.class); System.out.println("获取的指定方法:"+method4); System.out.println("方法的名字:"+method3.getName()); System.out.println("方法的修饰符:"+Modifier.toString(method4.getModifiers())); System.out.println("获得方法的返回值类型:"+method4.getReturnType().getName()); System.out.println("获取方法的参数:"+Arrays.toString(method4.getParameterTypes())); //执行指定方法 System.out.println("************************************************************"); System.out.println("通过反射执行的共有无参的方法"+ method3.invoke(student)); method4.setAccessible(true); System.out.println("通过反射执行的私有有参的方法"+method4.invoke(student, "name")); } }
5.反射的方法总结
将类结构转换为Class类的实例可以用的方法
- 类名.class
- new 类名.getClass()
- Class.forName(String className)
获取指定类继承的父类包括实现的接口
变量名.getSuperclass().getSimpleName()//获取父类的简单名称
变量名.getInterfaces()//获取所有接口
获取访问修饰符
Modifier.toString(变量名.getModifiers())
获取所有成员变量
getField(String name)//获取单个成员变量(只能获取到非私有的)
getFields()//获取所有成员变量(只能获取到非私有的)
getDeclaredFields()//获取所有成员变量(都可以获取包括private)
getDeclaredField()//获取单个成员变量(都可以获取包括private)
newInstance()//与通过new关键字创建的实例对象一样
setAccessible(true)//屏蔽字段私有性
getType().getSimpleName()//获取简单的变量类型
获取所有成员方法
getMethods()//所有的方法,包括父类
getMethods()//获取单个方法,括号里面传的是不定长参数
getDeclaredMethods()//获取当前类的所有方法,不包含父类
getDeclaredMethod()//获取当前类的单个方法,括号里面传的是不定长参数
getParameterTypes()//获取方法的参数
getReturnType()//返回值类型
i nvoke()//执行方法
获取构造函数
getConstructor()//获取指定参数的构造函数,括号里传的是不定长参数,类型后面不要忘记加class
constructor.newInstance()//给获取到的单个构造函数赋值
getConstructors()//获取所有的构造函数