一、反射是什么
反射即是获取类信息的一种能力!,把某个类的方法,变量,构造器全部获取到,然后加以应用!
二、用反射方法获取类信息
1.首先我们准备好各个类与接口
//Cat 类
public class Cat implements jump,Run {
public int age;
private String name;
protected String color;
double height;
public Cat(int age, String name, String color, double height) {
super();
this.age = age;
this.name = name;
this.color = color;
this.height = height;
}
Cat(){
}
Cat(String color){
this.color=color;
}
public void run(String name,int age,double height) {
System.out.println("小猫的名字叫:"+name);
}
public void run(String name) {
System.out.println("小猫的名字叫"+name);
}
private int setAge(int age) {
System.out.println("aa"+age);
return age;
}
void fly() {
System.out.println("猫不会飞");
}
protected void jump(int num) {
System.out.println("猫能跳"+num+"米");
}
}
// Run与jump接口
public interface Run {
}
public interface jump {
}
创建一个Test类!(接下来我将带领你领略反射的魔力!)
public class Testt {
}
2.获取类(Cat)信息
(1)要想使用反射,就必须先生成类对象
一个类的编译过程
获取类对象有三种方法
public class Testt {
public static void main(String[] args) throws Exception {
Cat cat=new Cat("black");
Class class1=cat.getClass();//方法1
Class class2=Cat.class;//方法2
Class class3=Class.forName("com.qcby.反射.Cat");//方法3 类的路径
System.out.println(class1);
System.out.println(class2);
System.out.println(class2);
}
}
结果:
说明这三种方法是等价的!!!我们获取到了类信息,以变量class1 class2 class3 变量展示
3.获取类的修饰符
类信息存储的形式一般有两种:1.获取相关的集合,2.直接获取
(1)获取相关的集合
import java.lang.reflect.Field;
import java.util.Arrays;
public class Testt {
public static void main(String[] args) throws Exception {
Cat cat=new Cat("black");
Class class1=cat.getClass();//方法1
Class class2=Cat.class;//方法2
Class class3=Class.forName("com.qcby.反射.Cat");//方法3 类的路径
Field[] fields=class3.getDeclaredFields();
System.out.println(Arrays.toString(fields));
}
}
输出如果:
我们获取到了Cat的所有修饰符
如果我们将class3.getDeclaredFields()改成class3.getFields()呢?
所以我们可以看到访问修饰符是 添加Declared可以访问到所有的修饰符(包括private public protected..) 而去掉 Declared只能访问到public 修饰符!
(2)直接获取
import java.lang.reflect.Field;
import java.util.Arrays;
public class Testt {
public static void main(String[] args) throws Exception {
Cat cat=new Cat("black");
Class class1=cat.getClass();//方法1
Class class2=Cat.class;//方法2
Class class3=Class.forName("com.qcby.反射.Cat");//方法3 类的路径
Field ageField= class3.getDeclaredField("age");
Field nameField= class3.getDeclaredField("name");
Field colorField= class3.getDeclaredField("color");
Field heightField= class3.getDeclaredField("height");
System.out.println(ageField);
System.out.println(nameField);
System.out.println(colorField);
System.out.println(heightField);
}
}
结果:
注意:1.当访问private和protected修饰符时,不用Declared就会报错!
2.两种获取类信息的方法我已介绍完毕,后文我将直接使用不再介绍
4.获取类方法:
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;
public class Testt {
public static void main(String[] args) throws Exception {
Cat cat=new Cat("black");
Class class1=cat.getClass();//方法1
Class class2=Cat.class;//方法2
Class class3=Class.forName("com.qcby.反射.Cat");//方法3 类的路径
Field ageField= class3.getDeclaredField("age");
Field nameField= class3.getDeclaredField("name");
Field colorField= class3.getDeclaredField("color");
Field heightField= class3.getDeclaredField("height");
//获取方法
Method[] methods= class3.getDeclaredMethods();
System.out.println(Arrays.toString(methods));
Method[] methods1=class3.getMethods();
System.out.println(Arrays.toString(methods1));
Method run1 = class3.getDeclaredMethod("run",String.class);
System.out.println(run1);
Method run2 = class3.getMethod("run", String.class);
System.out.println(run2);
Method fly= class3.getDeclaredMethod("fly");
System.out.println(fly);
}
}
结果:
4.获取构造器:
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Constructor;
import java.util.Arrays;
public class Testt {
public static void main(String[] args) throws Exception {
Cat cat=new Cat("black");
Class class1=cat.getClass();//方法1
Class class2=Cat.class;//方法2
Class class3=Class.forName("com.qcby.反射.Cat");//方法3 类的路径
Field ageField= class3.getDeclaredField("age");
Field nameField= class3.getDeclaredField("name");
Field colorField= class3.getDeclaredField("color");
Field heightField= class3.getDeclaredField("height");
//获取方法
Method[] methods= class3.getDeclaredMethods();
Method[] methods1=class3.getMethods();
Method run1 = class3.getDeclaredMethod("run",String.class);
Method run2 = class3.getMethod("run", String.class);
Method fly= class3.getDeclaredMethod("fly");
//获取构造器
Constructor[] c1 = class3.getDeclaredConstructors();
System.out.println(Arrays.toString(c1));
Constructor[] c2 =class3.getConstructors();
System.out.println(Arrays.toString(c2));
Constructor c3 =class3.getDeclaredConstructor(String.class);
System.out.println(c3);
}
}
5.获取接口
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Constructor;
import java.util.Arrays;
public class Testt {
public static void main(String[] args) throws Exception {
Cat cat=new Cat("black");
Class class1=cat.getClass();//方法1
Class class2=Cat.class;//方法2
Class class3=Class.forName("com.qcby.反射.Cat");//方法3 类的路径
Field ageField= class3.getDeclaredField("age");
Field nameField= class3.getDeclaredField("name");
Field colorField= class3.getDeclaredField("color");
Field heightField= class3.getDeclaredField("height");
//获取方法
Method[] methods= class3.getDeclaredMethods();
Method[] methods1=class3.getMethods();
Method run1 = class3.getDeclaredMethod("run",String.class);
Method run2 = class3.getMethod("run", String.class);
Method fly= class3.getDeclaredMethod("fly");
//获取构造器
Constructor[] c1 = class3.getDeclaredConstructors();
Constructor[] c2 =class3.getConstructors();
Constructor c3 =class3.getDeclaredConstructor(String.class);
//获取接口
Class[] classes=class3.getInterfaces();
System.out.println(Arrays.toString(classes));
}
}
结果:
三、获取的类信息中的值
我们首先获取类的各个修饰符,其次获取他的构造方法,将获取 的构造方法赋值给变量,再让变量,强制转换为Cat类,看代码:
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Constructor;
import java.util.Arrays;
public class Testt {
public static void main(String[] args) throws Exception {
Cat cat=new Cat("black");
Class class1=cat.getClass();//方法1
Class class2=Cat.class;//方法2
Class class3=Class.forName("com.qcby.反射.Cat");//方法3 类的路径
Field ageField= class3.getDeclaredField("age");
Field nameField= class3.getDeclaredField("name");
Field colorField= class3.getDeclaredField("color");
Field heightField= class3.getDeclaredField("height");
//获取构造器
Constructor c1 =class3.getDeclaredConstructor(int.class,String.class,String.class,double.class);
Constructor c2 =class3.getDeclaredConstructor(String.class);
Cat cat1= (Cat) c1.newInstance(10,"小白","白色",10.44);//强制转换成Cat类!
//获取cat1中修饰符的值
System.out.println(ageField.get(cat1));
System.out.println(nameField.get(cat1));
System.out.println(colorField.get(cat1));
System.out.println(heightField.get(cat1));
}
}
运行结果:
我们成功的获取到了构造方法中的age的值,但是当我们获取name 的时候确保错了
这是因为在Cat类中,name 是由 private修饰的,当应用private修饰的修饰符以及方法时,我们要用到暴力反射
//获取cat1中修饰符的值
System.out.println(ageField.get(cat1));
nameField.setAccessible(true);//暴力反射
System.out.println(nameField.get(cat1));
System.out.println(colorField.get(cat1));
System.out.println(heightField.get(cat1));
这样就允许我们去获取或者修改private 修饰的修饰符或者方法以及构造器了
输出结果:
四、设置类信息的值
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Constructor;
import java.util.Arrays;
public class Testt {
public static void main(String[] args) throws Exception {
Cat cat=new Cat("black");
Class class1=cat.getClass();//方法1
Class class2=Cat.class;//方法2
Class class3=Class.forName("com.qcby.反射.Cat");//方法3 类的路径
Field ageField= class3.getDeclaredField("age");
Field nameField= class3.getDeclaredField("name");
Field colorField= class3.getDeclaredField("color");
Field heightField= class3.getDeclaredField("height");
Constructor c1 =class3.getDeclaredConstructor(int.class,String.class,String.class,double.class);
Constructor c2 =class3.getDeclaredConstructor();
Constructor c3 =class3.getDeclaredConstructor(String.class);
Cat cat1= (Cat) c1.newInstance(10,"小白","白色",10.44);
//暴力反射--->使用private修饰的数据
c2.setAccessible(true);
Cat cat2 = (Cat) c2.newInstance();
Cat cat3 = (Cat) c3.newInstance("黑色");
ageField.set(cat1, 100);
int age1 = (int) ageField.get(cat1);
System.out.println(age1);
//暴力反射private修饰符
nameField.setAccessible(true);
nameField.set(cat1, "花花");
System.out.println(nameField.get(cat1));
System.out.println(colorField.get(cat1));
}
}
xx.set(obj,各参数的值)便是设置值的语句
注意private 修饰的修饰符和方法,需要暴力反射哦~