JAVA反射

J2EE

前言:框架=设计模式+反射。学习和使用框架我们可以不用了解反射,但是为了能更好的去学习和了解框架,我们需要对框架的组成部分进行学习。

目录

J2EE

一、什么是反射

二、反射的优点

三、反射的用途

四、反射的基本使用

1、获取class对象的三种方法

2、反射实例化

3、反射动态调用方法:

4、反射读写属性

总结:


一、什么是反射

反射是java语言中的一种机制,在程序运行时动态加载类并获取类的所有属性和方法。本质:JVM得到class文件,

再将class文件反编译从而获取类的各种信息。

二、反射的优点

1、可以解耦,提供代码的可扩展性

2、在运行时获得类的各种内容,进行反编译,对于Java这种先编译再运行的语言,能够让我们很方便的创建灵活

的代码,这些代码可以在运行时装配。

三、反射的用途

反射是框架的核心的一部分,所有反射可用于各种通用框架的开发。框架可以根据解析配置文件来加载不同的类或

者对象,调用不同的方法,为保证通用性,就需要用到反射。使用反射机制编写的代码是非常灵活的。

反射的本质图解:

四、反射的基本使用

1、获取class对象的三种方法

①Class.forName("全类名")

②类名.class

③对象.getClass()

代码:三种方式获得的都是一个Class对象

student类:用来测试反射方法的类

 

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

获取:

//方式一
		Class stuClz1 = Class.forName("com.zwf.reflect.Student");
		//方式二
		Class stuClz2=Student.class;
		//方式三
		Class stuClz3 = new Student().getClass();

		//比较
		System.out.println(stuClz1==stuClz2);//true
		System.out.println(stuClz2==stuClz3);//true

2、反射实例化

package com.zwf.reflect;

import java.lang.reflect.Constructor;

/**
 * 反射实例化
 * @author zjjt
 *
 */
public class Demo2 {
	public static void main(String[] args) throws Exception {
		//获取student的字节码对象即student类实例
		Class<Student> stuClz1 = (Class<Student>) Class.forName("com.zwf.reflect.Student");
		
		//反编译获取student对象的各种信息,即通过class字节码对象反射获得该对象,默认调用无参构造
		Student stu = (Student)stuClz1.newInstance();
		
		//stu可以当做正常对象使用
		stu.hello();
		
		//DeclaredConstructor和Constructor的区别
		//DeclaredConstructor可以获取类的私有、公有属性或方法,需要获得访问权限;Constructor只能获取公有属性或方法
		//获取student的有参构造方法
		Constructor<Student> c = stuClz1.getDeclaredConstructor(String.class);
		
		//反射方式调用student对象有参构造student对象
		Student s = c.newInstance("zs");
		System.out.println(s);
		
		Constructor<Student> c1 = stuClz1.getDeclaredConstructor(String.class,String.class);
		Student s1 = c1.newInstance("2","ls");
		System.out.println(s1);
		
		Constructor<Student> c2 = stuClz1.getDeclaredConstructor(Integer.class);
		//获取访问权限
		c2.setAccessible(true);
		Student s2 = c2.newInstance(18);
		System.out.println(s2);		
	}
}

3、反射动态调用方法:

package com.zwf.reflect;

import java.lang.reflect.Method;

/**
 * 反射动态方法调用
 * @author zjjt
 *
 */
public class Demo3 {
	public static void main(String[] args) throws Exception {
		//获得student的字节码class对象即student的类实例
		Class<Student> stuClz = (Class<Student>) Class.forName("com.zwf.reflect.Student");
		
		//反编译获取student对象的各种信息,即通过class字节码对象反射获得student类实例,默认调用无参构造
		Student s = stuClz.newInstance();
		
		//通过反射获得该对象的hello方法
		Method m1 = stuClz.getDeclaredMethod("hello");
		
		/**
		 * invoke()
		 * 参数一:类实例,这里是Student的类实例
		 * 参数二:当前被调用的方法,传递参数值。如果无参则不用传
		 * 返回值:被反射调用的方法的返回值.void类型方法返回null
		 * 执行我们通过反射获得的方法体
		 */
		m1.invoke(s);
		
		/**
		 * getDeclaredMethod()
		 * 参数一:方法名称  
		 * 参数二:方法需要传入的参数类型的类对象
		 * 返回值:执行该方法返回的值
		 * 这里就是使用反射的方式来调用我们的方法
		 */
		Method m2 = stuClz.getDeclaredMethod("add", Integer.class,Integer.class);
		//获得访问权限
		m2.setAccessible(true);
		System.out.println(m2.invoke(s, 10 , 5));//15
	}
}

4、反射读写属性

package com.zwf.reflect;

import java.lang.reflect.Field;

/**
 * 反射读写属性
 * @author zjjt
 *
 */
public class Demo4 {
	public static void main(String[] args) throws Exception {
		//获得student类的字节码对象即student类实例
		Class<Student> stuClz = (Class<Student>) Class.forName("com.zwf.reflect.Student");
		//通过反射获取student对象
		Student s = stuClz.newInstance();
		//反射获取sname属性
		Field f = stuClz.getDeclaredField("sname");
		//获得访问权限
		f.setAccessible(true);
		//反射写属性
		f.set(s, "zs");
		//反射读属性
		System.out.println(f.get(s));//zs
		
		//反射获得所有属性
		Field[] fs = stuClz.getDeclaredFields();
		for (Field ff : fs) {
			ff.setAccessible(true);
			System.out.println(ff.getName()+":"+ff.get(s));
		}
	}
}

打印结果:

注意:下面读所有属性时,sname为zs

通过反射获取的student对象s,在操作s时其实就是在操作它的类实例stuClz。

图解:

 

 

总结:

①通过反射这个机制,我们只需要修改xml文件即可实现同样的代码可以获取不同的对象,执行不同的方法。

②字节码文件对象就是每一个类对应的一个类实例。我们其实可以发现这些操作和传统的new来操作在实际运行效果上没有什么区别。但是带入框架来理解,可以看出使用反射机制写出的代码非常灵活,也证实了框架的通用性。

框架=设计模式+反射

③反射还有一个优点,就是当某一个实体类不见了,未涉及到该实体类的模块还是可以正常运行的,如果是传统的编写方式会产生编辑错误,整个项目都不能运行。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小张同学_java

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值