黑马程序员技术交流社区

标题: 如何根据字符串值动态给JAVA成员变量赋值 [打印本页]

作者: 山水游客    时间: 2012-6-28 20:12
标题: 如何根据字符串值动态给JAVA成员变量赋值
public class UserInfo {
private int userID;
private String userName;
public int getUserID() {
return userID;
}
public void setUserID(int userID) {
this.userID = userID;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
}

现在有另一字符串如下:
String userInfo = "userID=12,userName='Zhaomin'";

其中字符串中的userID和userName与java类中的成员变量名一致.

问题: 如何把字符串中的userID和userName的值设置给java类中的相应成员变量?
作者: 赵倩倩    时间: 2012-6-28 20:15
本帖最后由 赵倩倩 于 2012-6-28 20:16 编辑

这个是没有什么特别好的方法的。
只能实现约定字符串的格式,然后利用indexof,等操作,计算出id和,username的位置,然后通过subString的方式,截取出其中的有效信息
作者: 赵倩倩    时间: 2012-6-28 20:42
还请 刘蕴学 给反射一下看看,学习下
作者: 黄克帅    时间: 2012-6-28 22:45
可以先用 逗号截取字符串  然后去写入到Properties文件中  然后用反射读取配置文件  根据获得的属性名 设置对应的值

代码

package property;

import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;
import java.util.Set;

public class MainClass {
        public static void main(String[] args) throws IOException,
                        IntrospectionException, IllegalArgumentException,
                        IllegalAccessException, InvocationTargetException {

                String userInfo = "userID=12,userName='Zhaomin'";
                 

                String[] s = userInfo.split(",");
                BufferedWriter bw = new BufferedWriter(new FileWriter(
                                "E:/heima/src/property/userInfo.properties"));

                for (String str : s) {
                        bw.write(str);
                        bw.newLine();
                        bw.flush();
                }

                bw.close();
                BufferedReader br = new BufferedReader(new FileReader(
                                "E:/heima/src/property/userInfo.properties"));
                Properties pro = new Properties();
                pro.load(br);
                Set<Object> set = pro.keySet();

                UserInfo ui = new UserInfo();

                for (Object o : set) {
                        String key = (String) o;
                        String value = pro.getProperty(key);
                        PropertyDescriptor pd = new PropertyDescriptor(key, ui.getClass());
                       
                       
                        if(pd.getPropertyType().equals(int.class)){
                                int value1 = Integer.parseInt(value);
                                Method m = pd.getWriteMethod();
                                m.invoke(ui,value1);
                        }
                       
                        if(pd.getPropertyType().equals(String.class)){
                               
                                Method m = pd.getWriteMethod();
                                m.invoke(ui,value);
                        }
                       
                       
                       
                }
               
                System.out.println(ui.getUserID());
                System.out.println(ui.getUserName());
        }
}


感觉有点麻烦  每次要要判断类型  还有可能你的字符串不规范    应该有更简单的方法
作者: 韩慧阳    时间: 2012-6-28 22:58
想不通,为什么要用反射,类已经给了干嘛还用反射呢??
两个set方法都有用反射干什么啊??
直接字符串中截取子串再调用set方法不行吗?
作者: 黄克帅    时间: 2012-6-28 23:46
本帖最后由 黄克帅 于 2012-6-28 23:50 编辑

截取字符串 不靠谱,  你要考虑下程序的扩展性啊。
不过如果字符串不规范的话,也只能截取字符串了。 比如属性之间你一会儿逗号隔开,一会儿用空格隔开,有时候=号两边还加点空格。比如说这个题 我打印出来的userName就是 'Zhaomin' ,  有单引号。
作者: 刘蕴学    时间: 2012-6-29 18:43
赵倩倩 发表于 2012-6-28 20:42
还请 刘蕴学 给反射一下看看,学习下

我先吃饭,注释回头写,代码先发了吧,其实也不难
  1. import java.io.ByteArrayInputStream;
  2. import java.lang.reflect.Field;
  3. import java.util.Properties;

  4. class UserInfo
  5. {
  6.        
  7.         private int userID;
  8.        
  9.         private String userName;
  10.        
  11.         public int getUserID()
  12.         {
  13.        
  14.                 return userID;
  15.         }
  16.        
  17.         public void setUserID(int userID)
  18.         {
  19.        
  20.                 this.userID = userID;
  21.         }
  22.        
  23.         public String getUserName()
  24.         {
  25.        
  26.                 return userName;
  27.         }
  28.        
  29.         public void setUserName(String userName)
  30.         {
  31.        
  32.                 this.userName = userName;
  33.         }
  34. }

  35. class Test21
  36. {
  37.        
  38.         public static void main(String args[]) throws Exception
  39.         {
  40.                 String userInfo = "userID=12,userName='Zhaomin'".replace(',', '\r');
  41.                 UserInfo infoObj = new UserInfo();
  42.                 ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(userInfo.getBytes());
  43.                 Properties properties = new Properties();
  44.                 properties.load(byteArrayInputStream);
  45.                
  46.                 Field[] fields = UserInfo.class.getDeclaredFields();
  47.                
  48.                 boolean old_accessable;
  49.                 for (Field field : fields)
  50.         {
  51.                 if(properties.containsKey(field.getName()))
  52.                 {
  53.                         old_accessable = field.isAccessible();
  54.                         field.setAccessible(true);
  55.                         if(field.getType() == properties.get(field.getName()).getClass())
  56.                                 field.set(infoObj, properties.get(field.getName()));
  57.                         else
  58.                                 field.set(infoObj, convert(field, (String)properties.get(field.getName())));
  59.                         field.setAccessible(old_accessable);
  60.                 }
  61.         }
  62.                
  63.                
  64.                
  65.                 System.out.println(infoObj.getUserID());
  66.                 System.out.println(infoObj.getUserName());
  67.         }
  68.        
  69.         public static Object convert(Field field, String str) throws NoSuchMethodException, SecurityException
  70.         {
  71.                 Object object = null;
  72.                 if(field.getType() == int.class)
  73.                         return Integer.valueOf(str);
  74.                 return object;
  75.         }
  76. }
复制代码

作者: 赵倩倩    时间: 2012-6-29 21:40
刘蕴学 发表于 2012-6-29 18:43
我先吃饭,注释回头写,代码先发了吧,其实也不难

本质不还是对字符串的操作,已经给出set,get方法,还反射,又是何种用意?是不是啊。。。呵呵
作者: 刘蕴学    时间: 2012-6-29 21:44
本帖最后由 刘蕴学 于 2012-6-29 21:46 编辑
赵倩倩 发表于 2012-6-29 21:40
本质不还是对字符串的操作,已经给出set,get方法,还反射,又是何种用意?是不是啊。。。呵呵 ...

原理上来讲,反射可以实现任何具备这种特性的对象的赋值操作,到底是赋值变量,还是调用方法都是一样的,这个确实不好理解,现在你知道是userinfo这个类的对象,如果你不知道具体是哪个类的对象,你只知道字符串里有变量的名字和值,你怎么整,我这就是简单的写下,完全扩展性的写法代码会多不少

如果这么做毫无意义的话?为什么框架都会用到反射?
作者: 赵倩倩    时间: 2012-6-29 22:06
刘蕴学 发表于 2012-6-29 21:44
原理上来讲,反射可以实现任何具备这种特性的对象的赋值操作,到底是赋值变量,还是调用方法都是一样的, ...

反射本身没有什么神秘的,也没什么不好理解。只是一种比较强大的工具,有他特定的应用场景。反射在框架中的应用,主要是为了可配置性。通过配置文件中的配置,去创建对象,改变属性等等。另一种应用场景则是可以操作和利用原开发者不想你直接用的东西,比如安卓上有很多隐藏的api,不通过反射无法使用。在本例中,显然是不适合的。并且提问者提问的关键点也不是怎样把值放入对象,而是如何从字符串中提取出有效信息。如果觉得对,请加分。
作者: 刘蕴学    时间: 2012-6-29 22:11
本帖最后由 刘蕴学 于 2012-6-29 22:14 编辑
赵倩倩 发表于 2012-6-29 22:06
反射本身没有什么神秘的,也没什么不好理解。只是一种比较强大的工具,有他特定的应用场景。反射在框架中 ...

霸气侧漏啊,那我也得见识见识你有什么高见了,洗耳恭听,另外没有什么是不反射做不了的,没出反射的时候程序员也是一样编程
作者: 赵倩倩    时间: 2012-6-29 22:15
刘蕴学 发表于 2012-6-29 22:11
霸气侧漏啊,那我也得见识见识你有什么高见了,洗耳恭听,另外没有什么是不反射做不了的 ...

我已经说完了。再不明白只好你亲自去看看书,看看资料,或者找人问问了。呵呵。

或者不如咱们来讨论讨论反射的实现原理,如何?不准现查,直接讨论。
作者: 赵倩倩    时间: 2012-6-29 22:16
刘蕴学 发表于 2012-6-29 22:11
霸气侧漏啊,那我也得见识见识你有什么高见了,洗耳恭听,另外没有什么是不反射做不了的 ...

我已经说完了。再不明白只好你亲自去看看书,看看资料,或者找人问问了。呵呵。

或者不如咱们来讨论讨论反射的实现原理,如何?不准现查,直接讨论。
作者: 刘蕴学    时间: 2012-6-29 22:22
本帖最后由 刘蕴学 于 2012-6-29 22:23 编辑
赵倩倩 发表于 2012-6-29 22:16
我已经说完了。再不明白只好你亲自去看看书,看看资料,或者找人问问了。呵呵。

或者不如咱们来讨论讨论 ...

你还非得较劲了。。。行,光说反射,没意思,咱来动态代理实现原理吧,光说没意思,贴代码

我前阵子写的,代码写的烂点,没重构过,凑合看吧
proxy.zip (15.18 KB, 下载次数: 486)
作者: 赵倩倩    时间: 2012-6-29 22:25
刘蕴学 发表于 2012-6-29 22:22
你还非得较劲了。。。行,光说反射,没意思,咱来动态代理实现原理吧,光说没意思,贴代码 ...

我只能跟你说动态代理也没什么神秘的,无非是利用反射对包装设计模式的一种简便实现。至于贴代码就算了。手机党,见谅。
作者: 刘蕴学    时间: 2012-6-29 22:28
赵倩倩 发表于 2012-6-29 22:25
我只能跟你说动态代理也没什么神秘的,无非是利用反射对包装设计模式的一种简便实现。至于贴代码就算了。 ...

没什么是神秘,技术就是技术,呵呵,我就说几个关键词吧, 切面,代理类字节码动态编译,处理程序接口
作者: 刘蕴学    时间: 2012-6-29 22:31
赵倩倩 发表于 2012-6-29 22:25
我只能跟你说动态代理也没什么神秘的,无非是利用反射对包装设计模式的一种简便实现。至于贴代码就算了。 ...

另外我想说,你的理论说的在好,也没有代码实在,呵呵
作者: 赵倩倩    时间: 2012-6-29 22:31
刘蕴学 发表于 2012-6-29 22:22
你还非得较劲了。。。行,光说反射,没意思,咱来动态代理实现原理吧,光说没意思,贴代码

我前阵子写的 ...

简单的来说,就是通过反射判断调用的是否是目标对象的目标方法,如果是目标方法的话,也调用自己的实现。也可以在此基础上实现aop。你说对不,如果对,请加分。另外你倒是说说反射的原理呀,内部具体是怎么实现的?算了,还是不讨论了,你自便吧,但也别炫耀大家都会的反射了。
作者: 刘蕴学    时间: 2012-6-29 22:34
赵倩倩 发表于 2012-6-29 22:31
简单的来说,就是通过反射判断调用的是否是目标对象的目标方法,如果是目标方法的话,也调用自己的实现。 ...

什么时候你把我楼上的代码看完了你在上来说话吧,或者你是查资料,还是自己写,找人写,都行,只要你写的比我好,我甘拜下风,光说不练您就免了吧
作者: 刘蕴学    时间: 2012-6-29 22:37
赵倩倩 发表于 2012-6-29 22:31
简单的来说,就是通过反射判断调用的是否是目标对象的目标方法,如果是目标方法的话,也调用自己的实现。 ...

你真能写个完整的代理框架出来,你想要多少分我给你多少分,我话放在这,这不是问题,你一个人写代码,教会无数人的事情,我为什么不干
作者: 赵倩倩    时间: 2012-6-29 22:49
刘蕴学 发表于 2012-6-29 22:34
什么时候你把我楼上的代码看完了你在上来说话吧,或者你是查资料,还是自己写,找人写,都行,只要你写的 ...

代码今天是上不了了,手机党,你懂的。明天倒是可以给你看看。但是,我又觉得你说的是个伪命题,动态代理的关键部分不过十行左右的代码,会了就是会了,不会就是不会。技术就是一层窗户纸,一捅就破了。又不是大规模开发,就这么点小伎俩谁还能比谁写的好多少?明天也好膜拜下。我还是什么都不说了,低调才是最牛逼的炫耀,呵呵。
作者: 刘蕴学    时间: 2012-6-29 22:50
本帖最后由 刘蕴学 于 2012-6-30 00:13 编辑
赵倩倩 发表于 2012-6-29 22:49
代码今天是上不了了,手机党,你懂的。明天倒是可以给你看看。但是,我又觉得你说的是个伪命题,动态代理 ...

10几行是吧?恭候大驾,另外针对楼主的问题,参见spring框架,反射javabean部分的aop实现
作者: 赵倩倩    时间: 2012-6-30 10:31
刘蕴学 发表于 2012-6-29 22:50
10几行是吧?恭候大驾,另外针对楼主的问题,参见spring框架,反射javabean部分的aop实现 ...

方法一不是动态代理,而是包装设计模式,不讨论。
方法二就是利用反射搞了一下,也不讨论。
方法三倒还精彩些,不过也没用到什么特别的东西,也不讨论了。
方法四不错,用了一些不常见的东西,看起来很牛逼的样子。呵呵。说明了刘童鞋还是个很爱钻研的好孩子。

另外,如果没能看懂刘童鞋代码的朋友,我介绍给大家看篇文章,看完了,也应该就明白了。
http://www.ibm.com/developerworks/cn/java/j-lo-proxy1/
http://www.ibm.com/developerworks/cn/java/j-lo-proxy2/index.html#major8
作者: 赵倩倩    时间: 2012-6-30 10:52
刘蕴学 发表于 2012-6-29 22:50
10几行是吧?恭候大驾,另外针对楼主的问题,参见spring框架,反射javabean部分的aop实现 ...

本人不才,刘童鞋拿着以前写的代码,我也只好也拿出很久前写的代码了,相信聪明的你一看就明白。虽然不如刘童鞋的精彩,但也是一种动态的最佳实践。
另外有两点,
刘童鞋放出的代码,似乎是某套题目中的节选,出现在本论坛难免让人不联想到是某套题,大家懂的。放出来还是不太好。

还有就是,刘童鞋显然是已经拿到了锤子,但是也不能满眼都是钉子,在决定一种方案的时候,还是要考虑考虑什么才是本问题的关键点,什么才是这种方案的最佳实践。

关于这么点事情,纠结过来,纠结过去,让大家见笑了,还请见谅。:)
  1. private DaoFactory() {}
  2.         private static DaoFactory factory = new DaoFactory();
  3.         public static DaoFactory getInstance() {
  4.                 return factory;
  5.         }
  6.         public EmployeeDao getEmployeeDao() {
  7.                 return (EmployeeDao) Proxy.newProxyInstance(DaoFactory.class.getClassLoader(), EmployeeDaoHibernateImpl.class.getInterfaces(), new InvocationHandler() {
  8.                         Session session = null;
  9.                         Transaction transaction = null;
  10.                         @Override
  11.                         public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {
  12.                                 EmployeeDao employeeDao = new EmployeeDaoHibernateImpl();
  13.                                 try {
  14.                                         session = ThreadLocalUtil.getSession();
  15.                                         transaction = session.beginTransaction();
  16.                                        
  17.                                         Object object = method.invoke(employeeDao, args);
  18.                                        
  19.                                         transaction.commit();
  20.                                        
  21.                                         return object;
  22.                                        
  23.                                 } catch(Exception e) {
  24.                                         if(transaction!=null)
  25.                                                 transaction.rollback();
  26.                                         throw new RuntimeException(e);
  27.                                 } finally {
  28.                                         if(session != null) {
  29.                                                 ThreadLocalUtil.closeSession();
  30.                                         }
  31.                                 }
  32.                         }
  33.                 });
  34.         }
复制代码

作者: 赵倩倩    时间: 2012-6-30 10:56
再跟大家推荐另一篇文章吧,关于动态代理的前生今世,帮助大家理解动态代理的存在意义。

动态代理的前世今生.pdf

316.16 KB, 下载次数: 171


作者: 刘蕴学    时间: 2012-6-30 11:39
赵倩倩 发表于 2012-6-30 10:56
再跟大家推荐另一篇文章吧,关于动态代理的前生今世,帮助大家理解动态代理的存在意义。 ...

是不是钉子我不知道,但是吧,你看见userinfo第一反应是什么?带get set 的封装,没别的东西,除了web方面的javabean想不到别的了。
作者: 刘蕴学    时间: 2012-6-30 12:16
赵倩倩 发表于 2012-6-30 10:52
本人不才,刘童鞋拿着以前写的代码,我也只好也拿出很久前写的代码了,相信聪明的你一看就明白。虽然不如 ...

咱们俩讨论的重点不在题,也不在技术本身,你走的路跟我走的路有很大区别,事实上我很少去接触框架,除非我自己可以真正的变相实现这些技术,我在很多年里并没有像大部分程序员一样去接触新技术,而是去实现我掌握的技术本身是怎么出来的,呵呵,这个代理的4份代码就是根据很早之前那会不会代理的时候逐渐重构出来的,不过当然理论方面我确实不行,你让我说我也说不明白,这是软肋,所以我一般不会去讲什么原理,都是拿代码来阐述我的观点,呵呵
作者: 刘蕴学    时间: 2012-6-30 12:41
赵倩倩 发表于 2012-6-30 10:52
本人不才,刘童鞋拿着以前写的代码,我也只好也拿出很久前写的代码了,相信聪明的你一看就明白。虽然不如 ...

你这个代码倒是让我想起来struts多线程环境session存储问题,不过主干代码不全,我也不好猜测你这个local的具体实现,呵呵




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2