Java高级代码规范.pdf
一:不允许使用汉语拼音命名欠规范代码示例:public void zengJiaYongHu()拼音方法名称规范代码示例:public void addUser()解析:应当使用国际化语言,拼音使得代码难懂二:Package名必须全部小写,尽量使用单个单词欠规范代码示例:com.lxit.daoImpl 单词大写了,daoImpl多个单词规范代码示例:com.lxit.dao.impl解析:这是一个大家都认同的习惯写法,也是一个默认的规范三:局部变量及输入参数不要与类成员变量同名(get/set方法与构造函数除外)欠规范代码示例:public class UserDAOImpl private int count;pubic void page(int count)类字段和方法参数名相同规范代码示例:public class UserDAOImpl private int count;pubic void page(int pageCount)解析:类变量会引起逻辑错误,引起覆盖。四:尽量不要在变量后面加魔法数字,英文单个字母和没有实际意义的英文数字单词来区分变量欠规范代码示例:String One;命名一个英文数字的变量 User user1=new User();User user2=new User();规范代码示例:User userAdd=new User();User userUpdate=new User();解析:这样会降低代码的可读性,并且不容易日后开发人员的维护五:包,类,变量命名不要加下划线(常量除外)欠规范代码示例:com.tag_test.dao.jdbc_impl 有下划线的包名 int user_age;带下划线的变量名 public class Class_ 带下划线的类名规范代码示例:com.tag.test.dao.jdbc.impl int userAge;public class Classes 解析:一种习惯性的用法,默认的规范六:常量命名要大写,单词之间要用下划线分开.欠规范代码示例:public static final String teamAdd=teamAdd;小写且没有下划线规范代码示例:public static final String TEAM_ADD=teamAdd;解析:容易区分变量和常量七:方法名第一个字母小写(构造方法除外).欠规范代码示例:public void Function()大写的方法名规范代码示例:public void function()解析:习惯用法,默认的规范八:两个单词以上的变量名要驼峰命名欠规范代码示例:int userage;age 单词 a 小写欠规范代码示例:int userAge;解析:能够更清晰的看懂变量所带代表的意思九:每个变量要用看得懂的词语来描述,尽量不要省略.欠规范代码示例:private Studeng stu;把 student 简写成 stu规范代码示例:private Student student;解析:使代码看起来清晰使人易懂十:一个类的命名一般是名词(有些 ing的动词,形容词除外),变量名也是一样.函数的命名必须是动宾短语(构造词除外).欠规范代码示例:public class Manage 动词类命规范代码示例:public class UserManage 解析:能使别人一看到类名就知道这个类大概是做什么的。十一:数据库连接对象的生成不能跟Model层混搅,必须将其放在一个单独的类里,用单例模式来实现数据库的连接.欠规范代码示例:public class UserDAOImpl()privatestatic Connection connection;publicstaticsynchronized Connection getConnection()if(connection=null)try catch(SQLException e)catch(ClassNotFoundException e)e.printStackTrace()return connection;规范代码示例:public class DBConnectionTools privatestatic Connection connection;private DBConnectionTools()publicstaticsynchronized Connection getConnection()if(connection=null)try Class.forName(Constants.MYSQL_DRIVER);connection=DriverManager.getConnection(Constants.MYSQL_URL,Constants.MYSQL_USER_NAME,Constants.MYSQL_PASSWORD);catch(SQLException e)e.printStackTrace();catch(ClassNotFoundException e)e.printStackTrace();return connection;解析:数据库连接应当单独出去出来,以便其它类可以复用十二:id一般不用int类型,用long类型欠规范代码示例:int id;int 类型的关于人员的id规范代码示例:Long id;解析:随着id的增长,当增长的id超出 int的范围的时候就会出现异常十三:sql语句一定要用占位符,不能用拼写组成的语句欠规范代码示例:public void addUser(User user)String sql=insert into student(ID,name,sex,address)values(+user.getId()+,+user.getName()+,+user.getSex()+,+user.getAddress()+);/?则代表占位符 规范代码示例:public void addUser()sql=insert into student(ID,name,sex,address)values(?,?,?,?)/?则代表占位符/可用预处理来发送sql语句 解析:很容易出现错误,而且不清晰,不容易让人读懂。十四:PreparedStatement 最好不要声明为类字段.欠规范代码示例:public class UserDAOImpl()private PreparedStatement preparedStatement;规范代码示例:public class UserDAOImpl public void addUser()PreparedStatement preparedStatement=newPreparedStatement(sql);解析:虽然很多类都使用到了PrepareStatement对象,但各个方法里用到的PrepareStatement对象都是不同的,所以不能作为类字段,抽取出来做类字段的话会出现数据混乱的问题十五:做主键的列没有任何业务逻辑,没有任何实际意义,而且任何时候都不能修改。欠规范主键示例:主键用一个身份证号码,或者学号规范主键示例:主键用id,唯一性的,不可改变的。解析:虽然身份证号码和学号也是唯一性的,但是他们是有意义的列,而且在程序升级时是可以更改的,而 id主要就是用来做主键的十六:取记录的时候,拿数据库条件语句去比较,不要自己用Java代码去比较.欠规范代码示例:public void deleteById(Long id)String sql=select id,name,age from user;/.ResultSet result=ResultSet.executeQuery();where(result.next()if(result.getLong(id)=id)/.删除 规范代码示例:public void deleteById(Long id)String sql=delete from user where id=?;/删除操作 解析:一旦取出的数据量过大,而用java代码的 if判断的话,会影响运行速率,还可能导致内存不足等错误。十七:代码提交之前必须写注释,不管什么原因.欠规范代码示例:暂时无规范代码示例:暂时无解析:使别人能够很清晰的你知道做了哪些修改十八:提交之前先更新代码.欠规范代码示例:暂时无规范代码示例:暂时无解析:防止出现冲突十九:只要系统有红色错误,那么就不能提交,提交前要保证编译错误全部消除.欠规范代码示例:暂时无规范代码示例:暂时无解析:如果上传了错误的代码,会导致别人因为下载了错误代码而带来开发上的问题二十:每个人的代码每天尽量上传,代码在本地的时间不要超过2 天.欠规范代码示例:暂时无规范代码示例:暂时无解析:保持与资源库的同步二十一:提交java代码前应该检查是否有没用的语句如:(System.out.println();),jsp页面上面是否有alert调试信息.欠规范代码示例:暂时无规范代码示例:暂时无解析:因为如果保留了有可能会影响到程序正常运行的结果,如:for(int i=0;i10;i+)System.out.println(i);/如果测试 for语句里有没有执行for(int i=0;i10;i+)System.out.println(测试代码是否运行到这里);System.out.println(i);如果没有删除测试语句,则结果就会不一样了,二十二:两个不同的包不能出现相同的文件名欠规范示例:packge com.lxitedu.work.MyWork.java packge com.lxitedu.task.MyWork.java规范示例:packge com.lxitedu.work.MyWork.java packge com.lxitedu.task.Work.java解析:当一个在一个庞大的系统的时候,很可能引起混淆二十三:提交代码前如果有TODO 标签,要删除掉,如果要标记没有做完的任务或者以后要改进的任务,用 LXTODO.欠规范代码示例:暂时无规范代码示例:暂时无解析:暂时无二十四:注释掉的代码提交前要删除。欠规范代码示例:/*public void add()if(true)System.out.println(这段代码已经给注释掉了,程序中没有用到);*/提交前没有删除这段代码规范代码示例:删掉就行了解析:既然代码在程序中没有用到的话就要删除,以免其他队员看到误解和浪费他人时间来读其代码。二十五:代码提交的注释里面不要加自己的名字.欠规范代码示例:暂时无规范代码示例:暂时无解析:因为提交的时候,系统已经帮你提交了用户名。二十六:PreparedStatement、ResultSet、Statement.对象用完之后必须进行调用close()将会关闭,立即释放此 Statement 对象的数据库和 JDBC 资源,不然会占用系统很多资源./此规范可以用适配器模式解决,不必手动去关闭了二十七:尽量不要在构造方法里初始化.欠规范代码示例:public class Person public Person()Person person=new Person();add();规范代码示例:public class Person public Person()Unknown macro:/尽量少做些不必要的事情 解析:因为在构造器里初始化没办法控制,构造器多了也容易出现混乱。如果有反射机制,也许会跳过构造方法。二十八:函数的返回值类型(如果有的话)要和其功能相匹配,要符合常规思维.欠规范代码示例:得到一个用户的姓名publicString getPeopleName()returnuserName;规范代码示例:得到一个用户的姓名的方法publicString getUserName()returnuserName;解析:是得到一个用户的姓名,而不是得到一个人的姓名,因为人不一定是用户,所以用getUserName更准确一点二十九:内部类的变量不要设为全局变量,尽量少用全局变量.欠规范代码示例:暂时无规范代码示例:暂时无解析:暂时无三十:如果是布尔型的变量则最好在命名用is或 has开头。例如:isVisible,isExists等.欠规范代码示例:boolean isTrue=resultSet.next();规范代码示例:boolean hasNext=resultSet.next();解析:难懂,且没有任何意义。三十一:如果变量命名要加注释,说明命名不是很准确.欠规范代码示例:暂时无规范代码示例:暂时无解析:暂时无三十二:任何类字段除非必要,否则都要私有化.欠规范代码示例:public class Person String name;String sex;int age;规范代码示例:public class ClassName privateString name;privateString sex;privateint age;解析:没有为程序的安全考虑。可以被其他的类访问三十三:尽量减少一个类属性的作用域,在离使用它的最近的地方定义.欠规范代码示例:int index=1;/类似这种情况变量生命离使用地方有点远String sql=insert into student(ID,name,password,sex,address)values(?,?,?,?,?);PreparedStatement preparedStatement=connection.prepareStatement(sql);preparedStatement.setString(index+,user.getID();preparedStatement.setString(index+,user.getName();preparedStatement.setString(index+,user.getPassword();preparedStatement.setString(index+,user.getSex();preparedStatement.setString(index+,user.getAddress();preparedStatement.executeUpdate();preparedStatement.close();规范代码示例:String sql=insert into student(ID,name,password,sex,address)values(?,?,?,?,?);PreparedStatement preparedStatement=connection.prepareStatement(sql);int index=1;preparedStatement.setString(index+,user.getID();preparedStatement.setString(index+,user.getName();preparedStatement.setString(index+,user.getPassword();preparedStatement.setString(index+,user.getSex();preparedStatement.setString(index+,user.getAddress();preparedStatement.executeUpdate();preparedStatement.close();解析:当别人维护易引起混淆,容易引发错误三十四:单例模式的使用必须要考虑到同步.欠规范代码示例:/没有使用到同步publicstatic Connection getConnection()throwsClassNotFoundException,SQLException if(conn=null)Class.forName(com.p6spy.engine.spy.P6SpyDriver);conn=DriverManager.getConnection(jdbc:mysql:/localhost:3306/test,root,root);return conn;规范代码示例:/最熟悉的得到一个Connection连接publicstaticsynchronized Connection getConnection()throwsClassNotFoundException,SQLException if(conn=null)Class.forName(com.p6spy.engine.spy.P6SpyDriver);conn=DriverManager.getConnection(jdbc:mysql:/localhost:3306/test,root,root);return conn;解析:当有多个用户并发使用的时候会造成数据的混乱,导致线程不安全三十五:方法里面参数最好不要超过三个.欠规范代码示例:publicvoid update(intid,Stringname,Stringcode,Stringsex).规范代码示例:public void update(int id,String name,String sex).or/如果超过三个必须把数据封装成一个pojo 如下把上面 update方法中参数封装起来public class User()privateint id;privateString name;publicString getName()return name;public void setName(String name)this.name=name;publicString getCode()return code;public void setCode(String code)this.code=code;public void setId(int id)this.id=id;publicint getId()return id;public void update(User user).解析:参数多容易出现错误。尤其是调用的时候,如果参数的顺序传错了,将是一个非常大的麻烦,而且没有拓展性三十六:值类或值对象必须重写toString方法.欠规范代码示例:public class Code privateint id;privateString name;privateString sex;publicString getName()return name;public void setName(String name)this.name=name;publicString getSex()return viscera;public void setSex(String sex)this.viscera=viscera;public void setId(int id)this.id=id;publicint getId()return id;规范代码示例:public class Person privateint id;privateString name;privateString sex;publicString getName()return name;public void setName(String name)this.name=name;publicString getSex()return sex;public void setSex(String sex)this.sex=sex;public void setId(int id)this.id=id;publicint getId()return id;publicString toString()returnnewStringBuffer().append(id+,).append(name+,).append(sex).toString();解析:toString的作用是一字符串的形式来返回它的实例信息,因为不同的类的信息是不同的,所以要重写,不能全部都继承Object的 toString方法。三十七:重写equals方法的时候,必须重写hashCode方法.欠规范代码示例:public class People /必要的属性/必要的 get和 set方法/toString 方法没有 hashCode方法没有 equals方法 规范代码示例:public class People/必要的属性/必要的 get和 set方法/toString 方法publicint hashCode()finalint prime=31;int result=1;result=prime*result+id;result=prime*result+(name=null)?0:name.hashCode();result=prime*result+(viscera=null)?0:viscera.hashCode();return result;publicboolean equals(Object obj)if (this=obj)returntrue;if (obj=null)returnfalse;if (getClass()!=obj.getClass()returnfalse;Code other=(Code)obj;if (id!=other.id)returnfalse;if (name=null)if(other.name!=null)returnfalse;elseif(!name.equals(other.name)returnfalse;if (viscera=null)if(other.viscera!=null)returnfalse;elseif (!viscera.equals(other.viscera)returnfalse;returntrue;解析:重写equals和 hashcode方法是为了像Set一样不能存储重复的元素,实现serializable是为了使这个类可以序列化三十八:单元测试的时候必须是对象比较,如果一个字段有100 个字,有时候数据库会自动删除一些,此时我们就不知道程序那出bug 了欠规范代码示例:暂时无规范代码示例:暂时无解析:实用的开发经验三十九:单元测试类名后面要加Test.欠规范代码示例:/这是一个 UserDAO的单元测试类 public class UserDAO规范代码示例:public class UserDAOTest 解析:这样写让别人知道这个类是用做测试的,清晰易懂四十:操作提示颜色,成功用蓝色字体,错误用红色字体.欠规范代码示例:暂时无规范代码示例:暂时无解析:暂时无四十一:控制层不能调用model层除了最顶级的接口外任何内容。要通过 new 顶级接口才能调用欠规范代码示例:public class UserServiceImpl private UserDAOImpl userDAOImpl;public UserServiceImpl()userDAOImpl=new UserDAOImpl();public void deleteById(Long id)userDAOImpl.deleteById(id);规范代码示例:public class UserServiceImpl private UserDAOuserDAO;public UserServiceImpl()userDAO=DAOFactory.getUserDAO();public void deleteById(Long id)userDAO.deleteById(id);解析:这样做不仅是为了程序的灵活着想,更是为了使代码的层次结构清晰明了四十二:返回类型尽量是父类接口或是抽象类,例如:要取得一个arrayList对象,则返回类型要用List。欠规范代码示例:/返回一个只能是保存User对象元素的list public ArrayList query()ArrayList arrayList=new ArrayList();.returnarrayList;规范代码示例:;public List query()List list=new ArrayList();.returnlist;解析:扩大对象的接受范围,更有拓展性四十三:SQL 程序里命名要注意,不能把关键词作为属性.欠规范代码示例:create tableName id bigint primary key,describe varchar(20)规范代码示例:creat tableName id bigint not null primary key,classDescribe varchar(20)解析:SQL 语句里字段名为关键字时,执行时就可能会出现问题,出错了很难找,所以在开始的时候就要注意.四十四:使用try.catch时,一定要捕获且打印异常欠规范代码示例:try /代码块 catch(Exception e)规范代码示例:try /代码块 catch(Exception e)e.printStackTrace();解析:如果程序出现了异常,而 catch块又没有任何错误输出,那么你的程序将永远不会报错,就无法发现错误,但是你的程序总是有问题的,但又很难发现错误在哪里四十五:当能够用工厂实例化对象的时候不要用构造器生成对象,要用工厂方法去代替。欠规范代码示例:UsreDAO userDAO=new UserDAOImpl();规范代码示例:UserDAO userDAO=DAOFactory.getUserDAO();解析:为了程序扩展性考虑,当构造器里的改变的时候,比如说增加一个参数,可能会因为系统过于庞大而忘记了修改而用工厂模式可以一劳永逸四十六:属性不能成为一个类也不能成为一个函数名.欠规范代码示例:public class Name public void sex()-规范代码示例:public class Person public void addPerson()-解析:对象的属性只能作为属性,不能单独做一个类四十七:如果一个方法的返回值是用来做判断的,返回值最好不要用字符串,要用int,欠规范代码示例:/比如说修改后要提示修改该成功publicString updateUser(User user).if(true)/成功return 修改成功 ;else /失败return 修改失败;规范代码示例:publicint updateUser(User user).if()/成功return 1;else /失败return 0;解析:因为字符串容易引发潜在的错误,比如失误的操作使得字符串多了个空格等等。四十八:在eclipse中,一次启动的工程最好不要超过两个以上。不可取的操作:在 tomcat中一次加载多个(两个以上)工程正确的操作:加载的工程最多不要超过两个,不用的工程关闭解析:启动多了占用资源,出错了检查也不方便,也容易起冲突五十:工程保存路径不能有空格,中文和特殊字符。不可取路径:安装 my toolseclipse正确的路径:E:studytoolsinstalledmytoolseclipse解析:如果出现此类状况,会影响一些工具的应用,影响程序的运行。五十一:在类中,重复了两次以上且公用的变量一般都要抽出成为类字段。欠规范代码示例:public class ClassDAOImpl public void addClass()Connection conn=Tools.getConnection();public void deleteById(int ID)Connection conn=Tools.getConnection();规范代码示例:public class ClassDAOImpl private Connection conn;public void addClass()conn=Tools.getConnection();public void deleteById(int ID)conn=Tools.getConnection();.解析:增加代码的可读性,五十二:程序代码中不要出现魔法数字。欠规范代码示例:if(mark=6)System.out.printl(6 是魔法数字。);规范代码示例:int addOperation=6;/生命一个变量表示数字6 所代表的含义if(mark=addOperation)System.out.println(this is right);解析:凭空出现的数字没人知道它是什么。很难使人读懂五十三:数据库语句中,不要用*来代替也不能出现用变量拼写的语句欠规范代码示例:/一个 sql查询语句 String sql=select*from student where id=+user.getId();规范代码示例:String sql=select id,name,sex,age from student where id=?;解析:1.用属性名而不用*让语句看起来更加清析易懂。2.在增加或删除属性的时候出错的机率更少,也容易找出问题来。3.一般情况不要去拼凑sql语句,应当用占位符,预处理来发送sql语句;五十四:方法命名的时候一定要力求精准,比如:查询的时候要命名为queryAll或者 queryByID.欠规范代码示例:/查询所有用户如果有多个查询方法的话public void query()-/未免太过模糊规范代码示例:/根据 ID 来查找用户;public void queryById()/代码块 /查询所有用户public void queryAll()解析:如果只有一个query太模糊了很难知道是查什么用的.五十五:ActionForm类要有 toString方法欠规范代码示例:一个 UserActionpublic class UserForm extends ActionForm/属性privateLong id;privateString name;privateint age;/get和 set方法 pulbic void setId(Long userId)id=userId;publicLong getId()return id;public void setName(String userName)name=userName;publicString getName()return name;public void setAge(int userAge)age=userAge public ing getAge()return age;/缺少了 toString方法 规范代码示例;public class UserForm extends ActionForm/属性privateLong id;privateString name;privateint age;/get和 set方法 pulbic void setId(Long userId)id=userId;publicLong getId()return id;public void setName(String userName)name=userName;publicString getName()return name;public void setAge(int userAge)age=userAge public ing getAge()return age;/缺少了 toString方法public void toString()returnnewStringBuffer().append(id+,).append(name+,).append(age).toString();解析:ActionForm和 pojo类有些相似,但它们的区别是ActionForm主要是为 struts1 jsp提供 FormBean,它的对象不需要比较,所以只要提供toString 方法就可以了五十六:有返回类型的方法,不能返回一个null 欠规范代码示例:/返回类型为null的publicstatic StudentDAO getStudentDAO(String type)if(DAOFactory.DAO_TYPE_JDBC.equals(type)returnnew StudentDAOJdbcImpl();returnnull;规范代码示例:/返回一个自定义的异常publicstatic StudentDAO getStudentDAO(String type)if(DAOFactory.DAO_TYPE_JDBC.equals(type)returnnew StudentDAOJdbcImpl();returnnew LxitException();解析:一个方法有返回类型,就不能返回null或 0.如果要返回null时或 0,则要写一个自定义的异常.返加这个自定义异常.五十七:类里面不能写空方法.如果有必要,则在方法里面要加一个注释欠规范代码示例:/写了一个空的方法public void init()规范代码示例:/在方法里面加上注释public void init()/TODO 该方法还没有写完,待完成.解析:如果一个方法里面什么都没有写,那么要删除.如果是实现过来的必须要重写该方法而不做会事的,应该要加注释.五十八:多条 if、else语句判断时,考虑用 if去替代欠规范代码示例:/if、else if 语句public ActionErrors validate(ActionMapping mapping,HttpServletRequest request)ActionErrors errors=new ActionErrors();if(id=null|id.length()1)errors.add(id,newActionMessage(error.id.required);elseif (name=null|name.length()1)errors.add(password,newActionMessage(error.name.required);elseif (descs=null|descs.length()1)errors.add(descs,newActionMessage(error.descs.required);elseif (teacherId=null|teacherId.length()1)errors.add(teacherId,newActionMessage(error.teacherId.required);return errors;规范代码示例:/用 if代替 else ifpublic ActionErrors validate(ActionMapping mapping,HttpServletRequest request)ActionErrors errors=new ActionErrors();if(id=null|id.length()1)errors.add(id,newActionMessage(error.id.required);if(name=null|name.length()1)errors.add(password,newActionMessage(error.name.required);if(descs=null|descs.length()1)errors.add(descs,newActionMessage(error.descs.required);if(teacherId=null|teacherId.length()1)errors.add(teacherId,newActionMessage(error.t