没有比人更高的山

一个隐藏了将近2年的Bug1

最近在维护华中科技大学电信系的电子档案库,发现了一个隐藏了将近2年的Bug,记录如下:

需求:一个科研项目有一定的工作量,而每个项目有很多参与人,需要为每个参与人设置其工作量分配额度。当用户添加了一个项目时,需要同时添加其参与人:

实现:当用户录入了科研项目信息之后,点击“添加参与人”的按钮,转向到选择参与人的页面,可以勾选任意数目的参与人,点击“保存”按钮后返回科研项目信息页面。

在执行保存选择的参与人信息时,检查所选择的人员是否已经在科研项目的参与人中存在的代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
for (Iterator<string> iterator = selectedMemberList.iterator(); iterator.hasNext();) {
    ParticipatorBean participatorBean = new ParticipatorBean();
    long teacherId = Long.parseLong(iterator.next());
    Teacherbasicinfo teacher = ServiceProvider.getTeacherInfoService().findById(teacherId);
    Long id = teacher.getTeacherId();
    participatorBean.setTeacherId(id);
    participatorBean.setTeacherName(teacher.getTeacherName());
    if (participatorsMap.get(id) == null) {
        participatorsMap.put(String.valueOf(id), String.valueOf(id));
        participators.add(participatorBean);
    }
}
</string>

其中,selectedMemberList是选中的用户列表,ParticipatorBean是用来传递给前一个页面的参与人的Java类,Teacherbasicinfo是领域模型,代表教师基本信息,老师编号teacherId为Long型。

participatorsMap是我从来去除重复的一个HashMap,也就是说我每遍历一个Teacherbasicinfo,就将其teacherId转换成字符串型添加到这个Map中,在每次添加之前我先检查这个Map是否已经存在了(且不论这种方法的好与坏,这是我们几年前的代码了)

这段代码无编译异常、无运行异常,但是却有逻辑异常。有用户反映。多次选择的时候会有重复的项出现。

经过多番调试,最后发现第八行代码有误,应该将

1
if (participatorsMap.get(id) == null) {

改成为:

1
if (participatorsMap.get(String.valueOf(id)) == null) {

恍然大悟,虽然我使用的是范型,但是Map的get方法仍然接受的是Object类型的参数,不对其参数进行检查,其put方法的签名为V put(K key, V value),则会对key和value的类型都进行检查。

这是我的错呢,还是Java的错,为啥不把get方法的参数用范型类型检查一下呢?可能是sun的工程师有别的考虑吧。

VN:F [1.7.5_995]
Rating: 10.0/10 (1 vote cast)
VN:F [1.7.5_995]
Rating: -1 (from 1 vote)

Java int型转换中文大写数字表示方法0

之前写过一篇博客,记录的是如何将Java中文大写数字转int型,今天遇到的问题是将Java int型转换成中文大写数字表示。

下面是程序,很容易理解,不过,只支持10000以内的数字转换:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
public static String intToChnNumConverter(int num){
    String resultNumber = null;
    if(num > 10000 || num < 0){
        return "";
    }
    HashMap chnNumbers = new HashMap();
    chnNumbers.put(0, "零");
    chnNumbers.put(1, "一");
    chnNumbers.put(2, "二");
    chnNumbers.put(3, "三");
    chnNumbers.put(4, "四");
    chnNumbers.put(5, "五");
    chnNumbers.put(6, "六");
    chnNumbers.put(7, "七");
    chnNumbers.put(8, "八");
    chnNumbers.put(9, "九");
 
    HashMap unitMap = new HashMap();
    unitMap.put(1, "");
    unitMap.put(10, "十");
    unitMap.put(100, "百");
    unitMap.put(1000, "千");
    int[] unitArray = {1000, 100, 10, 1};
 
    StringBuilder result = new StringBuilder();
    int i = 0;
    while(num > 0){
        int n1 = num / unitArray[i];
        if(n1 > 0){
            result.append(chnNumbers.get(n1)).append(unitMap.get(unitArray[i]));
        }
        if(n1 == 0){
            if(result.lastIndexOf("零") != result.length()-1){
                result.append("零");
            }
        }
        num = num % unitArray[i++];
        if(num == 0){
            break;
        }
    }
    resultNumber = result.toString();
    if(resultNumber.startsWith("零")){
        resultNumber = resultNumber.substring(1);
    }
    if(resultNumber.startsWith("一十")){
        resultNumber = resultNumber.substring(1);
    }
    return resultNumber;
}
VN:F [1.7.5_995]
Rating: 1.0/10 (1 vote cast)
VN:F [1.7.5_995]
Rating: +1 (from 1 vote)

Java中文大写数字转int型0

暂时不支持万以上级别,后面会加上这个。道理很简单,但我搜了一下google,找到的代码没有几个能直接用,所以分享下,直接贴代码了:

    public static int chnNumToIntConverter(String chnNum){
        HashMap<String, Integer> numbers = new HashMap<String, Integer>();
        numbers.put(”零”, 0);
        numbers.put(”一”, 1);
        numbers.put(”二”, 2);
        numbers.put(”三”, 3);
        numbers.put(”四”, 4);
        numbers.put(”五”, 5);
        numbers.put(”六”, 6);
        numbers.put(”七”, 7);
        numbers.put(”八”, 8);
        numbers.put(”九”, 9);
        HashMap<String, Integer> units = new HashMap<String, Integer>();
        units.put(”十”, 10);
        units.put(”百”, 100);
        units.put(”千”, 1000);
       
        int result = 0;
       
        //补全“十三”这种类型前的“一”
        if(chnNum.startsWith(”十”)){
            chnNum = “一” + chnNum;
        }
       
        int length = chnNum.length();
        for(int i=0; i<length; i++){
            String num = chnNum.substring(i, i+1);
            if(! num.equals(”零”)){
                if(i+2 > length){
                    result += numbers.get(num);
                }else{
                    String unit = chnNum.substring(i+1, i+2);
                    result += numbers.get(num) * units.get(unit);
                }
                i++;
            }
        }
       
        return result;
    }

VN:F [1.7.5_995]
Rating: 1.0/10 (1 vote cast)
VN:F [1.7.5_995]
Rating: 0 (from 0 votes)

Working copy path '*' does not exist in repository的解决方法0

开发中对一个working copy进行update操作的时候出现了标题所示的错误,因为在update之前对其进行了switch操作,因此猜想可能是因为这个缘故,上网查了一下,找到一篇文章《SVN merger errors: Working copy path ‘*’ does not exist in repo》,按照其描述的方法并不能解决我的问题,但是让我对.svn文件夹下的这个entry文件产生了兴趣,仔细的看了一下,发现这个文件里面有一行是写的版本号,紧接着下一行就是文件夹路径,但是这个文件夹路径是错误的。

    对其进行了改正后,重新update,正常了,看来是svn的一个bug吧。

VN:F [1.7.5_995]
Rating: 0.0/10 (0 votes cast)
VN:F [1.7.5_995]
Rating: 0 (from 0 votes)

一个ant的build.xml文件实例0

很简单,很实用,写完之后,发现,嘿嘿!我居然可以不翻doc写build文件了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
<?xml version="1.0" encoding="utf-8" ?>
<project name="dian_bid" basedir="." default="deploy">
 
 <property name="source" location="src" />
 <property name="resource" location="res" />
 <property name="test-srouce" location="test" />
 <property name="release-resource" location="release" />
 <property name="dest" location="dest" />
 
 <property name="webroot" location="web"/>
 <property name="tomcat-root" location="D:/Java/apache-tomcat-a"/>
 
 <target name="clean">
  <echo message="清理生成过程中的临时文件" />
  <delete dir="${tomcat-root}/webapps/bid" />
  <delete dir="${webroot}/WEB-INF/classes" />
  <delete dir="${dest}" />
 </target>
 
 <target name="prepare" depends="clean">
  <mkdir dir="${webroot}/WEB-INF/classes"/>
  <mkdir dir="${dest}" />
 </target>
 
 <target name="build" depends="prepare">
  <echo message="编译Java源代码" />
  <javac destdir="${webroot}/WEB-INF/classes" srcdir="${source}">
   <sourcepath path="${test-srouce}" />
   <classpath>
    <fileset dir="${tomcat-root}/lib">
     <include name="**/*.jar"/>
    </fileset>
    <fileset dir="${webroot}/WEB-INF/lib">
     <include name="**/*.jar"/>
    </fileset>
   </classpath>
  </javac>
 </target>
 
 <target name="package" depends="build">
  <echo message="将Web工程打包成war可部署文件格式" />
  <copydir dest="${webroot}/WEB-INF/classes" src="${resource}" />
  <copydir dest="${webroot}/WEB-INF/classes" src="${release-resource}" />
  <war destfile="${dest}/bid.war"  basedir="${webroot}" webxml="${webroot}/WEB-INF/web.xml"/>
 </target>
 
 <target name="deploy" depends="package">
  <echo message="开始部署BID系统到服务器上" />
  <copy file="${dest}/bid.war" todir="${tomcat-root}/webapps" />
  <echo message="停止tomcat服务器" />
  <exec executable="${tomcat-root}/bin/shutdown.bat" />
  <echo message="启动tomcat服务器" />
  <exec executable="${tomcat-root}/bin/startup.bat" />
  <echo message="部署BID系统完成" />
 </target>
</project>
VN:F [1.7.5_995]
Rating: 8.5/10 (2 votes cast)
VN:F [1.7.5_995]
Rating: 0 (from 2 votes)