反射

反射

1.那什么是反射:

反射java语言中的一种机制,通过这种机制可以动态的实例化对象、读写属性、调用方法,并且能改变它的属性。而这也是Java被视为动态(或准动态,为啥要说是准动态,因为一般而言的动态语言定义是程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言,从这个观点看,Perl,Python,Ruby是动态语言,C++,Java,C#不是动态语言。)语言的一个关键性质。

2.反射能做什么?

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

3.反射的具体实现

下面是一个实体类student

package com.bowen.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有三种方法:

//1、通过对象调用 getClass() 方法来获取,通常应用在:比如你传过来一个 Object
  //  类型的对象,而我不知道你具体是什么类,用这种方法
         Student stu=new Student();
           Class forName=stu.getClass();
 //2、直接通过 类名.class 的方式得到,该方法最为安全可靠,程序性能更高
 //  这说明任何一个类都有一个隐含的静态成员变量 class
    Student stu=Student .class;
     //3、通过 Class 对象的 forName() 静态方法来获取,用的最多,
 //   但可能抛出 ClassNotFoundException 异常
Class forName=Class.forName("com.bowen.reflect.Student");


查阅 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():通过类的不带参数的构造方法创建这个类的一个对象。

实例化对象 newInstance()----- Constructor

( Constructor.getConstructor/Constructor.getDeclaredConstructor
注:一定要提供无参构造器

package com.bowen.reflect;

import java.lang.reflect.Constructor;

/**
 * 利用反射进行对象的实例化
 * 之前:通过关键字进行实例化
 * 现在:
 *     通过Java.lang
 * 
 * @author 125x
 *
 */
public class Demo2 {
public static void main(String[] args) throws Exception, Exception {
	/*Student stu=new Student();
	Class stuClz=stu.getClass();*/
	//newInstance这个方法默认使用无惨构造器去实例化对象
//	Student stu2=(Student) stuClz.newInstance();
//	System.out.println(stu2);
	
	
	//调用有参构造去实例化对象(一个参数)
//	Class stuClz=Student.class;
//	Constructor<Student> constructor= stuClz.getConstructor(String.class);
//	Student stu2=(Student)constructor.newInstance("zs");
	
	
	//调用有参构造去实例化对象(两个参数)
//	Class stuClz=Student.class;
//	Constructor<Student> constructor= stuClz.getConstructor(String.class,String.class);
//	Student stu2=(Student)constructor.newInstance("s001","zs");

	//调用有参构造去实例化对象(两个参数)
	Class stuClz=Student.class;
	Constructor<Student> constructor= stuClz.getConstructor(String.class,String.class);
	Student stu2=(Student)constructor.newInstance("s001","zs");

运行如下:
在这里插入图片描述

下面你是用这个方法的话会报错(java.lang.NoSuchMethodException:没有找到匹配的方法)

   //调用私有构造去实例化对象(两个参数)
   //java.lang.NoSuchMethodException
     Class stuClz=Student.class;
   Constructor<Student> constructor= stuClz.getConstructor(Integer.class);
   Student stu2=(Student)constructor.newInstance(18);//会报错

如下:
在这里插入图片描述

如果把.getConstructor改成getDeclaredConstructor;(又报以下错误)
在这里插入图片描述
不能访问private修饰的( java.lang.IllegalAccessException: Class com.bowen.reflect.Demo2 can not access a member of class com.bowen.reflect.Student with modifiers “private”)
要是不想报错:
加一个(constructor.setAccessible(true);)

  Class stuClz=Student.class;
	Constructor<Student> constructor= stuClz.getDeclaredConstructor(Integer.class);
	constructor.setAccessible(true);
	Student stu2=(Student)constructor.newInstance(18);

** 动态调用方法**(实列)

调用一个无参的

package com.bowen.reflect;

import java.lang.reflect.Method;

/**
 * 动态方法调用
 * @author 125x
 *
 */
public class Demo3 {
public static void main(String[] args) throws Exception, Exception {
	Student stu=new Student();
	Class<? extends Student> stuClz=stu.getClass();
	//调用一个无参的
	 Method m= stuClz.getDeclaredMethod("hello");
	 m.invoke(stu);
	 
}
}

运行如下:
在这里插入图片描述
调用一个有参的

package com.bowen.reflect;

import java.lang.reflect.Method;

/**
 * 动态方法调用
 * @author 125x
 *
 */
public class Demo3 {
public static void main(String[] args) throws Exception, Exception {
	Student stu=new Student();
	Class<? extends Student> stuClz=stu.getClass();

	//调用一个有参的
	Method m=stuClz.getDeclaredMethod("hello", String.class);
	 m.invoke(stu,"zs");
}
}

运行结果:
在这里插入图片描述
调用add方法

package com.bowen.reflect;

import java.lang.reflect.Method;

/**
 * 动态方法调用
 * @author 125x
 *
 */
public class Demo3 {
public static void main(String[] args) throws Exception, Exception {
	Student stu=new Student();
	Class<? extends Student> stuClz=stu.getClass();

	//调用add方法
	Method m=stuClz.getDeclaredMethod("add", Integer.class,Integer.class);
//	Method.invoke的返回值是被动态调用的方法的返回值
	   m.setAccessible(true);
   Object invoke=m.invoke(stu,25,2);
   System.out.println(invoke);
}
}

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

读写属性

package com.bowen.reflect;

import java.lang.reflect.Field;

/**
 * 反射读属性
 * 自定义标签库。通用分页。自定义MVC要用
 * 
 *  访问修饰符
 * getModifiers()
 * java:private 1
 * protected public 2
 * static 4
 * final 8
 * abstract...
 * 判断属性或方法被那些修饰符所修饰
 * @author 125x
 *
 */
public class Demo4 {
public static void main(String[] args) throws Exception{
	Student stu=new Student("s001","zs");
	stu.age=22;
	System.out.println(stu.getSid());
	System.out.println(stu.getSname());
	Class<? extends Student> stuClz=stu.getClass();
	
     /*Field f=	stuClz.getDeclaredField("sname");
    f.setAccessible(true);
      System.out.println(f.get(stu));*/
	
	//获取当前Student实例中的stu所有属性以及属性值
	Field[] f=stuClz.getDeclaredFields();
	for (Field field : f) {
		field.setAccessible(true);
		System.out.println(field.getName()+":"+field.get(stu));
	}
	
}
}

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

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值