Java之反射

这篇博客介绍了Java中的反射机制,详细阐述了如何通过反射获取类对象的三种方式,并探讨了反射的三大作用:实例化对象、动态调用方法和读写属性。通过具体的代码示例,展示了如何使用java.lang.reflect.*包中的API来实现这些功能。
摘要由CSDN通过智能技术生成

什么是反射

反射java语言中的一种机制,通过这种机制可以动态的实例化对象、读写属性、调用方法

一切反射相关的代码都从获得类(java.lang.Class)对象开始

首先需要一个类:

package com.leiyuanlin.reflect;

import java.io.Serializable;

public class Student implements Serializable{
	private String sid;

	private String sname;

	public Integer age;

	public Student() {
		super();
		System.out.println("调用无参构造方法创建了一个学生对象");
	}
	
	static {
		System.out.println("Student被加载到JVM中");
	}

	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());
	}

	@Override
	public String toString() {
		return "Student [sid=" + sid + ", sname=" + sname + ", age=" + age + "]";
	}
}

获取类对象的3种方式:

1.Class.forName(完整类名)

package com.leiyuanlin.reflect;
/**
 * 如何获取类对象(三种方式)
 * 	1、Class.forName("类的全路径名")
 * 	2、类名.class
 * 	3、类实例.getClass()
 * 
 * 好处:1、提高代码的灵活性
 * 		 2、安全性高
 * @author 2018101801
 *
 */
public class Demo1 {
	public static void main(String[] args) throws Exception {
//		如何获取类对象(三种方式)
//		1、Class.forName("类的全路径名")
		Class cl = Class.forName("com.leiyuanlin.reflect.Student");
		System.out.println(cl);
}

结果:
在这里插入图片描述
2、类名.class

package com.leiyuanlin.reflect;
/**
 * 如何获取类对象(三种方式)
 * 	1、Class.forName("类的全路径名")
 * 	2、类名.class
 * 	3、类实例.getClass()
 * 
 * 好处:1、提高代码的灵活性
 * 		 2、安全性高
 * @author 2018101801
 *
 */
public class Demo1 {
	public static void main(String[] args) throws Exception {
//		如何获取类对象(三种方式)	
//		2、类名.class
		Class cl2 = Student.class;
		System.out.println(cl2);
	}
}

结果:
在这里插入图片描述
3、类(Class类的类对象)实例.getClass()

package com.leiyuanlin.reflect;
/**
 * 如何获取类对象(三种方式)
 * 	1、Class.forName("类的全路径名")
 * 	2、类名.class
 * 	3、类实例.getClass()
 * 
 * 好处:1、提高代码的灵活性
 * 		 2、安全性高
 * @author 2018101801
 *
 */
public class Demo1 {
	public static void main(String[] args) throws Exception {
//		如何获取类对象(三种方式)
//		3、类(Class类的类对象)实例.getClass()
		Student stu = new Student();
		Class cl3 = stu.getClass();
		System.out.println(cl3);
	}
}

结果:
在这里插入图片描述

注意:
1.ClassNotFoundException(类名错|少jar包)
2. 同一类的类对象只会创建一个

反射三大作用(java.lang.reflect.*)

1、实例化对象
方法:c.newInstance()
Constructor.getConstructor/Constructor.getDeclaredConstructor

 注意:一定要提供无参构造器

由上面的student类来做例子

第一种(反射调用无参构造方法创建一个学生对象):

package com.leiyuanlin.reflect;

import java.lang.reflect.Constructor;

/**
 * 反射实例化
 * 	1、能够实例化未知的类
 * 	2、能够通过私有构造器创建实例
 * @author 2018101801
 *
 */
public class Demo2 {
	public static void main(String[] args) throws Exception {
		Class clz = Student.class;
//		反射调用无参构造方法创建一个学生对象
		Student stu = (Student) clz.newInstance();
		System.out.println(stu);
	}
}

结果:
在这里插入图片描述

第二种(反射调用带一个参数的构造方法创建了一个学生对象):

package com.leiyuanlin.reflect;

import java.lang.reflect.Constructor;

/**
 * 反射实例化
 * 	1、能够实例化未知的类
 * 	2、能够通过私有构造器创建实例
 * @author 2018101801
 *
 */
public class Demo2 {
	public static void main(String[] args) throws Exception {
//		反射调用带一个参数的构造方法创建了一个学生对象
//		1、拿到构造器类
		Constructor con = clz.getConstructor(String.class);
//		2、通过构造器实例化对象
		Student stu1 = (Student)con.newInstance("s001");
	}
}

结果:
在这里插入图片描述

第三种(反射调用带二个参数的构造方法创建了一个学生对象):

package com.leiyuanlin.reflect;

import java.lang.reflect.Constructor;

/**
 * 反射实例化
 * 	1、能够实例化未知的类
 * 	2、能够通过私有构造器创建实例
 * @author 2018101801
 *
 */
public class Demo2 {
	public static void main(String[] args) throws Exception {
//		反射调用带二个参数的构造方法创建了一个学生对象
//		1、拿到构造器类
		Constructor con2 =clz.getConstructor(String.class,String.class);
//		2、通过构造器实例化对象
		Student stu2 = (Student)con2.newInstance("s001","zs");
	}
}

结果:
在这里插入图片描述

第四种(反射调用Student类私有的构造方法创建一个学生对象):

package com.leiyuanlin.reflect;

import java.lang.reflect.Constructor;

/**
 * 反射实例化
 * 	1、能够实例化未知的类
 * 	2、能够通过私有构造器创建实例
 * @author 2018101801
 *
 */
public class Demo2 {
	public static void main(String[] args) throws Exception {
//		反射调用Student类私有的构造方法创建一个学生对象
//		getConstructor只能寻找到public修饰的构造器
//		getDeclaredConstructor可以寻找到任何修饰符修饰的构造器
//		java.lang.NoSuchMethodException(找不到方法)
//		1、拿到构造器类
//		Constructor con3 = clz.getConstructor(Integer.class);
		
//		java.lang.IllegalArgumentException: Class com.leiyuanlin.reflect.Demo2 can not access a member of class com.leiyuanlin.reflect.Student with modifiers "private"(不允许访问)
		Constructor con3 = clz.getDeclaredConstructor(Integer.class);
//		setAccessible(设置访问权限)默认不能访问私有方法,设置为true则允许访问
		con3.setAccessible(true);
//		2、通过构造器实例化对象
		Student stu3 = (Student)con3.newInstance(123);
	}
}

结果:
在这里插入图片描述

2、动态调用方法
Method m;
m.invoke

同上用student类举例

第一种(调用无参方法):

package com.leiyuanlin.reflect;

import java.lang.reflect.Method;

/**
 * 反射调用方法
 * @author 2018101801
 *
 */
public class Demo3 {
	public static void main(String[] args) throws Exception {
		Student stu = new Student();
		
		Class clz = stu.getClass();
//		调用无参方法
		Method m = clz.getDeclaredMethod("hello");
		m.invoke(stu);
	}
}

结果:
在这里插入图片描述

第二种(调用有参方法):

package com.leiyuanlin.reflect;

import java.lang.reflect.Method;

/**
 * 反射调用方法
 * @author 2018101801
 *
 */
public class Demo3 {
	public static void main(String[] args) throws Exception {
		Student stu = new Student();
		
		Class clz = stu.getClass();
//		调用有参方法
		Method m = clz.getDeclaredMethod("hello",String.class);
		m.invoke(stu,"zs");
	}
}

结果:
在这里插入图片描述

第三种(调用私有方法):

package com.leiyuanlin.reflect;

import java.lang.reflect.Method;

/**
 * 反射调用方法
 * @author 2018101801
 *
 */
public class Demo3 {
	public static void main(String[] args) throws Exception {
		Student stu = new Student();
		
		Class clz = stu.getClass();
//		调用私有方法
		Method m = clz.getDeclaredMethod("add",Integer.class,Integer.class);
		m.setAccessible(true);
//		invoke 如果反射动态调用的方法是被void所修饰,那么返回的就是null
//		如果反射动态调用的方法是不被void所修饰,那么返回的就是被调用的方法的返回值
		Object invoke = m.invoke(stu,3,4);
		System.out.println(invoke);
	}
}

结果:
在这里插入图片描述

3、读写属性
Field set/get

同上举例

赋值、取值:

package com.leiyuanlin.reflect;

import java.lang.reflect.Field;

/**
 * 反射属性赋值取值
 * 
 * 反射能将jsp传递过来的参数直接封装到实体类中
 * @author 2018101801
 *
 */
public class Demo4 {

	public static void main(String[] args) throws Exception {
		Student stu = new Student();
		stu.age = 22;
		Class clz = stu.getClass();
//		赋值
		Field field = clz.getDeclaredField("sid");
		field.setAccessible(true);
		field.set(stu, "s001");
		System.out.println(stu);
//		取值
		System.out.println(field.get(stu));

}

结果:
在这里插入图片描述

取值:

package com.leiyuanlin.reflect;

import java.lang.reflect.Field;

/**
 * 反射属性赋值取值
 * 
 * 反射能将jsp传递过来的参数直接封装到实体类中
 * @author 2018101801
 *
 */
public class Demo4 {

	public static void main(String[] args) throws Exception {
		Student stu = new Student("s002","zs");
		stu.age = 22;
		Class clz = stu.getClass();
		
		Field[] fields = clz.getDeclaredFields();
		for (Field field : fields) {
			field.setAccessible(true);
			System.out.println(field.getName()+ ":" + field.get(stu));
		}
	}

}

结果:
在这里插入图片描述
感谢观看!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值