1. 方法的
连续调用而没有判断,很容易
抛出NullPointerException等
异常
String infant = session.getAttribute("giant").toString();
session.getAttribute("giant")很可能是null值,再调用toString()会产生空指针异常。
解决方法:
String infant = null;
Object plantation = session.getAttribute("giant");
if (plantation != null) {
infant = plantation.toString();
}
对于强制转换的情况:
String infant = ((Elephant)session.getAttribute("giant")).eat();
这里除了会出现NullPointerException值外,还有可能出现ClassCastException。
解决方法:
String infant = null;
Object plantation = session.getAttribute("giant");
if (plantation != null && plantation instanceof Elephant) {
infant = ((Elephant)plantation).eat();
}
2. 通过
try...catch块来控制程序流程是不可取的,对异常的跟踪通常会遍历整个栈。
3.
for循环的判断表达式应该简单,而不是复杂或耗时的运算,如果遍历次数很多,会对性能造成影响:
List<Bean> beans = new ArrayList<Bean>();
for (int i = 0; i < obj.getPressure().length; i++) {
Bean bean = new Bean();
bean.setAccuracy(obj.getAccuracy()[i]);
bean.setPressure(obj.getPressure()[i]);
beans.add(bean);
}
可以优化成:
for (int i = 0, len = obj.getPressure().length; i < len; i++) {
Bean bean = new Bean();
bean.setAccuracy(obj.getAccuracy()[i]);
bean.setPressure(obj.getPressure()[i]);
beans.add(bean);
}
目前很多Java虚拟机都会优化该功能。我们可以使用Sun的server或hotspot模式以及其它jvm实现。
4. String的startsWith(String prefix),
prefix是大小写敏感的。
5. 数据库表的主键字段通常是int或者bigint类型,但也有可能是其它类型。假设主键类型声明为varchar,值是由数字组成的,根据int或者bigint来查询是会出问题的:
表Employee
emp_id (varchar) emp_name (varchar)
13103422 Pinnacle
09084323 Commensurate
String empId = "13103422";
Integer id = NumberUtils.toInt(empId); // id = 13103422
Employee emp1 = EmployeeService.getEmployeeById(id); // 可以拿到数据
String empId2 = "09084323";
Integer id2 = NumberUtils.toInt(empId2); // id = 9084323
Employee emp2 = EmployeeService.getEmployeeById(id2); // 拿不到数据
6. StringBuilder或StringBuffer拼接的字符串,获取所有的用toString()方法;获取部分的直接用
substring()方法,这样只创建
一个String实例:
StringBuffer sb = new StringBuffer();
for (int i = 0; i < 4; i++) {
sb.append("candy").append(i).append("|");
}
String retVal = sb.substring(0, sb.length() - 1);
下面获取部分的方式会创建两个String实例:
String str = sb.toString();
String retVal = str.substring(0, str.length() - 1);
7. jar打包和解压
将当前目录下的指定文件夹(包括子文件夹和文件)和文件打包成指定jar文件
jar cvf reconciliate.jar org lib about.html plugin.xml plugin.properties
同上,区别是使用指定的清单文件,而不是创建清单文件
jar cvfm reconciliate.jar META-INF/MANIFEST.MF *
解压指定jar包到当前目录
jar xvf reconciliate.jar
显示指定jar包的文件列表
jar tf .jar
选项:
-c 创建新的jar包
-u 更新已存在的jar包
-t 显示jar包中的文件列表
-x 解压jar包
-v 显示压缩或解压的详细信息
-f 指定jar文件名称
-m 指定清单文件并包含到jar包中
-e 指定jar包的执行入口点
-0 只存储,不压缩
-M 不生成清单文件
-i 生成索引信息
-C 切换到指定的目录,将目录下的指定文件包含到jar包中
8.
JDK1.5及以下不支持注解
编译环境为JDK1.5及以下时,在代码上加注解会报错:
public interface Config {
void set(String key, String value);
}
public class ConfigImpl implements Config {
@Override
public void set(String key, String value) {
}
}
9. 服务发布后,运行时
NoSuchFieldError或
NoSuchMethodError错误
jar版本冲突,另一个版本的类先被JVM加载,导致获取其属性或调用其方法时报错。
预防:编码注意包和类名的设置,清晰,简洁,尽量不重复。
解决:移除不同版本的jar,MAVEN工程通过pom.xml文件的[
Exclude Maven Artifact...]菜单;将正确版本的jar包放在classpath其它版本的前面(风险大)。
10. 三层架构:
表现层(MVC),
中间层,
数据访问层(DAO)
表现层
常用的框架是:SpringMVC,Struts1,2
中间层
粘合表现层和数据访问层,把各种对象放到容器中进行管理,以及业务处理。
中间层可以细分为业务层和服务层,业务层主要是通过调用各种服务来实现复杂的逻辑;服务层提供基本的服务调用,封装了数据操作,可以实现事务。
常用的框架是:Spring, EJB
数据访问层
和数据库打交道,获取以及持久化数据,通常一个方法只操作一次数据,不存在事务性问题。
常用的框架是:Hibernate, iBatis
11. 没有修饰符的构造函数,即为protected的:
public class Mankind {
Mankind() {} // 和 protected Mankind() {} 效果相同
}
12. 原始类型和包装类型
原始类型如:byte, boolean, char, short, int, long, float, double
对应的包装类型:Byte, Boolean, Character, Short, Integer, Long, Float, Double
原始类型有自己的默认值,如int的默认值为0
包装类型的默认值都是null。
JDK5.0起支持编译器自动装箱(从原始到包装)和拆箱(从包装到原始)。
包装类型为null时,和原始类型比较会报错:
Integer val = null;
if (val != 0) { // val为null, null是特殊的引用类型,无法拆箱和int比较,报空指针异常
}
// 可以写成
if (val != null && val != 0) {
}
// 或者
if (Integer.valueOf(0).equals(val)) { // equals参数可以传null
}