J2EE(反射)

本文详细介绍了J2EE中的反射机制,包括反射的定义、作用,如何获取类类,反射实例化的方法,动态调用无参和有参方法,以及通过反射读取对象属性。反射提供了解析类动态信息的能力,增强了程序的灵活性。
摘要由CSDN通过智能技术生成

目录

前言

 一:反射

1,定义

2.作用/为什么要学反射

二:类类

1.什么是类类?

2.类类的三种获取方式:

 1.如何获取类类

 2.类实例

三.反射实例化

四.反射动态方法调用

1.调用无参的共有方法

1.调用无参的共有方法

  2.调用一个有参数的共有方法

 3.调用两个个有参的 私有方法

 五: 反射读取属性

总结


前言

提示:这里可以添加本文要记录的大概内容:

今天分享的是J2EE中的反射,本文章介绍了反射的使用和定义


 一:反射

1,定义

反射是JAVA语言中一种机制,通过该机制可以动态的实例化对象,读取属性,以及调用方法。

2.作用/为什么要学反射

java的反射机制就是增加程序的灵活性,避免将代码写的太死,使其更灵活。

二:类类

1.什么是类类?

举个通俗易懂的例子:比如旺财是狗类的实例,张三是学生类的实例,而狗类和学生类以及其他所有的类又是类类的实例 所以说类类就是其他类的上一级,其他类就是类类的实例

2.类类的三种获取方式:

例:学生类

package com.mgy.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());
	}
}

其中包括:三个属性,无参的构造方法,带一个参的公有的构造方法,带两个参的公有的构造方法

无参的公有方法:hello()       带一个参的公有方法 hello(String name)   带两个参的私有方法(integer a,interger b)

 1.如何获取类类

用类名点class

列如:

Class clz1=Student.class;

 2.类实例

//2、类实例.getClass()
//        确定本工程有这个类,才可以实例化
        Student stu=new Student();
//        本工程没有这个类,也可以编译通过,但是会在运行期报错
//        Object newInstance = Class.forName("com.ycx.reflect.Student").newInstance();
        Class clz2 = stu.getClass();

3.Class.forName("类的全路径名")

例:

//3、Class.forName("类的全路径名");
        Class clz3 = Class.forName("com.ycx.reflect.Student");

三.反射实例化

什么时候用到?

我们可以通过直接实例来拿到一个类的公开的方法,但是拿不到私有的,此时就需要反射实例化

例:上文中的学生类

* 反射实例化
 1、无参数  共有的构造方法
  2、有参数  共有的构造方法
 3、有多个参数  共有的构造方法
4、私有的构造方法 

注意:所有的反射皆从获取类类开始!!!

反射中的方法:

1.调用无参的共有的构造方法  同时也是默认的

类类.newInstance();

  2.有参数 共有的构造方法

拿到构造器对象 三个.代表可以传1个或n个参数   拿到一个参数为String的构造器对象,调用类中的方法,括号中填方法参数的类型.class
类类.getConstructor(String.class);

  3、.getDeclaredConstructor();     调用类中的方法,  其中括号里面是填的类型

类类.getDeclaredConstructor(Integer.class);

4.getConstructor与getDeclaredConstructor的区别:

getConstructor只能够获取共有的构造方法,要获取私有的构造器getDeclaredConstructor

但是 很多小伙办在调用了getDeclaredConstructor之后却报错

  解决方法:getDeclaredConstructor 需要设置访问权限

.setAccessible(true);

完整案例:

package com.mgy.reflect;
 
import java.lang.reflect.Constructor;
 
/**
 * 反射实例化
 * 1.无参数 共有的构造方法
 * 2.有参数 共有的构造方法
 * 3.有多个参数 共有的构造方法
 * 4.私有的构造方法
 * @author Administrator 莫国煜
 * 下午7:12:41
 */
public class Demo2 {
	public static void main(String[] args) throws Exception, Exception {
		Student stu1 = new Student();
		Student stu2 = new Student("s001");
		Student stu3 = new Student("s001", "fjsdk");
		
		System.out.println("***************以下均为反射方式实例化对象");
		//获取类类
		Class<? extends Student> clz1 = stu1.getClass();
//		默认就是调用无参的 共有的 构造函数
//		1.无参数 共有的构造方法
		Student stu4 = clz1.newInstance();
//		2.有参数 共有的构造方法
//		拿到构造器对象 三个.代表可以传1个或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.私有的构造方法
//		getConstructor只能够获取共有的构造方法,要获取私有的构造器getDeclaredConstructor
		Constructor<? extends Student> c3 = clz1.getDeclaredConstructor(Integer.class);
		//打开访问权限
		c3.setAccessible(true);
		Student stu7 = c3.newInstance(18);
	}
}

运行结果:参照Student类中的打印结果

四.反射动态方法调用

1.调用无参的共有方法

调用步骤: 

 1.先拿到类类

 2.拿到方法对象       

 3.调用对应的方法

1.调用无参的共有方法

	    //拿到类类
		Class<Student> clz=Student.class;
		//name:方法名    parameterTypes:方法对应的参数
//		拿到方法对象
		Method m1 = clz.getMethod("hello");
//		1.调用对应的方法
//		第一个参数:那个类实例  第二个参数:方法调用时的实参
//		m1.invoke方法调用的返回值 就是 方法对象本身的返回值 hello方法的返回值
		Object invoke = m1.invoke(clz.newInstance());
		System.out.println(invoke);

结果:

  2.调用一个有参数的共有方法

//        2.调用一个参数的构造方法
        Method m2 = clz.getMethod("hello", String.class);
        Object invoke2 = m2.invoke(clz.newInstance(), "张三");
        System.out.println(invoke2);
//        

结果:

 3.调用两个个有参的 私有方法

//3调用两个个有参的 私有方法
        Method m3 = clz.getDeclaredMethod("add", Integer.class,Integer.class);
        m3.setAccessible(true);
        Object invoke3 = m3.invoke(clz.newInstance(), 5,5);
        System.out.println(invoke3);

结果:

 五: 反射读取属性

需求:读取对象的每一个属性

如果换做我们没有学反射之前来完成这个需求的话,我们可能会这样操作

package com.mgy.reflect;
 
import java.lang.reflect.Field;
 
/**
 * @author Administrator 莫国煜
 *下午5:38:18
 */
 
public class Demo4 {
	public static void main(String[] args) throws Exception {
		Student stu = new Student("s003", "张三");
		stu.age=20;
//		拿到这个学生所有的属性以及属性值
		System.out.println("age:"+stu.age);
		System.out.println("sname"+stu.getSname());
		System.out.println("sid:"+stu.getSid());
	
	}
}

 读取结果:

 思考一下以下两个问题

1.如果我们事先不知道这个类有几个属性呢?

2.假设这个类有几十个属性呢?

所以我们需要使用反射来实现该需求:

package com.mgy.reflect;
 
import java.lang.reflect.Field;
 
/**
 * @author Administrator 莫国煜
 * 下午5:38:18
 */
 
public class Demo4 {
	public static void main(String[] args) throws Exception {
		Student stu = new Student("s003", "张三");
		stu.age=20;
		
//		一切反射从类类开始
		Class<? extends Student> clz = stu.getClass();
//		当前类的所有属性对象
		Field[] fields = clz.getDeclaredFields();
		System.out.println(fields.length);
//		for循环中的f代表每一个属性对象
		for (Field f : fields) {
//			打开访问权限
			f.setAccessible(true);
//			通过属性对象拿到属性名称
			System.out.println(f.getName());
//			拿到当前的属性对象的属性值
			System.out.println(f.get(stu));
		}
	
	}
}

读取结果:

这样以来我们只需要一个for循环就可以得到所有的属性,无论有多少个属性都可以拿到,代码始终不变


总结

以上就是今天要讲的内容,本文仅仅介绍了反射的使用,而反射提供了可以动态的实例化对象,读取属性,以及调用方法。大大的增加程序的灵活性,避免将代码写的太死,使其更灵活。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值