目录
一、认识反射
什么是反射: 反射是java语言中的一种机制,通过这种机制可以动态的实例化对象,读写属性,调用方法
反射的用途:许多开发框架都使用到了“反射”,还有jdbc中的类类,它的功能是获取方法、属性等类中的信息;调用类对象的方法;生成动态代理。
大量地使用反射,会造成性能下降
二、类类
什么是类类?
如动物类中的Dog类,Cat类和Person类
而Dog类就是动物类中的实例
那类类的获取方式有哪些?
1.类.class;
package com.lucy.fs;
public class Demo1 {
public static void main(String[] args) throws Exception {
//1.类.class
Class clz1=Student.class;
//本工程没有此类,也可以编译通过
// Object newInstance=Class.forName("com.lucy.fs.Student").newInstance();
}
}
2.类实例.getClass();
//2.类实例.getClass
Student s=new Student();
Class clz2=s.getClass();
3.Class.forName("类的全路径名");
//3.Class.forName("类的全路径名")
Class clz3=Class.forName("com.lucy.fs.Student");
三、反射实例化
方法:
getConstructor(公有方法使用)
getDeclaredConstructor(私有方法使用)
newInstance(实例化)
知识点2:
* 1.无参数 公有的构造方法
* 2.有参数 公有的构造方法
* 3.有多个参数 公有的构造方法
* 4. 私有的构造方法
package com.lucy.fs;
import java.lang.reflect.Constructor;
/**
* @author lucy
*
*/
public class Demo2 {
public static void main(String[] args) throws Exception, IllegalAccessException {
//创建对象
Student stu1=new Student();//无参
Student stu2=new Student("s002");//有参
Student stu3=new Student("s001","哈哈");//多个参数
}
}
效果图如下
一般创建类的方法:
------以下均为反射的方法去创建对象
package com.lucy.fs;
import java.lang.reflect.Constructor;/**知识点2:反射实例化
* 1.无参数 公有的构造方法
* 2.有参数 公有的构造方法
* 3.有多个参数 公有的构造方法
* 4. 私有的构造方法
* @author lucy
*
*/
public class Demo2 {
public static void main(String[] args) throws Exception, IllegalAccessException {
//创建对象
Student stu1=new Student();//无参
// ------以下均为反射的方法去创建对象-------
//获得类类
Class<? extends Student> clz1=stu1.getClass();
//默认调用无参 且公有的构造方法
// 1.无参数 公有构造方法
Student stu4=clz1.newInstance();
// 2.有参数 公有的构造函数
//拿到构造器对象 三个点代表可以传1个 2个 n个参数--->拿到一个参数为String的构造器
Constructor<? extends Student> c1= clz1.getConstructor(String.class);
Student stu5=c1.newInstance("s001");
// 3.有多个(两个) 参数公有的构造方法
Constructor<? extends Student> c2 =clz1.getConstructor(String.class,String.class);
Student stu6=c2.newInstance("s001","张三");
// 4.私有构造方法 要调用此法必须要拿到私有的构造器即getDeclaredConstructor
Constructor<? extends Student> c3= clz1.getDeclaredConstructor(Integer.class);
// 打开访问权限
c3.setAccessible(true);
Student stu7=c3.newInstance(17);//实例化
}
}
效果图如下:
四、反射动态方法调用
方法调用:getMethod
getDeclaredMethod
具体步骤如下:
* 第一步:拿到类类
* 第二步:拿到方法对象
* 第三步: 调用对应的方法
package com.lucy.fs;
import java.lang.reflect.Method;
/**知识点3:反射动态调用方法
* @author lucy
*1.调用无参的 公有构造方法
*2.调用1个有参的 公有构造方法
*3.调用2个有参的 公有构造方法
*4.调用私有的构造方法
*
*/
public class Demo3 {
public static void main(String[] args) throws Exception {
// 1.拿到类类
Class clz=Class.forName("com.lucy.fs.Student");
// 2.拿到方法对象
// name :方法名;parametertypes:方法对应的数
Method m1 =clz.getMethod("hello");
// 3. 调用无参的方法:
// 第一个参数是:那个类实例对象; 第二个参数是:方法调用时的实参
// m1.invoke方法调用的返回值就是方法对象本身的返回hello方法的返回值
Object invoke1=m1.invoke(clz.newInstance());
System.out.println(invoke1);
// 4.调用1个有参的公有方法
Method m2=clz.getMethod("hello",String.class);
Object invoke2= m2.invoke(clz.newInstance(),"李四" );
System.out.println(invoke2);
// 5.有两个参数公有方法
// 略(与例4差不多)
// 6.私有的方法
Method m3=clz.getDeclaredMethod("add",Integer.class,Integer.class);
// 打开权限
m3.setAccessible(true);
//调用方法 ---两个整数值的总合
Object invoke3=m3.invoke(clz.newInstance(),3,3);
System.out.println(invoke3);
}
}
例1-5的效果图:
例6效果图:
五、反射读写属性
用法:类类.getDeclaredFields();多个
类类.getDeclaredField();单个
package com.lucy.fs;
import java.lang.reflect.Field;
/**知识点4:反射读写属性
* @author lucy
*
*/
public class Demo4 {
public static void main(String[] args) throws Exception {
Student stu=new Student("s001","小洲");
stu.age=18;
//需求:要拿到所有属性值
// 一般做法如下:System.out.println("一般做法如下:");
System.out.println("sname:"+stu.getSname());
System.out.println("sid:"+stu.getSid());
System.out.println("sage:"+stu.age);
/**
* 分析:
* 上面代码所存在的问题:
* 1.你如何得知此类有多少属性?
* 2.假设student有30个属性嘞?
*
*/==============================反射方法如下=============================================
// 反射从类类开始
Class clz=stu.getClass();
// 拿到当前类的所有属性
Field[] fields=clz.getDeclaredFields();//复数
// System.out.println(fields.length);
// for循环里的f代表每一个属性对象System.out.println("=============若用反射方法如下===============");
for (Field f : fields) {//遍历属性对象
// 打开访问权限
f.setAccessible(true);
//通过属性对象拿到
System.out.println(f.getName());//属性名
// 拿到属性对象的属性值
System.out.println(f.get(stu));
}
}
}
效果图如下:
===================================未经允许不得复制=============================================================