1、String类
equals方法
hashCode
2、MD5或者sha1加盐生成安全密码
org.apache.commons.codec进行base64和hex编码、解码
/** * 生成安全的密码,生成随机的16位salt并经过1024次 sha-1 hash */ public static String entryptPassword(String plainPassword) { byte[] salt = Digests.generateSalt(SALT_SIZE); byte[] hashPassword = Digests.sha1(plainPassword.getBytes(), salt, HASH_INTERATIONS); return Encodes.encodeHex(salt)+Encodes.encodeHex(hashPassword); } /** * 验证密码 * @param plainPassword 明文密码 * @param password 密文密码 * @return 验证成功返回true */ public static boolean validatePassword(String plainPassword, String password) { byte[] salt = Encodes.decodeHex(password.substring(0,16)); byte[] hashPassword = Digests.sha1(plainPassword.getBytes(), salt, HASH_INTERATIONS); return password.equals(Encodes.encodeHex(salt)+Encodes.encodeHex(hashPassword)); }
Java中byte用二进制表示占用8位,而我们知道16进制的每个字符需要用4位二进制位来表示,(所以我们就可以把每个byte转换成两个相应的16进制字符,即把byte的高4位和低4位分别转换成相应的16进制字符H和L,并组合起来得到byte转换到16进制字符串的结果new String(H) + new String(L)。即byte用十六进制表示只占2位。
3、float和double浮点数误差大,比较等值出问题,商业计算使用BigDecimal,用于高精度计算
1)除法操作需要设置小数位数
使用BigDecimal进行除法运算,如果结果出现无限小数,会抛出异常,如
Java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result. at java.math.BigDecimal.divide(Unknown Source)
此时需要对除法计算设置小数位数,方法为divide(BigDecimal divisor, int scale, int roundingMode)。
2)不要使用equals判断是否相等
BigDecimal的equals() 方法会考虑数字的换算值,即使看起来相同的数字 equals() 比较未必相等。如对于1.00和1.0000两个数字,BigDecimal的equals() 方法比较结果是不相等的,而 compareTo() 方法会认为这两个数是相等的。因此比较两个BigDecimal数值是否相等,应使用compareTo() 方法而不是equals()方法。
3)jdk中已经明确不建议使用new BigDecimal(double value)这种形式的构造函数,尽量使用参数类型为String的构造函数
参数类型为double的构造方法的结果有一定的不可预知性
当double必须用作BigDecimal的源时,请注意,此构造方法提供了一个准确转换;它不提供与以下操作相同的结果:先使用Double.toString(double)
方法,然后使用BigDecimal(String)
构造方法
4)BigDecimal都是不可变的(immutable)的
BigDecimal a =new BigDecimal("1.22");
System.out.println("construct with a String value: " + a);
BigDecimal b =new BigDecimal("2.22");
a.add(b);
System.out.println("aplus b is : " + a);
我们很容易会认为会输出:
construct with a Stringvalue: 1.22
a plus b is :3.44
以上只是对加法源码的分析,减乘除其实最终都返回的是一个新的BigDecimal对象,因为BigInteger与BigDecimal都是不可变的(immutable)的,在进行每一步运算时,都会产生一个新的对象,所以a.add(b);虽然做了加法操作,但是a并没有保存加操作后的值,正确的用法应该是a=a.add(b);
4、取某个日历之前的某个月。例如要取2002年1月12号之前1个月的时间,应该是2001年12月12日。
Calendar calendar = Calendar.getInstance();
calendar.set(2002, 0, 12);//代表2002年1月12日
calendar.add(Calendar.MONTH, -1);//这样就将日期设置成了2001年12月12日。
System.out.println(calendar.getTime().toString());
但是这种情况如果用roll()来实现。如以下代码:
Calendar calendar = Calendar.getInstance();
calendar.set(2002, 0, 12);//代表2002年1月12日
calendar.roll(Calendar.MONTH, -1);//这样就将日期设置成了2002年12月12日。
System.out.println(calendar.getTime().toString());
结论:roll()函数处理,只会比相应的字段进行处理,不会智能的对其它字段也进行逻辑上的改变。但是add()函数会在逻辑上改变其它字段,使结果正确。
注:Calendar中的Month是从0-11的,0代表1月,11代表12月。
5、
classpath 和 classpath* 区别: classpath:只会到你的class路径中查找找文件; classpath*:不仅包含class路径,还包括jar文件中(class路径)进行查找.
6、web.xml执行的顺序
context-param >> listener >> filter >> servlet
1) 启动一个WEB项目的时候,容器(如:Tomcat)会去读它的配置文件web.xml.读两个节点: <listener></listener> 和 <context-param></context-param>
2)紧接着,容器创建一个ServletContext(上下文),这个WEB项目所有部分都将共享这个上下文.
3)容器将<context-param></context-param>转化为键值对,并交给ServletContext
4)容器创建<listener></listener>中的类实例,即创建监听
5)在监听中会有contextInitialized(ServletContextEvent args)初始化方法,在这个方法中获得
ServletContext = ServletContextEvent.getServletContext();
context-param的值 = ServletContext.getInitParameter("context-param的键");