能够获取分析类信息的能力,反射.
反射是如何工作的?这需要了解类的声明周期
由创建的.java文件编译为字节码文件,再在方法区存储class 对象 到在堆内存实例化对象 到卸载
我们来分析一下class里面含有什么 :成员变量、构造器、方法、(父类)
获取类信息磁盘阶段:class.forName("全类名') //全类名是包名加类名
jdbc 加载驱动程序也是用的class.forName
类对象阶段:类名.class
运行时阶段:对象名.getclass()//需要先实例化对象
下面的是需要添加抛出异常的因为后面还有 所以可以throws Exception 就处理了所有抛出异常不用具体写哪一个了就。
我把dog类也写出来方便参考
package keshang;//引入的时候换成自己的包名
// 反射
public class Dog {
private Integer age = 18;
public String name = "小花";
protected Character sex = '男';
String color = "白色";
public Dog(){
}
public Dog(String name){
this.name = name;
}
private Dog(String name,Integer age){
this.name = name;
this.age = age;
}
public void run(int mum){
System.out.println("小花跑的很快"+mum);
}
public void run(){
System.out.println("小花吃的很多");
}
private void flay(){
System.out.println("狗不能飞");
}
private void jump(int num,String name){
System.out.println(name + "能跳" + num + "米");
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Character getSex() {
return sex;
}
public void setSex(Character sex) {
this.sex = sex;
}
@Override
public String toString() {
return "Dog{" +
"age=" + age +
", name='" + name + ''' +
", sex=" + sex +
'}';
}
}
class对象的常用功能
获取全局变量
所有的全局变量被封装在filed数组里面
共有四种:类对象名称 .getfields(); //用数组接收只能获取由public 修饰的变量
Filed [] fileds=class1.getfields();
for(Filed filed: fileds){
System.out.prinln(filed);
}//用for each循环进行输出
l类对象名称.getFields();//用Field[]进行接受 只能获取public 修饰的变量 若此时的类对象名称是class1
四种方式:
Field[] fields=class1.getDeclaredFields();//这是获取所有的成员变量
Field[] fields=class1.getFields();//这是只能获取public 修饰的成员变量
Field field=class1.getField("name");//获取name变量必须是public 修饰的
Field field2=class1.getgetDeclaredField("age");//可以获取任意指定变量
获取之后当然要拿来用的,那么如何获取到他的值呢?
获取成员变量的值肯定也是要分为public 修饰和private修饰是有不同的,也不是一定要private修饰才特殊,只要是在别的类里面不能之际使用修饰符都这样,只是private 常用。
Field c=class1.getDeclaredField("age");//要输出他的值首先要得到这个变量
Dog dog=new Dog();//因为要输出那么一定要有具体的对象才可以需要进行实例化
//age是private修饰的变量因此 需要用上暴力反射
fieldAge.setAccessible(true);
//用object 类型的接受 因为age 类型不明确(总不能每次都区看吧何况有的情况看不见Dog)
//所以用object 这个超类就肯定不会有问题
Object obj=fieldAge.get(dog);//调用get方法参数是你想得到哪一个对象里面的值就写哪个对象
System.out.println(obj);
修改成员变量的值
流程和上面类似的 但是fieldAge调用的方法不一样 是调用set方法
Dog dog1=new Dog();
Field fieldAge=class1.getDeclaredField("age");
fieldAge.setAccessible(true);
fieldAge.set(dog1, 20);//第一个是实例化的对象,第二个参数是要修改成哪一个值
Object obj1=fieldAge.get(dog1);//接受验证一下是否成功
System.out.println(obj1);
获取class的方法
和class的变量不一样 class的方法存在 Method[]数组里面,当然真正写程序的时候都需要调用这些包的。
对于方法的获取Method []methods=class1.getDeclaredMethods();
Method []methods1=class1.getMethods();
Method method=class1.getDeclaredMethod("方法名字(参数类型.class)");//多参数 参数类型.class,参数类型.class
Method method2=class1.getMethod("方法名字(参数类型.class)");
Method methods[]=class1.getDeclaredMethods();//获取所有方法包括父类
Method methods1[]=class1.getMethods();//获取public 类型方法
for(Method method:methods1) {
System.out.println(method);
}
Method runMethod=class1.getMethod("run");//获取无参方法
Method setAgeMethod=class1.getMethod("setAge", Integer.class);//获取有参方法
方法的执行
获取方法后总不能只看着把,那如何执行方法呢?invoke()函数
//执行方法 如果是private修饰需要 方法对象.setAccessible(true) //你得接上前面的获取方法代码 //没有创建对象的话需要先创建对象 //调用invoke方法 第一个参数是对象名dog 第二个是要执行的方法的参数的值如果有的话 runMethod.invoke(dog); setAgeMethod.invoke(dog,33);构造器 获取构造器
构造器存在constructor 数组里面
构造器都是public 修饰的因此 在获取上 declared 加不加没啥差别
Constructor constructors[]=class1.getConstructors();
Constructor constructors1[]=class1.getDeclaredConstructors();
for(Constructor constructor:constructors) {
System.out.println(constructor);
}
构造器的执行这就不能再建立对象了 因为构造器不就是用来初始化对象的值的嘛
Constructor constructor=class1.getConstructor();//调用无参的构造函数
Object o=constructor.newInstance();
System.out.println(o);
System.out.println(constructor);
System.out.println("--------------------------");
Constructor constructor1 = class1.getConstructor(String.class);
System.out.println(constructor1);
Object o1 = constructor1.newInstance("小白");
System.out.println(o1);
System.out.println("--------------------------");
//参数类型是private修饰的
Constructor constructor2 = class1.getDeclaredConstructor(String.class, Integer.class);
constructor2.setAccessible(true);
Object o2 = constructor2.newInstance("小白", 20);
System.out.println(constructor2);
System.out.println(o2);



