Tinking in java 琐碎知识点之反射


25、创建并使用自己的类加载器
    JVM中除了根加载器之外都是ClassLoader子类的实例,程序员可以通过扩展(extends)ClassLoader子类并重写它的方法来实现自定义的类加载器。
    通过Class对象获取对应类的详细信息    
public class ClassTest {
	private ClassTest(){
		
	}
	public ClassTest(String s){
		System.out.println("有参构造器");
	}
	public  void info(){
		System.out.println("无参方法");
	}
	public  void info(String s){
		System.out.println("有参方法,参数为:"+s);
	}
	static class Inner{
		static{
			System.out.println("Inner被加载");
		}
	}
	public static void main(String[] args) throws Exception {
		Class<ClassTest> clazz=ClassTest.class;
		Constructor[] costors=clazz.getConstructors();
		System.out.println("Class对象所对应类的全部public构造器");
		for(Constructor c:costors){
			System.out.println(c);
		}
		
		Constructor[] allcostors=clazz.getDeclaredConstructors();
		System.out.println("Class对象所对应类的全部构造器");
		for(Constructor c:allcostors){
			System.out.println(c);
		}
		
		Method mtds[]=clazz.getDeclaredMethods();
		System.out.println("Class对象所对应类的全部方法");
		for(Method c:mtds){
			System.out.println(c);
		}
		
		Class inClazz=Class.forName("ClassTest$Inner");
		System.out.print("inClazz对应的外部类:"+inClazz.getDeclaringClass());
	}
}

26、使用反射生成并操作对象
Class对象可以获得的该类里的成分包括方法(由Method对象表示)、构造器(由Constructor对象表示)、Field(由field对象表示),这三个类都定义在java.lang.reflect包下。程序可以通过Method对象来执行对应的方法,通过Constructor对象来调用对应的构造器创建对象,能通过Field对象来直接访问并修改对象的属性值。
每个类加载之后,系统会为该类生成一个Class对象,通过Class对象就可以访问到JVM中的这个类了,Java中通常有三种方式获得Class对象:
Class.forName():使用Class类的static方法forName("XXX")
Person.class:调用某个类的class属性来获取该类对应的Class对象。
调用某个对象的getClass()方法,该方法是java.lang.Object类中的一个方法,它返回该对象所属类对应的Class对象

例程:
import java.io.FileInputStream;
import java.util.*;
public class ObjectPoolFactory {
	//定义一个对象池,前面是对象名,后面是实际对象
	private Map<String,Object> objectPool=new HashMap<String,Object>();
	//定义一个创建对象的方法,该方法只要传入一个字符串类名,程序就可以根据类名来生成java对象
	private Object creatObjet(String clazzName) throws ClassNotFoundException, InstantiationException, 


IllegalAccessException{
		Class<?> clazz=Class.forName(clazzName);//使用反射来创建某个类或接口对应的java.lang.Class对象
		return clazz.newInstance();
	}
	
	//该方法根据指定文件来初始化对象池,它会根据配置文件来创建对象
	public void initPool(String fileName){
		FileInputStream fis=null;
		try {
			fis=new FileInputStream(fileName);
			Properties prop=new Properties();
			prop.load(fis);
			System.out.println("prop.stringPropertyNames():"+prop.stringPropertyNames());
			for(String name:prop.stringPropertyNames()){
				objectPool.put(name, creatObjet(prop.getProperty(name)));
			}
		} catch (Exception e) {
			System.out.println("读取"+fileName+"异常!");
		}
		finally{
			try {
				if(fis!=null){
					fis.close();
				}
			} catch (Exception e2) {
				e2.printStackTrace();
			}
		}
	}
	
	//从object中取出指定name对应的对象
	public Object getObject(String name){
		return objectPool.get(name);
	}
	public static void main(String[] args) {
		ObjectPoolFactory ofy=new ObjectPoolFactory();
		ofy.initPool("obj.txt");
		System.out.println(ofy.getObject("a"));
		System.out.println(ofy.getObject("c"));
	}
}
/*输出
prop.stringPropertyNames():[b, a, c]
Mon Apr 28 22:15:50 CST 2014
[]
*/
配置文件obj.txt
a=java.util.Date
b=javax.swing.JFrame
c=java.util.ArrayList




加强版的 ObjectPoolFactory例程(可以使用方法来改变属性值)
配置文件改为extObj.txt
a=javax.swing.JFrame
b=javax.swing.JLabel
#set the title of a
a%title=Test Title


import java.io.FileInputStream;
import java.lang.reflect.*;
import java.util.*;
public class ExtendObjectPoolFactory {
	//定义一个对象池,前面是对象名,后面是实际对象
	private Map<String,Object> objectPool=new HashMap<String,Object>();
	//定义一个创建对象的方法,该方法只要传入一个字符串类名,程序就可以根据类名来生成java对象
	private Object creatObjet(String clazzName) throws ClassNotFoundException, InstantiationException, 


IllegalAccessException{
		Class<?> clazz=Class.forName(clazzName);
		return clazz.newInstance();
	}
	
	private Properties config=new Properties();
	//该方法根据指定文件来初始化对象池,它会根据配置文件来创建对象
	public void initPool(String fileName){
		FileInputStream fis=null;
		try {
			fis=new FileInputStream(fileName);
			config.load(fis);
			//System.out.println("prop.stringPropertyNames():"+prop.stringPropertyNames());
			//对于每取出的属性名、属性值对,如果属性名中不包含%,就根据属性值创建一个对象,并将对象放入对象池中
			for(String name:config.stringPropertyNames()){
				if(!name.contains("%")){
				objectPool.put(name, creatObjet(config.getProperty(name)));
			}
			}
		} catch (Exception e) {
			System.out.println("读取"+fileName+"异常!");
		}
		finally{
			try {
				if(fis!=null){
					fis.close();
				}
			} catch (Exception e2) {
				e2.printStackTrace();
			}
		}
	}
	
	//每取出一对属性名-属性值对,如果属性名中包含百分号(%),即可认为该属性是用于为对象设置属性值
	//程序将调用对应的setter方法来为对应的属性设置属性值
	public void initPropertyByMethodReflect() throws SecurityException, NoSuchMethodException, IllegalArgumentException, 


IllegalAccessException, InvocationTargetException{
		for(String name:config.stringPropertyNames()){
			if(name.contains("%")){
				String[] keyAndValue=name.split("%");
				Object target=getObject(keyAndValue[0]);
				//String mtdName="set"+keyAndValue[1].substring(0,1).toUpperCase()+keyAndValue[1].substring(1);
				String mtdName="setTitle";//与上面的语句功能相同
				//通过对象的getClass方法获取他的实现类对应的Class对象
				Class<?> clazz=target.getClass();
				Method mtd=clazz.getMethod(mtdName,String.class);
				mtd.invoke(target, config.getProperty(name));
			}
		}
	}
	
	//从object中取出指定name对应的对象
	public Object getObject(String name){
		return objectPool.get(name);
	}
	
	public static void main(String[] args) throws Exception {
		ExtendObjectPoolFactory ofy=new ExtendObjectPoolFactory();
		ofy.initPool("extObj.txt");
		ofy.initPropertyByMethodReflect();
		System.out.println(ofy.getObject("a"));
	}
}

27、通过反射访问属性值
import java.lang.reflect.*;
import static java.lang.System.*;
public class FieldTest {
	public static void main(String[] args) throws Exception {
		Person p=new Person();
		Class<Person> personClass=Person.class;
		// 使用getDeclaredField方法获取各种控制符的field
		Field namefield=personClass.getDeclaredField("name");
		//设置通过反射来访问Field时取消访问权限检查
		namefield.setAccessible(true);
		namefield.set(p, "zpc周");
		Field agefield=personClass.getDeclaredField("age");
		agefield.setAccessible(true);
		agefield.set(p, 22);
		out.println(p);
	}


}
class Person{
	private String name;
	private int age;
	public String toString(){
		return "Person[name="+name+",age="+age+"]";
	}
}
//输出:Person[name=zpc周,age=0]

28、泛型与反射
import java.util.Date;
import javax.swing.JFrame;
public class ReflectAndGeneric {
	public static <T> T getInstance(Class<T> cls){
		try {
			return cls.newInstance();
		} catch (InstantiationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		}
	}
	public static void main(String[] args) {
		Date d=ReflectAndGeneric.getInstance(Date.class);
		JFrame jfm=ReflectAndGeneric.getInstance(JFrame.class);
	}
}

你可能感兴趣的:(Tinking in java 琐碎知识点之反射)