java--反射

WHAT:

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

WHY:

为什么会有反射

因为在java程序运行时,有一些类是不需要从头用到尾的,而反射机制可以在需要的时候在加载类,就比如数据库配置时使用的相关类

HOW:

反射怎么用,用反射能干什么

提高代码健壮性,灵活性

  1. 怎么用:

使用反射机制,首先我们引入一个叫做’类类’的东西,也就是Class类,类类有三种获取方式

这里借助一个学生类Student.java

package com.csf.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.通过类得到

Class stuClz=Student.class;

2.通过对象得到

Student s=new Student();
Class<Student> stuClz = (Class<Student>) s.getClass();

3.通过完整类名得到

Class<Student> stuClz = Class.forName("com.csf.reflect.Student");

所以,反射的第一步,得到类类

得到类类之后,可通过反射实例化得到对象,得对象,便可用这个对象的属性,方法。

以下都借助Student类进行,都用stuClz作为类类名称

1.反射实例化:

1.stuClz.newInstance()          无参构造

Student stu = (Student) stuClz.newInstance();
		stu.hello();
		stu.hello("张三");

 可以看到,这个方法调用了Student的无参构造,并且对应方法的调用都没问题。

注:所以,如果要使用这种方法进行反射实例化,则在给类写有参构造是,须保留无参构造。

2.stuClz.getConstrutor(参数)      有参构造,这里的参数填实体类中构造函数的数据类型。

这里调用的是反射的有参构造器,还需要一步才能得到对象

Constructor<Student> c = stuClz.getConstructor(String.class);
		Student stu = c.newInstance("s001");
		stu.hello();

 

3.stuClz.getDeclaredConstructor()      和上面这个方法差不多,不过利用这个方法有调用私有方法的权限。

先用上面的方法去调用Student的私有方法

Constructor<Student> c = stuClz.getConstructor(String.class);
		c.newInstance(18);

 这里报了方法未找到的错,所以,这种方法是无法获取私有方法的

所以,用.getDeclaredConstructor()再试一下,

Constructor c = stuClz.getDeclaredConstructor(Integer.class);
		c.newInstance(133);

 可以看到,还是报错,不过这一次的错已经不一样了。这里是因为检测到了这个私有的构造,不过没有权限,所以需要打开权限。

Constructor c = stuClz.getDeclaredConstructor(Integer.class);
		c.setAccessible(true);
		c.newInstance(133);

  

 OK了。上面的.getConstrutor(参数) 方法是用不了。setAccessible()方法的。

反射动态方法

反射调用方法有两种方式,

1..getMethod("方法名","参数");//不可调用私有的

2..getDeclaredMethod("方法名","参数");//可以调用私有的

所以就只演示第二种了

  • 首先得到类对象
  • 创建一个类实例(后面会用到)
  • 再调用.getDeclareMethod()
  • 再用方法对象调用执行方法,就可运行也就是.idnvoke(参数)。参数放该方法的对象
Class stuClz=Class.forName("com.csf.reflect.Student");
	    Student stu = (Student) stuClz.newInstance();
		//invoke:
		//参数一:类实例,在这里就是Student的类实例
		//参数二:调用的方法传递的参数,这里是Student中,hello方法的参数
	    //返回值,就是被反射调用的方法的返回值
        //stuClz.getDeclaredMethod(name, parameterTypes)  name是方法名 parameterTypes参数类型,因为这里调用的方法没有参数,所以不写
	    Method m1 = stuClz.getDeclaredMethod("hello");
		m1.invoke(stu);//因为没有返回值,所以不用接收

 

        Method m1 = stuClz.getDeclaredMethod("hello");
		m1.invoke(stu);
		
		Method m2 = stuClz.getDeclaredMethod("hello", String.class);
	    m2.invoke(stu, "张三");
		
	    Method m3 = stuClz.getDeclaredMethod("add", Integer.class,Integer.class);
	    m3.setAccessible(true);
	    System.out.println(m3.invoke(stu, 123,456));

 

 注:在调用私有方法是,同样要打开权限

 反射读写属性

读写属性的思维和上面差不多

就不详细讲解

Class stuClz=Class.forName("com.csf.reflect.Student");
		Student s= (Student) stuClz.newInstance();
		Field f = stuClz.getDeclaredField("sname");
		f.setAccessible(true);
		f.set(s, "张三");
		System.out.println(s.getSname());
		System.out.println(f.get(s));

输出效果是

不过,用反射可以将对象属性,一把提出来

方法是

Field[] f=stuClz.getDeclaredFields();
		
		for (Field ff : f) {
			ff.setAccessible(true);
			System.out.println(ff.getName()+":1"+ff.get(s));
		}

over.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

无感_K

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

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

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

打赏作者

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

抵扣说明:

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

余额充值