Java反射的实现

      首先了解一下什么是java的反射机制,百度百科中的概述是:JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。那么就有另一个问题的产生了,为什么要用反射,为什么不直接实例化一个对象来调用里面的方法和属性,而是运用反射的机制来实现呢,这就涉及到了动态与静态的概念,静态编译是指在编译时确定类型,绑定对象,而动态编译则是运行时确定类型,绑定对象。动态编译最大限度发挥了java的灵活性,体现了多态的应用,有以降低类之间的耦合性。一句话,反射机制的优点就是可以实现动态创建对象和编译,体现出很好的灵活性。

      下面简单的利用工厂模式说明一下反射的方便之处,当然有利必有弊,反射虽然灵活但是会影响性能,记住这一点。

public class test {

	/**
	 * @param args
	 * @throws ClassNotFoundException 
	 */
	public static void main(String[] args) throws Exception {
		fruitFactory fct = new fruitFactory();
		fruit f = fct.getFruit("apple");
		f.color();
		fruitFactory1 fct1 = new fruitFactory1();
		fruit f1 = fct1.getFruit("orange");
		f1.color();
	}
}

class fruit{
	public void color(){
		System.out.println("this color ");
	}
}

class apple extends fruit{
	@Override
	public void color() {
		System.out.println("this is red");
	}
}

class orange extends fruit{
	@Override
	public void color() {
		System.out.println("this is yellow");
	}
}

class fruitFactory1{
	public fruit getFruit(String name) throws Exception{
		Class clazz = Class.forName("com.hlxsoft.invoke."+name);
		return (fruit)clazz.newInstance();
	}
}

class fruitFactory{
	public fruit getFruit(String name){
		if(name.equals("apple")){
			return new apple();
		}else{
			return new orange();
		}
	}
}



如上面的代码一样,假如我们生产一个水果,那么传统的方法时在工厂中判断他是什么样的水果,需要判断一下到底需要生产的水果是苹果还是橙子,然后在根据结果来实例化一个对象返回。而通过运用反射机制则无需判断你所想要生产的水果的类型,这就大大的降低了代码的冗余,而且可以在外部文件中定义你所需要生产的水果类型,降低了代码的耦合。也许这只是一个简单的代码,并不能很好的体现出反射的优点,但是在实际繁重的项目代码中却能够起到很好的作用,而且反射还会用在我们使用的一些框架中,比如说struts,他的配置文件中就用到了反射的机制,通过配置文件定义一个action,然后通过反射来实例化调用。

       下面就具体说一下java反射具体的实现是怎么实现的。

       首先来看一下通过反射来获得类的一些属性参数。

public class hello {
	public static void main(String[] args) {
		Hi hi = new Hi();
		System.out.println(hi.getClass().getName());
		System.out.println(hi.getClass().getSimpleName());
	}
}
class Hi{
	
}

#运行的结果为#:

com.hlxsoft.invoke.Hi
Hi

      通过反射实例化其他类的对象。

public class hello {
	public static void main(String[] args) throws Exception{
		Class clazz = Class.forName("com.hlxsoft.invoke.Hi");
		Hi hi = (Hi) clazz.newInstance();
		hi.showName();
	}
}
class Hi{
	public String name;
	public int age;
	public void showName(){
		System.out.println("my name is cc");
	}
}

#运行结果为#:my name is cc

通过调用Class的newInstance()方法来实例化Hi这个类。


      通过反射获得实现的接口名称。

public class hello {
	public static void main(String[] args) throws Exception{
		Class clazz = Class.forName("com.hlxsoft.invoke.Hi");
		Class<?> c[] = clazz.getInterfaces();
		System.out.println(c[0].getSimpleName());
	}
}
class Hi implements yo{
	public String name;
	public int age;
	public void showName(){
		System.out.println("my name is cc");
	}
}
interface yo{
	public static String name ="";
}

#运行结果为#:yo


      通过反射获得对象的私有成员变量。

import java.lang.reflect.Field;

public class hello {
	public static void main(String[] args) throws Exception{
		Class clazz = Class.forName("com.hlxsoft.invoke.Hi");
		Field f = clazz.getDeclaredField("name");
		f.setAccessible(true);
		System.out.println((String)f.get(clazz.newInstance()));
	}
}
class Hi{
	private String name="jin";
	public int age;
	public void showName(){
		System.out.println("my name is cc");
	}
}

这里关键的一个语句就是f.setAccessible();这条语句就是设置能否读取私有成员变量的语句,还有通过api文档可以知道获取field的方法有两种,一种是上面的getDeclaredField()还有一种是getField(),这两种方法有什么区别呢,第一种方法是只能获取实例化的成员变量,而第二种方法是获取静态的成员变量,要注意这两个的区别。


       通过反射来调用成员的方法。

import java.lang.reflect.Method;

public class hello {
	public static void main(String[] args) throws Exception{
		Class clazz = Class.forName("com.hlxsoft.invoke.Hi");
		Method method = clazz.getMethod("showName");
		method.invoke(clazz.newInstance());
		
		Method method1 = clazz.getMethod("show", String.class);
		method1.invoke(clazz.newInstance(), "jin");
		
		Method method2 = clazz.getMethod("getName");
		System.out.println((String)method2.invoke(clazz.newInstance()));
	}
}
class Hi{
	private String name="jin";
	public int age;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public void showName(){
		System.out.println("my name is cc");
	}
	
	public void show(String s){
		System.out.println("s="+s);
	}
}

#运行结果为#:

my name is cc
s=jin
jin

调用Class的getMethod("show", String.class)方法来获取类的方法,第一个参数为方法名,第二个参数为方法所需要传递的参数类型。

然后通过调用Method的invoke(clazz.newInstance(), "jin")方法来调用真正的对象的方法。第一个参数为实例化的对象,第二个参数为传入的具体的值。

如果没有传入的参数那么直接省略就可以。


这里就只给出了一些反射的基本的操作,并没有详细的说明里面的每个方法都是什么,可以通过api自己试试,就能够很好的明白,只要掌握这些基本的东西也就基本能够运用反射来做一些事情了。










评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值