一、反射的概述
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象.
1.1 什么是反射
反射java语言中的一种机制,通过这种机制可以动态的实例化对象、读写属性、调用方法
1.2反射的核心
一切反射相关的代码都从获得类对象开始
获取对象的方式
在此之前我们需要有一个实列化的包
分为三种
1:通过对应类实列(java.lang .Class)的类实列(Stuent.class)的方法获取
Student stu=new Student();//获取Student 的class的一个实列
Class clz=stu.getClass();//获得Class
2:通过class.forName(“类的全路径”);JDBC的驱动加载用到反射技术
//Class clz = Class.forName("com.zking.reflect.Student");
3:类实列.class 做通用查询的时候用到
Class clz=Student.class;//3 作为参数来传
利用反射进行实列化
思考:
利用反射经行实列化
能够获取Students.class
如何通过Student.class拿到Student的一个实列?
反射的好处?
能够将未知的类经行实列化
注意:
① ClassNotFoundException(类名错|少jar包)
② 同一类的、类对象只会创建一个
1.调用无参的构造函数
Class clz=Student.class;
//通过反射的方式调用无参构造函数
Student stu = (Student) clz.newInstance();//将未知的类经行实列化
2.调用含有一个参的构造函数
//通过反射的方式调用带有一个参数的构造器来实列化 Class
//(String.class是对class的一种实列 描述了所有带class的文件)
Constructor c = clz.getConstructor(String.class);//可变参数
Student stu = (Student) c.newInstance("s001");
3.调用两个参的构造函数
//通过反射的方式调用带有两个参数的构造器来实列化 Class
//(String,class是对class的一种实列 描述了所有带class的文件)
Constructor c = clz.getConstructor(String.class,String.class);//可变参数
Student stu = (Student) c.newInstance("s001","zs");
4.调用私有化的构造函数
//通过反射的的方式调用私有化的构造器来实列化对象
Constructor c = clz.getDeclaredConstructor(Integer.class);//可变参数
c.setAccessible(true);//打开访问权限
Student stu =(Student) c.newInstance(23);
getConstructor 与getDeclaredConstructor 的区别
getConstructor 获取到的是public 修饰的
getDeclaredConstructor获得的是所有的构造器
动态方法调用
//第一个参数指的是,类类的类实列的类实列
//第二个参数指的是调用方法所携带的可变参数
//Method类invoke方法的返回值就是被调用的方法的返回值
//如果被调用的方法不具备返回值,那么就返回null
1.无参的构造函数
Class clz=Student.class;
Method m = clz.getDeclaredMethod("hello");//可变参数可传可不传
//m.invoke(clz.newInstance());//当前对象的实列(具体的实列)
System.out.println(m.invoke(clz.newInstance()));
2.含有一个参数的构造函数
Method m=clz.getDeclaredMethod("hello", String.class);
Object invoke = m.invoke(clz.newInstance(), "xxx");
3.含有私有化的构造函数
Method m=clz.getDeclaredMethod("add", Integer.class,Integer.class);
m.setAccessible(true);//打开访问权限
Object invoke = m.invoke(clz.newInstance(), 20,5);
System.out.println(invoke);
读写属性
1.获取属性值
public static void main(String[] args) throws Exception {
Student stu=new Student("s001","zs");
stu.age=23;
Class clz=stu.getClass();
//获取属性值 获取
Field[] fields = clz.getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
System.out.println(field.getName()+":"+ field.get(stu));
}
2.设置属性值 共有的
Field field = clz.getDeclaredField("age");
field.set(stu, 45);
System.out.println(stu.age);
3.设置属性值 私有的
Field field = clz.getDeclaredField("sname");
field.setAccessible(true);
field.set(stu, "ls");
System.out.println(stu.getSname());
举例:
思考
封装后的类,内部的属性一定不能被外界访问吗
内部私有化的方法一定不能够被外界所调用吗?
结果的显示: