一、反射
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("\n=========================通过反射获得类构造==================\n");
//方法一:
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("\n=========================通过反射获得类的相关信息==================\n");
//获取类的名字
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("\n=========================通过反射获得属性相关信息============================\n");
Field [] fields=c3.getFields();
System.out.println("通过getFies()获得父类和子类的所有共有属性:\n");
for (Field field : fields) {
System.out.println(field);
}
System.out.println("***************************************************************");
//获取当前类的所有共有属性
System.out.println("通过getFies()当前类的所有属性(不论私有共有):\n");
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("\n================================获取类中方法的信息========================\n");
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()//获取所有的构造函数