1.通过反射调用类中的方法
示例:
Person类:
package com.ares.demo;interface Info { public static final String AUTHOR = "ARES"; public String getInfo(); public String say(String name, String content); public void sayHello();}public class Person implements Info { private String name; private int age; public Person() { } public Person(String name) { this.setName(name); } public Person(String name, int age) { this(name); this.setAge(age); } public String getInfo() { return "Hello World!!!"; } public String say(String name, String content) { return name + "说了:" + content; } public void sayHello() { System.out.println("hello --> " + AUTHOR); } public String toString() { return "姓名:" + this.name + ";年龄:" + this.age; }}
InvokeMethodDemo类:
package com.ares.demo;import java.lang.reflect.Method;public class InvokeMethodDemo { public static void main(String[] args) throws Exception { Class c = Class.forName("com.ares.demo.Person"); // 本程序中将调用Person类中的sayHello()方法 Method met = c.getMethod("sayHello") ; met.invoke(c.newInstance()) ; }}
注: getMethod表示取得方法. invoke则表示执行方法.
类似的:
// ①本程序中将调用Person类中的getInfo()方法Method met = c.getMethod("getInfo") ;String val = (String)met.invoke(c.newInstance()) ;System.out.println(val) ;// ②本程序中将调用Person类中的say()方法Method met = c.getMethod("say", String.class, String.class);String val = (String) met.invoke(c.newInstance(), "ARES", "WELLCOME!");System.out.println(val);
拼接的方式反射调用getXXX和setXXX方法
示例:
package com.ares.demo;import java.lang.reflect.Method;public class InvokeMethodDemo{ public static void main(String[] args) throws Exception { Class c = Class.forName("org.lxh.demo.classdemo05.Person"); Object o = c.newInstance() ; set("name","ARES",o,String.class) ; set("age",24,o,int.class) ; get("name",o) ; get("age",o) ; } /** * * @param name 属性名称 * @param value 属性值 * @param obj 要操作的对象 */ public static void set(String name, Object value, Object obj, Class type) throws Exception { Method met = obj.getClass().getMethod("set" + initStr(name),type); met.invoke(obj, value); // 调用方法 } public static void get(String name, Object obj) throws Exception { Method met = obj.getClass().getMethod("get" + initStr(name)); Object value = met.invoke(obj); System.out.println(value); } public static String initStr(String name) { StringBuffer buf = new StringBuffer(); buf.append(name.substring(0, 1).toUpperCase()) .append(name.substring(1)); return buf.toString(); }}
2.通过反射直接操作属性
示例:
package com.ares.demo;import java.lang.reflect.Field;public class InvokeFieldDemo { public static void main(String[] args) throws Exception { Class c = Class.forName("com.ares.demo.Person"); Object obj = c.newInstance(); Field nameField = c.getDeclaredField("name"); nameField.setAccessible(true);// 让属性可见 nameField.set(obj, "ARES"); System.out.println(nameField.get(obj)) ; }}
直接操作属性实际使用中是很少的,因为其安全性不好.拼接的方式反射调用getXXX和setXXX方法是建议使用的.
3.综合应用
接合工厂模式
①示例:
package com.ares.demo;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 f = null ; if(className.equals("apple")){ f = new Apple() ; } if(className.equals("orange")){ f = new Orange() ; } return f ; }}public class FactoryDemo { public static void main(String[] args) { Fruit f = Factory.getInstance("apple") ; f.eat() ; }}
这中方式的工厂模式还是有问题的,因为新添加子类必须修改工厂类.不便于维护.
②优化示例:
package com.ares.demo;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 f = null ; try{ f = (Fruit)Class.forName(className).newInstance() ; }catch(Exception e){} return f ; }}public class FactoryDemo02 { public static void main(String[] args) { Fruit f = Factory.getInstance("com.ares.demo.Apple") ; f.eat() ; }}
这种工厂模式解决了子类扩充的问题,但是有一个问题就是每次反射获取类的实例时,包类名称太长,不便与操作.
③优化示例:
package com.ares.demo;import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.util.Properties;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 f = null; try { f = (Fruit) Class.forName(className).newInstance(); } catch (Exception e) { } return f; }}class PropertiesOperate {// 属性操作类 private Properties pro = null; private File file = new File("d:" + File.separator + "fruit.properties"); public PropertiesOperate() { this.pro = new Properties(); if (file.exists()) {// 文件存在 try { pro.loadFromXML(new FileInputStream(file)); // 读取 } catch (Exception e) { e.printStackTrace(); } }else{ this.save() ; } } private void save() { this.pro.setProperty("apple", "com.ares.demo.Apple"); this.pro.setProperty("orange", "com.ares.demo.Orange"); try { this.pro.storeToXML(new FileOutputStream(this.file), "Fruit"); } catch (Exception e) { e.printStackTrace(); } } public Properties getProperties() { return this.pro; }}public class FactoryDemo { public static void main(String[] args) { Properties pro = new PropertiesOperate().getProperties() ; Fruit f = Factory.getInstance(pro.getProperty("apple")); f.eat(); }}
这种思想到今天都还在使用,比如常用的SSH框架.
最新的程序设计理念,是将注释写到代码中,让注释起到程序控制的作用,那么要实现此操作则要使用Annotion完成.
20150524
JAVA学习笔记系列
--------------------------------------------
联系方式
--------------------------------------------
Weibo: ARESXIONG
E-Mail: aresxdy@gmail.com
------------------------------------------------