JAVA 反射机制

概念:

动态语言:是指程序在运行的过程中可以改变其结构(添加新的方法和属性)的语言。动态语言有JavaScript、Ruby、Python。C和C++不属于动态语言。从反射的角度来说Java属于半动态语言。

反射的思想是当我们的程序在运行时,需要动态地加载一些类 而这些类 可能之前用不到 所以没有被加载到 JVM ,所以在 运行时 需要动态的加载(比如数据库动态加载驱动类)。动态的加载的时 我们指定的类,并且获取该类中的所有内容。而且是一个将字节码文件中的内容封装成对象。那么好比将.class文件封装成.java文件(反编译的过程)。通过反射机制我们可以动态的获取、访问到java对象的属性,方法,构造函数等。

补充:

  • 我们知道所有的Java类都继承一个Object类。Object类是类层次结构的根类。每个类都使用Object作为超类。所有的对象、数组都会实现这个类的方法。Object中的getClass():会返回一个Class对象(类对象)。
  • Class对象实在加载类时由Java虚拟机以及通过调用类加载器中的defineClass方法自动构造的。
  • 静态编译:在编译时确定类型,绑定对象,即通过。
  • 动态编译:在运行时确定类型,绑定对象。动态编译最大限度发挥了Java的灵活性,体现了多态的应用,减低了 类之间的耦合性。

反射机制的有缺点:
优点:可以实现动态地创建对象和编译,体现了很大的灵活性,提高程序的扩展性。
缺点:对性能有影响,使用反射基本上是一种解析操作,我可以告诉JVM,我们希望做什么并且它可以满足我们的要求,但是这些操作总是慢于直接执行的相同操作。

Java中关于反射的操作定义在:java.lang.reflect 包下

JDK文档

基本步骤:

  1. 获得Class对象,就是获取到指定名称的字节码文件对象。
  2. 实例化对象,获得类的属性、方法、构造函数。
  3. 访问属性、调用方法、调用构造函数创建对象。

获取Class对象:

在反射机制中获取class对象有三种方法

  1. 通过对象的getClass()方法获取。(缺点:先要创建该类的对象)。
  2. 通过数据类型的静态属性class(缺点:必须先明确该类)。
  3. 使用class类中的静态forName()方法。(优点:指定什么类名,就获取什么类的字节码文件对象,扩展性强)
package dong.test;

/**
 * 获得类对象的三种方法
 * @author YIMA
 *
 */
public class Reflection {

	public static void main(String[] args) throws ClassNotFoundException {
		//方法1:通过对象reflection调用getClass()方法获得类对象
		Reflection reflection = new Reflection();
		Class class1 =  reflection.getClass();

		//方法2:通过静态属性class获得类对象
		Class class2 = Reflection.class;

		//方法3:调用类中的静态方法forName(),获取类对象。这里 的“dong.test.Reflection”意思是:dong.test包下的Reflection类。
		Class class3 = Class.forName("dong.test.Reflection");
	}

}



创建类的对象:

对象进行实例化时的初始化的方式有两种

  1. 调用无参的构造函数:调用newInstance()方法;(一般情况下,被反射的类,内部通常都会提供一个公有的空参数的构造函数)

  2. 调用带参的构造函数:先要获取指定参数列表的构造函数对象,然后通过该构造函数对象的newInstance(实际参数)进行对象的初始化;(注意:这里必须先明确具体的构造函数的参数类型,不便于扩展)

package dong.test;

import java.lang.reflect.Constructor;

/**
 * 实例化类的对象
 * @author YIMA
 *
 */
public class Reflection {
	private String r1;
	public Reflection(String r1){
		System.out.println("调用有参的构造函数");
		this.r1 = r1;
	}
	public Reflection(){
		System.out.println("调用无参的构造函数");
	}

	public static void main(String[] args) {
		
		Class class3;
		Object object;
		Object object2;
		try {
			//方法3:调用类中的静态方法forName(),获取类对象
			class3 = Class.forName("dong.test.Reflection");
			//类对象通过无参newInstance()方法获取实例化一个对象
			object = class3.newInstance();//调用了该类无参的构造函数
			
			Constructor constructor = class3.getConstructor(String.class);//获取特定的构造函数
			object2 = constructor.newInstance("test");//调用了该类有参的构造函数
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}

}

上面代码运行的结果:

调用无参的构造函数
调用有参的构造函数


获得类的构造函数

类型方法解释
ConstructorgetConstructor(Class[] patams)获得使用特殊参数的公共构造函数
Constructor[]getConstructors()获得类中所有的公共构造函数
ConstructorgetDeclaredConstructor(Class patams)获得所有的构造函数包括私有的
Constructor[]getDeclaredConstructor()获得该类所有的构造函数包括私有的
package dong.test;

import java.lang.reflect.Constructor;

/**
 * 获得构造函数
 * @author YIMA
 *
 */

public class Reflection{
	private String r1;
	
	public Reflection(String r1){
		System.out.println("调用有参的构造函数");
		this.r1 = r1;
	}
	
	public Reflection(){
		System.out.println("调用无参的构造函数");
	}
	
	private Reflection(int i){}

	public static void main(String[] args) {
		
		Class class3 = null;
		Constructor[] constructors = null;
		try {
			//方法3:调用类中的静态方法forName(),获取类对象
			class3 = Class.forName("dong.test.Reflection");
			
			
			//constructors = class3.getConstructors();//获取的是该类以及父类中的公有的构造函数
			constructors = class3.getDeclaredConstructors();//获取本类的构造函数,包括私有的
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		//遍历输出
		for(Constructor con:constructors){
			System.out.println(con);
		}
	}

}

运行结果:

private dong.test.Reflection(int)
public dong.test.Reflection()
public dong.test.Reflection(java.lang.String)

当上面的代码中执行的代码片段是:

constructors = class3.getConstructors();//获取的是该类以及父类中的公有的构造函数
			

此时的运行结果是:

public dong.test.Reflection()
public dong.test.Reflection(java.lang.String)


获取类的方法

package dong.test;

import java.lang.reflect.Method;

/**
 * 获得方法
 * @author YIMA
 *
 */

public class Reflection{
	private String r1;
	
	public String getR1() {
		return r1;
	}

	public void setR1(String r1) {
		this.r1 = r1;
	}
	
	public void show(){
		
	}
	
	public static void main(String[] args) {
		
		Class class3 = null;
		Method[] methods = null;
		try {
			//方法3:调用类中的静态方法forName(),获取类对象
			class3 = Class.forName("dong.test.Reflection");
			//获取本类中的所有方法
			methods = class3.getDeclaredMethods();
			
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		for(Method m:methods){
			System.out.println(m);
		}
	}



	

}

运行结果:控制输出了本类中的四个方法,其中也包括了main方法。

public static void dong.test.Reflection.main(java.lang.String[])
public java.lang.String dong.test.Reflection.getR1()
public void dong.test.Reflection.setR1(java.lang.String)
public void dong.test.Reflection.show()

获取类中指定的方法

补充:方法调用:invoke()

package dong.test;

import java.lang.reflect.Method;

/**
 * 获得方法
 * @author YIMA
 *
 */

public class Reflection{
	private String r1;
	
	public String getR1() {
		return r1;
	}

	public void setR1(String r1) {
		System.out.println(r1);
		this.r1 = r1;
	}
	
	public void show(){
		
	}
	
	public static void main(String[] args) {
		Class class3 = null;
		Method[] methods = null;
		try {
			//方法3:调用类中的静态方法forName(),获取类对象
			class3 = Class.forName("dong.test.Reflection");
			Object object = class3.newInstance();
			
			//获取指定名称的方法
			Method m = class3.getDeclaredMethod("setR1",String.class);
			m.invoke(object, "获取指定名称的方法");
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

运行结果:

获取指定名称的方法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值