前言:后期我们将会学到“框架”,因为框架可以提高开发效率,它本身就是一个“半成品”,框架由两个部分组成:反射+设计模式,所以反射是框架中的重中之重,今天我们来学习一下java中的反射,为后期学习框架做铺垫(重点)
JAVA反射
1.什么是反射?
概念:反射是java语言中的一种机制,通过这种机制可以动态的实例化对象、读写属性、调用方法(重点)
2.类类:将所有的类放在一起叫做类类
例如:
所有狗 狗类 Dog (泛指) 狗对象 旺财(特指)
所有猫 猫类 Cat (泛指) 猫对象 肥波(特指)
所有类 类类 java.lang.Class(泛指) 类对象 特定类(特指)
注意:所有与反射相关的架包都在java.reflect.*下
3.一切反射相关的代码都从获得类对象开始
现在有一个学生对象类:
package com.xiaoqing.reflect;
public class Student {
private String sid;
private String sname;
public Integer age;
static{
System.out.println("加载进jvm中!");
}
public Student() {
super();
System.out.println("调用无参构造方法创建了一个学生对象");
}
public Student(String sid) {
super();
this.sid = sid;
System.out.println("调用带一个参数的构造方法创建了一个学生对象");
}
public Student(String sid, String sname) {
super();
this.sid = sid;
this.sname = sname;
System.out.println("调用带二个参数的构造方法创建了一个学生对象");
}
@SuppressWarnings("unused")
private Student(Integer age) {
System.out.println("调用Student类私有的构造方法创建一个学生对象");
this.age = age;
}
public String getSid() {
return sid;
}
public void setSid(String sid) {
this.sid = sid;
}
public String getSname() {
return sname;
}
public void setSname(String sname) {
this.sname = sname;
}
public void hello() {
System.out.println("你好!我是" + this.sname);
}
public void hello(String name) {
System.out.println(name + "你好!我是" + this.sname);
}
@SuppressWarnings("unused")
private Integer add(Integer a, Integer b) {
return new Integer(a.intValue() + b.intValue());
}
}
3.1、Class.forName(完整类名)
测试:
package com.xiaoqing.reflect;
/**
* 获取类对象的方式:
* Class.forName("")
* Xxx.class
* 对象.getClass
* @author 晴sister
*
* https://i.csdn.net/#/uc/profile
*/
public class Demo1 {
public static void main(String[] args) throws Exception {
//Class.forName("")
Class<?> clz = Class.forName("com.xiaoqing.reflect.Student");
System.out.println(clz);
}
}
运行结果如下:
3.2、 类名.class
package com.xiaoqing.reflect;
/**
* 获取类对象的方式:
* Class.forName("")
* Xxx.class
* 对象.getClass
* @author 晴sister
*
* https://i.csdn.net/#/uc/profile
*/
public class Demo2 {
public static void main(String[] args) throws Exception {
//Xxx.class
Class<?> clz = Student.class;
System.out.println(clz);
}
}
运行结果如下:
3.3、 对象.getClass()
package com.xiaoqing.reflect;
/**
* 获取类对象的方式:
* Class.forName("")
* Xxx.class
* 对象.getClass
* @author 晴sister
*
* https://i.csdn.net/#/uc/profile
*/
public class Demo3 {
public static void main(String[] args) throws Exception {
//对象.getClass
Student stu=new Student();
Class clz = stu.getClass();
System.out.println(clz);
}
}
运行结果如下:
4、反射实例化对象
操作student对象类(如下,与上述一样):
package com.xiaoqing.reflect;
public class Student {
private String sid;
private String sname;
public Integer age;
static{
System.out.println("加载进jvm中!");
}
public Student() {
super();
System.out.println("调用无参构造方法创建了一个学生对象");
}
public Student(String sid) {
super();
this.sid = sid;
System.out.println("调用带一个参数的构造方法创建了一个学生对象");
}
public Student(String sid, String sname) {
super();
this.sid = sid;
this.sname = sname;
System.out.println("调用带二个参数的构造方法创建了一个学生对象");
}
@SuppressWarnings("unused")
private Student(Integer age) {
System.out.println("调用Student类私有的构造方法创建一个学生对象");
this.age = age;
}
public String getSid() {
return sid;
}
public void setSid(String sid) {
this.sid = sid;
}
public String getSname() {
return sname;
}
public void setSname(String sname) {
this.sname = sname;
}
public void hello() {
System.out.println("你好!我是" + this.sname);
}
public void hello(String name) {
System.out.println(name + "你好!我是" + this.sname);
}
@SuppressWarnings("unused")
private Integer add(Integer a, Integer b) {
return new Integer(a.intValue() + b.intValue());
}
}
1.无参公有的实例化
2.有一个参数的公有构造器
3.有两个参数的公有构造器实例化
4.私有的构造器实例化
现有一个类来反射实例化对象:
package com.xiaoqing.reflect;
import java.lang.reflect.Constructor;
/**
* 反射实例化对象(重点)
* 1.无参公有的实例化
* 2.有一个参数的公有构造器
* 3.有两个参数的公有构造器实例化
* 4.私有的构造器实例化
* @author 晴sister
*
* https://i.csdn.net/#/uc/profile
*/
public class Demo4 {
public static void main(String[] args) throws Exception{
//oop实例化对象
Student stu=new Student();
Class<? extends Student> clz = stu.getClass();
//反射实例化
// 1.无参公有的实例化
Student stu2 =(Student)clz.newInstance();
System.out.println(stu2);
//为什么学习反射
//答:能够让代码更具有灵活性
//为什么在new关键字实例化对象后,需要学习反射实例化
//答:能够将未知的对象进行实例化
//参考Tomcat运行流程 :仿写Tomcat
// 2.有一个参数的公有构造器(String代表的是参数的数据类型)
System.out.println("------------------------------");
Constructor<? extends Student> c = clz.getConstructor(String.class);
Student stu3 = c.newInstance("s001");
System.out.println(stu3);
// 3.有两个参数的公有构造器实例化
System.out.println("------------------------------");
Constructor<? extends Student> c2 = clz.getConstructor(String.class,String.class);
Student stu4 = c2.newInstance("s001","张三");
System.out.println(stu4);
//4.私有的构造器实例化
//java.lang.NoSuchMethodException:student类中没有integer为参数的构造方法
//getConstructor是获取到public修饰的构造方法
//getDeclaredConstructor能够获取到任意修饰符的构造器
//java.lang.IllegalArgumentException:非法访问.因为这个构造器是private修饰
System.out.println("------------------------------");
Constructor<? extends Student> c3 = clz.getDeclaredConstructor(Integer.class);
//打开通道
c3.setAccessible(true);
Student stu5 = c3.newInstance(22);
System.out.println(stu5);
}
}
运行结果如下:
注意:
1.在私有的构造器实例化中不能使用clz.getConstructor(Integer.class);否则会报java.lang.NoSuchMethodException(异常,注释上打了)
2.在私有的构造器实例化中必须要打开通道c3.setAccessible(true);,否则会报java.lang.IllegalArgumentException(异常):非法访问.因为这个构造器是private修饰
3.java.lang.ClassNotFoundException(异常):类没有找到(拓展知识)
出现这个问题的有两种情况:
3.1.类名错误
3.2.架包没有导入
4.1、我们为什么要学习反射呢?
因为反射是框架中的基石,能够让代码更具有灵活性,反射就效率而言,是更加低效的,如果该框架过多的使用了反射,那么这个框架的运行效率是非常差的
4.2、为什么在new关键字实例化对象后,需要学习反射实例化?
能够将未知的对象进行实例化
现有一个分析图,针对4.1、4.2知识点来论证,如下:
可以参考Tomcat运行流程 : 仿写Tomcat.
5.反射调用方法
此处也是用student对象来进行操作(student中的内容如上第4点)
调用方法
- 1.无参公有的方法调用
- 2.有一个参数的方法调用
- 3.私有的方法调用(记得打开通道)
package com.xiaoqing.reflect;
import java.lang.reflect.Method;
/**
* 调用方法
* 1.无参公有的方法调用
* 2.有一个参数的方法调用
* 3.私有的方法调用
* @author 晴sister
*
* https://i.csdn.net/#/uc/profile
*/
public class Demo5 {
public static void main(String[] args) throws Exception{
Student stu=new Student();
Class<? extends Student> clz = stu.getClass();
//1.无参公有的方法调用
//hello是方法名 invoke:调用
Method m = clz.getMethod("hello");
Object invoke = m.invoke(stu);
//动态被调用的方法,如果该方法是void类型的返回值,那么被invoke,此时结果为null
System.out.println(invoke);
//2.有一个参数的方法调用
System.out.println("-----------------------");
Method m2=clz.getMethod("hello", String.class);
Object invoke2 = m2.invoke(stu, "张三");
System.out.println(invoke2);
//3.私有的方法调用
System.out.println("-----------------------");
Method m3 = clz.getDeclaredMethod("add", Integer.class,Integer.class);
m3.setAccessible(true);
Object invoke3 = m3.invoke(stu, 20,5);
//动态被调用的方法,如果该方法是非void类型的返回值,那么被invoke,就是该被调用方法的结果
System.out.println(invoke3);
}
}
运行结果如下:
6.反射读写属性
1.公有的,私有的读写属性
此处也是用student对象来进行操作(student中的内容如上第4点)
package com.xiaoqing.reflect;
import java.lang.reflect.Field;
/**
* 反射读写属性
* 1.公有的,私有的读写属性
* BaseDao增删改有用
* @author 晴sister
*
* https://i.csdn.net/#/uc/profile
*/
public class Demo6 {
//想知道success这个变量被那些修饰符所修饰 1 2 4 8 16
private static final String success="登录成功";
//private public static final protect
public static void main(String[] args) throws Exception {
Student stu=new Student("s001","zhangshang");
stu.age=23;
Class<? extends Student> clz = stu.getClass();
System.out.println(stu.getSname());
Field f = clz.getDeclaredField("sname");
f.setAccessible(true);
System.out.println(f.get(stu));
System.out.println("----------------------");
//反射读写属性常用方法(一次性获取该类的所有属性值)
Field[] fs = clz.getDeclaredFields();
for (Field field : fs) {
field.setAccessible(true);
//设置值,field.set(类实例化,属性值)
System.out.println(field.get(stu));//可以用在通用查询结果集对象中去ResultSet
}
System.out.println("-----------设置--------------");
//想通过反射改变sname对应的值
f.set(stu, "lisi");
System.out.println(stu.getSname());
}
}
运行结果如下:
7、访问修饰符(看懂案例)
1.getModifiers()
2.作用:使用二进制的方式将所有的修饰符的二进制进行相加
案例:
package com.xiaoqing;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
public class Demo4 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchFieldException {
Student s=new Student();
s.setSname("勇勇");
//System.out.println(s);
//反射机制实例化对象
Class c1=Class.forName("com.zking.Student");//获取类对象
Field field=c1.getDeclaredField("USER_NAME");
int modifer=field.getModifiers();
System.out.println(modifer);
System.out.println(Modifier.PUBLIC);
System.out.println(Modifier.STATIC);
System.out.println(Modifier.FINAL);
}
}
运行结果:
8.总结
后续会继续更新博客!!!!
goodbye!!