一、反射
1.原理:
每一个封装后的类进行编译,会生成一个字节码文件
当第一次自动使用该类的时候,JVM会把字节码文件加载到方法去区里面,并且生成该字节码文件对应的对象在堆里面。这个对象是Class类型的。
不管是哪一个字节码文件,都会省生成一个对应的对象,这些对象都有共同的特征和行为(类名,属性,构造,方法),根据共同的特征和行为向上抽取一个类,就是Cclass。
Class提供了一些很多的方法功能,对于字节码文件的对象可以调用Class类的功能,可以去获得它对应的字节码文件中的所有数据信息(类名,属性,构造,方法),这就是反射。
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;//所有的反射技术都来自这个包
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import javax.sound.midi.Soundbank;
class Student{
private int no;
public String name;
public Student() {
System.out.println("无参构造");
}
public Student(int no, String name) {
this.no = no;
this.name = name;
System.out.println("带参构造:" + this.no + "," + this.name);
}
public void method() {
System.out.println("无参方法");
}
public String function(String str,int num) {
return "带参方法:" + str + ":" + num;
}
}
public class TestStudent {
public static void main(String[] args) throws Exception {
//对字节码文件进行操作(没有原码)
//获得字节码对应的对象有三种方式
//1.方式一(在代码中直接用上这个类了)
//对象是Student类型
Class<Student> c1 = Student.class;//直接通过类名.class获得
//2.方式二(也在代码中直接用上这个类了,并且创建了一个对象)
//对象是Student类型和Student子类型
Class<? extends Student> c2 = new Student().getClass();//知道类名,创建一个对象,并且getClass获得
//3.方式三 最常用(更灵活,用户可以随意传参)
//对象类型是不确定的
Class<?> c3 = Class.forName("cn.day0720.Student");//加载初始化一个类,必须完全限定名称(包名.类名),来获得对象
/* 属性:Fieid
* 方法:Method
* 构造:Constructor
*/
//----------------属性---------
//1.获得所有的公共的属性
Field [] fs = c3.getFields();
//2.获得所有类型的属性
fs= c3.getDeclaredFields();
for(Field f:fs){
//4.f.getName():获得名称(属性的,构造的,方法的)
System.out.println(f.getName());
//5.f.getType():获得类型
System.out.println(f.getType());
//6.获得访问权限(f.getModifiers())
System.out.println(Modifier.toString(f.getModifiers()));
//获得单个属性
Field f1 = c3.getDeclaredField("name");
//创建一个实例对象
Object obj = c1.newInstance();
//给属性赋值
f1.set(obj, "hello,tom");
//访问属性值
System.out.println(f1.get(obj));
//访问private属性
f1 = c3.getDeclaredField("no");
f1.setAccessible(true);
f1.set(obj, 11);
System.out.println(f1.get(obj));
//----------------方法---------
Method [] ms = c3.getDeclaredMethods();
for(Method m:ms){
//获得方法名称
System.out.println(m.getName());
//获得返回值类型
System.out.println(m.getReturnType());
//获得参数类型
System.out.println(Arrays.toString(m.getParameterTypes()));
}
//单个方法
Method m = c3.getDeclaredMethod("method");
m.invoke(obj);
//带参数的
m = c3.getDeclaredMethod("function", String.class,int.class);
System.out.println(m.invoke(obj, "hello",999));
//----------------构造---------
Constructor [] crs = c3.getDeclaredConstructors();
for(Constructor cr:crs){
System.out.println(Arrays.toString(cr.getParameterTypes()));
}
//获得无参构造
Constructor cr = c3.getEnclosingConstructor();
cr.newInstance();
//获得带参构造
cr = c3.getConstructor(int.class,String.class);
cr.newInstance(22,"guojing");
}
}
}