反射(*)

前言:后期我们将会学到“框架”,因为框架可以提高开发效率,它本身就是一个“半成品”,框架由两个部分组成:反射+设计模式,所以反射是框架中的重中之重,今天我们来学习一下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!!

评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值