java 反射

java 反射

1.什么是反射

Java反射就是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;并且能改变它的属性。而这也是Java被视为动态(或准动态,为啥要说是准动态,因为一般而言的动态语言定义是程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言。

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

2.反射能做什么

我们知道反射机制允许程序在运行时取得任何一个已知名称的class的内部信息,包括包括其modifiers(修饰符),fields(属性),methods(方法)等,并可于运行时改变fields内容或调用methods。那么我们便可以更灵活的编写代码,代码可以在运行时装配,无需在组件之间进行源代码链接,降低代码的耦合度;还有动态代理的实现等等;但是需要注意的是反射使用不当会造成很高的资源消耗!

3.获取类对象的方式

这里有一个Student类

package com.zking.refle;

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;
2 、对象名.getClass();
3 、Class.forName(全限定名/全路径名);

package com.zking.refle;

/**
 * 获取类对象的方式
 * 		获取java。lang。class的一个类实例
 * 		-->对于本堂课而言,Student.class
 * 		1.通过对应类(java。lang。class)实例的类(Student.class)的getClass()方法获取
 * 			通用增删改的时候用到
 * 		2.通过Class。forNmae(“类的全路径”);JDBC的驱动加载就是用的反射技术
 * 		3.类实例.class
 * 			做通用查询的时候用到
 * 		
 * @author huguiyun
 *
 */

public class Demo2 {
	public static void main(String[] args) throws Exception {
//		Student stu = new Student();
//		Class clz = stu.getClass();方式一
		
//		Class clz = Class.forName("com.zking.refle.Student");方式二
		
//		Class clz = Student.class;方式三
//		System.out.println(clz);
		
		
		
	}
}

②、通过 Class 类获取成员变量、成员方法、接口、超类、构造方法等

查阅 API 可以看到 Class 有很多方法:

getName():获得类的完整名字。

getFields():获得类的public类型的属性。

getDeclaredFields():获得类的所有属性。包括private 声明的和继承类

getMethods():获得类的public类型的方法。

getDeclaredMethods():获得类的所有方法。包括private 声明的和继承类

getMethod(String name, Class[] parameterTypes):获得类的特定方法,name参数指定方法的名字,parameterTypes 参数指定方法的参数类型。

getConstructors():获得类的public类型的构造方法。

getConstructor(Class[] parameterTypes):获得类的特定构造方法,parameterTypes 参数指定构造方法的参数类型。

newInstance():通过类的不带参数的构造方法创建这个类的一个对象。

4.利用反射进行实例化

实例化对象 c.newInstance()

clz.getConstructor 获取的是public修饰的
clz.getDeclaredConstrutor(); -->获取单个构造方法(包括私有、受保护、默认、公有)。 如果要调用有参构造函数就必须先调用这个方法

package com.zking.refle;

import java.lang.reflect.Constructor;

/**
 * 利用反射进行实例化
 * 		能够获取到student.class
 * 			如何通过Student.class拿到Student的一个实例
 * 
 * 反射的好处?
 * 		能够将未知的类进行实例化  没有就报错ClassNotFoundException
 * 
 * 
 * @author huguiyun
 *
 */

public class Demo3 {
	public static void main(String[] args) throws Exception {
		
		Class clz = Student.class;
		
		//通过反射的方式来调用无参构造器来实例化对象
//		Student stu = (Student)clz.newInstance();
		
		//通过反射的方法调用带有一个参数的构造器来实例化对象 class
//		Constructor c = clz.getConstructor(String.class);
//		Student stu = (Student)c.newInstance("s001");
		
		//通过反射的方法调用带有二个参数的构造器来实例化对象 class
//		Constructor c = clz.getConstructor(String.class,String.class);
//		Student stu = (Student)c.newInstance("s001","zs");
		
		//通过反射的方法调用私有的构造器来实例化对象 class
//		getConstructor 与 getDeclaredConstructor 的区别
//		getConstructor获取到的是public修饰的
//		getDeclaredConstructor 获取所有的构造器
		Constructor c = clz.getDeclaredConstructor(Integer.class);
		c.setAccessible(true);//打开访问权限
		Student stu = (Student)c.newInstance(23);
		
	}

}


5.动态方法调用

package com.zking.refle;

import java.lang.reflect.Method;

/**
 * 动态方法调用
 * 
 * 
 * @author huguiyun
 *
 */
public class Demo4 {
	public static void main(String[] args) throws Exception {
		Class clz = Student.class;
//		Method m = clz.getDeclaredMethod("hello");//调用无参的方法
		//第一个参数指的是,类类的类实例的类实例
//		第二个参数指的是调用方法所携带的可变参数
//		Method类invoke方法的返回值就是被调用的方法的返回值
//		如果被调用的方法的不具备返回值,那么返回null
//		Object invoke = m.invoke(clz.newInstance());
//		System.out.println(m.invoke(clz.newInstance()));
		
//		Method m = clz.getDeclaredMethod("hello",String.class);//调用有参的方法
//		m.invoke(clz.newInstance(), "xxx");
		
		Method m = clz.getDeclaredMethod("add",Integer.class,Integer.class);//调用私有的方法
		m.setAccessible(true);//打开访问权限
		Object in = m.invoke(clz.newInstance(), 20,6);
		System.out.println(in);
		
	}

}

6.反射读写属性

Field field=clz.getField(“属性名”);

field.getName(); -->获取属性名
filed.getType(); -->获取属性类型
field.getModifiers(); -->获取属性访问修饰符
field.set(Object,Object); -->设置属性值,参数1:要设置属性所在对象;参数2:要设置的值;
field.get(Object); -->获取属性值,参数:要获取属性值的对象
field.getDeclaredField(“属性名”); -->获取单个属性(私有、公有、受保护、默认、静态)
field.getDeclaredFields(); -->获取所有属性(私有、公有、受保护、默认、静态)

package com.zking.refle;

import java.lang.reflect.Field;

/**
 * 反射读写属性
 * 
 * 
 * @author huguiyun
 *
 */

public class Demo5 {
	public static void main(String[] args) throws Exception {
		Student stu = new Student("s001", "zs");
		stu.age = 12;
		
		Class clz = Student.class;
		//获取属性值
//		Field[] fields = clz.getDeclaredFields();
//		for (Field field : fields) {
//			field.setAccessible(true);
//			System.out.println(field.getName()+":"+field.get(stu));
//		}
		
		//设置属性值  公有的
//		Field field = clz.getDeclaredField("age");
//		field.set(stu, 55);
//		System.out.println(stu.age);
		
		Field field = clz.getDeclaredField("sname");
		field.setAccessible(true);//打开访问权限
		field.set(stu, "ls");
		System.out.println(stu.getSname());
	}
}

7.反射修饰符

JAVA 反射机制中,Field的getModifiers()方法返回int类型值表示该字段的修饰符。

其中,该修饰符是java.lang.reflect.Modifier的静态属性。

getModifiers(),来获取它的访问修饰符
不同修饰符返回的值如下:

PUBLIC: 1
PRIVATE: 2
PROTECTED: 4
STATIC: 8
FINAL: 16
SYNCHRONIZED: 32
VOLATILE: 64
TRANSIENT: 128
NATIVE: 256
INTERFACE: 512
ABSTRACT: 1024
STRICT: 2048

反射总结

灵活使用反射能让我们代码更加灵活,这里比如JDBC原生代码注册驱动,hibernate 的实体类,Spring 的 AOP等等都有反射的实现。但是凡事都有两面性,反射也会消耗系统的性能,增加复杂性等,合理使用才是真!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值