Java_反射机制

1、获取反射的三种方式。

(1)通过类.class.

(2)通过对象.getClass();

(3)通过Class.forName();

最常用,最灵活的当属Class.forName();

2、反射是将类的各种成分映射成相应的类。

实例:

package com.lixinghua.fanshe;

public class X
{

}
package com.lixinghua.fanshe;

public class GetClassDemo01
{

	/**
	 * @param args
	 */
	public static void main(String[] args)
	{
		// TODO Auto-generated method stub
		X x = new X();
		System.out.println(x.getClass().getName());
	}

}
通过上面的代码可以获取X类的完整的包名,但是x.getClass()这个方法哪里来的呢?

任何一个类如果没有明确声明继承自哪个类,则默认继承Object类。Object类中定义了:public final Class getClass();

3、通过反射的三种方式实例化对象。

Class<?> c1 = null;
Class<?> c2 = null;
Class<?> c3 = null;

//方式一
c1 = Class.forName(com.lixinghua.fanshe);
//方式二
c2 = new X().getClass();
//方式三
c3 = X.class;

System.out.println(c1.getName());
System.out.println(c2.getName());
System.out.println(c3.getName());
这样最终都可以输出对象X所在的完整的包的名称。

4、反射机制的深入应用。

(1)通过反射调用类中的无参方法

package com.lixinghua.fanshe;

import java.lang.reflect.Method;


public class GetClassDemo01
{

	/**
	 * @param args
	 */
	public static void main(String[] args)
	{
		// TODO Auto-generated method stub
		Class<?> c1 = null;
		try
		{
			//实例化Class对象
			c1 = Class.forName("com.lixinghua.fanshe.Person");
			//Person中的sayHello方法没有参数,所以不需要传递参数
			Method method = c1.getMethod("sayHello");
			//调用此方法,必须传递对象实例
			method.invoke(c1.newInstance());
		} catch (Exception e)
		{
			// TODO: handle exception
		}
		
	}

}

class Person
{
	private String name;
	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;
	}
	private int age;
	public Person()
	{
		// TODO Auto-generated constructor stub
	}
	
	public void sayHello()
	{
		System.out.println("Hello World!");
	}
	public String say(String name,int age)
	{
		return name+"_"+age;
	}
}


(2)通过反射调用类中的有参方法。

public static void main(String[] args)
	{
		// TODO Auto-generated method stub
		Class<?> c1 = null;
		try
		{
			//实例化Class对象
			c1 = Class.forName("com.lixinghua.fanshe.Person");
			//Person中的say方法中有两个参数
			Method method = c1.getMethod("say",String.class,int.class);
			//调用此方法,必须传递对象实例和参数
			String result = (String)method.invoke(c1.newInstance(),"zlf",22);
			System.out.println(result);
		} catch (Exception e)
		{
			// TODO: handle exception
		}
		
	}
(3)通过反射调用setter以及getter方法。
public class GetClassDemo01
{
	public static void main(String[] args)
	{
		// TODO Auto-generated method stub
		Class<?> c1 = null;
		Object object = null;
		try
		{
			//实例化Class对象
			c1 = Class.forName("com.lixinghua.fanshe.Person");
			object = c1.newInstance();
		} catch (Exception e)
		{
			// TODO: handle exception
		}
		
		setter(object, "name", "zlf", String.class);
		setter(object, "age", 22, int.class);
		System.out.print("姓名:");
		getter(object, "name");
		System.out.print("年龄:");
		getter(object, "age");
	}
	
	public static void setter(Object obj, String att, Object value, Class<?> type)
	{
		try
		{
			Method method = obj.getClass().getMethod("set"+initStr(att), type);//设置方法参数类型
			method.invoke(obj, value);//调用方法
		} catch (Exception e)
		{
			// TODO: handle exception
		}
	}
	
	public static void getter(Object obj, String att)
	{
		try
		{
			Method method = obj.getClass().getMethod("get"+initStr(att));
			System.out.println(method.invoke(obj));
		} catch (Exception e)
		{
			// TODO: handle exception
		}
	}
	
	public static String initStr(String old)
	{
		String string = old.substring(0,1).toUpperCase()+old.substring(1);//单词首字母大写
		return string;
	}
}

5、将反射应用在工厂模式上。

(1)工厂模式在实际的开发中使用得非常多,通过反射机制改善工厂类,让其在增加子类时可以不用做任何的修改,就可以达到功能的扩充。

package com.lixinghua.fanshe;

interface Fruit
{
	public void eat();
}

class Apple implements Fruit
{
	public void eat()
	{
		System.out.println("**吃苹果");
	}
}

class Orange implements Fruit
{
	public void eat()
	{
		System.out.println("**吃橘子");
	}
}

class Factory
{
	public static Fruit getInstance(String className)
	{
		Fruit fruit = null;
		try
		{
			fruit = (Fruit) Class.forName(className).newInstance();
		} catch (Exception e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return fruit;
	}
}
(2)接下来该编写主类了。
package com.lixinghua.fanshe;

import java.util.Properties;

public class Main
{
	public static void main(String[] args)
	{
		//方法一
		//Fruit fruit = Factory.getInstance("com.lixinghua.fanshe.Apple");
		
		//方法二
		Properties properties = Init.getProperties();//初始化属性类
		Fruit fruit = Factory.getInstance(properties.getProperty("apple"));
		
		if(fruit!=null)
		{
			fruit.eat();
		}
	}
}
(3)主类中通过方法一的话,用户需要知道该类的完整包名,而用户是不可能知道一个借口中有多少个可以使用的子类。所以开发中,最好使用第二种方法,配置属性文件的方法。

属性文件类:

package com.lixinghua.fanshe;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.Properties;

public class Init
{
	public static Properties getProperties()
	{
		Properties properties = new Properties();
		File file = new File("fruit.properties");
		try
		{
			if(file.exists())//如果属性文件已经存在
			{
				properties.load(new FileInputStream(file));//读取内容
			}else {//否则新建一个属性文件
				properties.setProperty("apple", "com.lixinghua.fanshe.Apple");
				properties.setProperty("orange", "com.lixinghua.fanshe.Orange");
				properties.store(new FileOutputStream(file), "Fruit Class");
			}
		} catch (Exception e)
		{
			// TODO: handle exception
		}
		
		return properties;
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值