如何写出好的Java代码
①
优雅需要付出代价.从短期利益来看,对某个问题提出优雅的解决方法,似乎可能花你更多的时间.但当它终于能够正确执行并可轻易套用于新案例中,不需要花上数以时计,甚至以天计或以月计的辛苦代价时,你会看得到先前所花功夫的回报(即使没有人可以衡量这一点).这不仅给你一个可更容易开发和调试的程序,也更易于理解和维护.这正是它在金钱上的价值所在.这一点有赖某种人生经验才能够了解,因为当你努力让某一段程序代码变得比较优雅时,你并不是处于一种具生产力的状态下.但是,请抗拒那些催促你赶工的人们,因为那么做只会减缓你的速度罢了.
记住"各个击破"的原理.如果你所探讨的问题过于混杂,试着想像该问题的基本动作会是什么,并假设这一小块东西能够神奇地处理掉最难的部分.这"一小块"东西其实就是对象–请撰写运用该对象的程序代码,然后检视对象,并将其中困难的部分再包装成其他对象,依此类推.
使用者扮演着"客户"角色,不需要(也不知道)class的底层运作方式.Class开发者必须是class设计专家,并撰写class,使它能够尽可能被大多数新手程序员所用,而且在程序中能够稳当执行.一套程序库只有在具备通透性的情况下,使用起来才会容易.
interfaces保持最少,以及让这些classes和其他classes之间的关联性( 尤其是base
classes)保持最少.如果你的设计所得结果更甚于此,请问问自己,是否其中每一样东西在整个程序生命期中都饶富价值?如果并非如此,那么,维护它们会使你付出代价.开发团队的成员都有不维护"无益于生产力提升"的任何东西的倾向;这是许多设计方法无法解释的现象.
让所有东西尽量自动化.先撰写测试用的程序代码(在你撰写class之前),并让它和class结合在一起.请使用makefile或类似工具,自动进行测试动作.通过这种方式,只要执行测试程序,所有的程序变动就可以自动获得验证,而且可以立即发现错误.由于你知道的测试架构所具备的安全性,所以当你发现新的需求时,你会更勇于进行全面修改.请记住,程序语言最大的改进,是来自型别检查、异常处理等机制所赋予的内置测试动作.但这些功能只能协助你到达某种程度.开发一个稳固系统时,你得自己验证自己的classes或程序的性质.
的可能长相.撰写测试码通常能够显现出额外的特性(features)或限制 (
constraints)__它们并不一定总是能够在分析和设计过程中出现.测试码也可做为展示class 用法的示例程序.
indirection)"加以简化.这个软件工程上的基础法则是抽象化概念的根据,而抽象化概念正是面向对象程序设计的主要性质.10.
①.1.
让class尽可能微小而无法切割(atomic).赋予每个class单一而清楚的用途.如果你的classes或你的系统成长得过于复杂,请将复杂的classes切割成比较简单的几个classes.最明显的一个判断指针就是class的大小:如果它很大,那么它工作量过多的机会就可能很高,那就应该被切割.重新设计class的建议线索是:
许多函数各自处理类型极为不同的动作:请考虑切割为多个不同的(classes).
lists).冗长的引数列会使函数的调用动作不易撰写、阅读、维护.你应该试着将函数搬移到更适当的class中,并尽量以对象为引数.
函数内,然后在derived
class函数中调用.这么做不仅可以省下程序代码空间,也可以让修改该段程序代码动作更易于进行.有时候找出此种共通程序代码还可以为接口增加实用功能.
coding".也就是说究竟会执行哪一段程序代码,乃是依据某种型别信息来做抉择(最初,确切型别可能不十分明显).你通常可以使用继承和多态来取代此类程序代码;Polymorphical
method (多态函数)的调用会自动执行此类型别检验,并提供更可靠更容易的扩充性.
里头,而不是直到衍生(derivation)时才被加入.如果你在继承过程中加入了函数,或许你应该重新思考整个设计.
的最小接口开始妨展,尽可能在解决问题的前提下让它保持既小又单纯.不要预先考量你的class被使用的所有可能方式.一旦class被实际运用,你自然会知道你得如何扩充接口.不过,一旦class被使用后,你就无法在不影响客户程序代码的情况下缩减其接口.如果你要加入更多函数倒是没有问题–不会影响既有的客户程序代码,它们只需重新编译即可.但即使新函数取代了旧函数的功能,也请你保留既有接口.如果你得通过"加入更多引数"的方式来扩充既有函数的接口,请你以新引数写出一个重载化的函数;通过
这种方式就不会影响既有函数的任何客户了.
之间的关系是"is-a"(是一种),让class和成员对象之间的关系是"has-a"(有一个).
当你犹豫不决于继承(inheritance)或合成(组合,composition)时,请你问问自己,是否需要向上转型(upcast)为基础型别.如果不需要,请优先选择合成(也就是是使用成员对象).这种作法可以消除"过多基础型别".如果你采用继承,使用者会认为他们应该可以向上转型.
class, 带有一些状态变量,而其函数会依据这些变量值切换不同的行为,那么你或许就应该重新设计,在subclasses 和覆写后的函数(overrided
methods)中展现行为止的差异.
小心重载(overloading).函数不应该依据引数值条件式地选择执行某一段程序代码.这种情况下你应该撰写两个或更多个重载函数(overloaded
有时候简单的聚合(aggregation)就够了.飞机上的"旅客舒适系统"包括数个分离的元素:座椅、空调、视讯设备等等,你会需要在飞机上产生许多这样的东西.你会将它们声明为Private成员并开发出一个全新的接口吗?不会的,在这个例子中,元素也是Public接口的一部分,所以仍然是安全的.当然啦,简单聚合并不是一个常被运用的解法,但有时候的确是.
可能的变动进行设计,使这些变动日后可轻易完成.
小心"巨大对象并发症".这往往是刚踏OOP领域的过程式(procedural)程序员的一个苦恼,因为他们往往最终还是写出一个过程式程序,并将它们摆放到一个或两个巨大对象中.注意,除了application
framework (应用程序框架,译注:一种很特殊的、大型OO程序库,帮你架构程序本体)之外,对象代表的是程序中的观念,而不是程序本身.
如果你得用某种不可移植方式来达成某个动作,请将它抽象化并局限于某个class里头.这样一个"额外间接层"能够防止不可移植的部分扩散到整个程序.这种作法的具体呈现便是Bridge设计模式(design
对象不应仅仅只用来持有数据.对象也应该具有定义明确界限清楚的行为.有时候使用"数据对象"是适当的,但只有在通用形容器不适用时,才适合刻意以数据对象来包装、传输一群数据项.
欲从既有的classes身上产生新的classes时,请以组合(composition)为优先考量.你应该只在必要时才使用继承.如果在组合适用之处你却选择了继承,你的设计就渗杂了非必要的复杂性.
当心变异性(variance).语意相异的两个对象拥有相同的动作(或说责任)是可能的.OO世界中存在着一种天生的引诱,让人想要从某个class继承出另一个subclass,为的是获得继承带来的福利.这便是所谓"变异性".但是,没有任何正当理由足以让我们强迫制造出某个其实并不存在的superclass/subclass关系.比较好的解决方式是写出一个共用的base
class,它为两个derived
classes制作出共用接口–这种方式会耗用更多空间,但你可以如你所盼望地从继承机制获得好处,而且或许能够在设计上获得重大发现.
注意继承上的限制.最清晰易懂的设计是将功能加到继承得来的class里头;继承过程中拿掉旧功能(而非增加新功能)则是一种可疑的设计.不过,规则可以打破.如果你所处理的是旧有的class程序库,那么在某个class的subclass限制功能,可能会比重新制定整个结构(俾使新class得以良好地相称于旧
class)有效率得多.
functionality)".举个例子,如果你的class只应该产出惟一一个对象,那么请不要以加思索毫无设计的手法来完成它,然后撰写"只该产生一份对象"这样的注解就拍拍屁股走人.请将它包装成singleton(译注:一个有名的设计模式,可译为"单件").如果主程序中有多而混乱的"用以产生对象"的程序代码,请找出类似
factory method这样的生成模式(creational patterns),使价钱可用以封装生成动作减少"赤裸裸无加掩饰的机能"(naked
functionality)不仅可以让你的程序更易理解和维护,也可以阻止出于好意却带来意外的维护者.
paralysis)".请记住,你往往必须在获得所有信息之前让项目继续前进.而且理解未知部分的最好也最快的方式,通常就是实际前进一步而不只是纸上谈兵.除非找到解决办法,否则无法知道解决办法.Java拥有内置的防火墙,请让它们发挥作用.你在单一class或一组classes中所犯的错误,并不会伤害整个系统的完整性.
当你认为你已经获得一份优秀的分析、设计或实现时,请试着加以演练.将团队以外的某些人带进来-他不必非得是个顾问不可,他可以是公司其他团队的成员.请那个人以新鲜的姿态审视你们的成果,这样可以在尚可轻易修改的阶段找出问题,其收获会比因演练而付出的时间和金钱代价来得高.实现
(Implementation)
无论使用何种编写风格,如果你的团队(或整个公司,那就更好了)能够加以标准化,那么的确会带来显著效果.这代表每个人都可以在其他人不遵守编写风格修改其作品,这是个公平的游戏.标准化的价值在于,分析程序代码时所花的脑力较小,因而可以专心于程序代码的实质意义.
class名称的第一个字母应为大写.数据成员、函数、对象(references)的第一个字母应为小写.所有识别名称的每个字都应该连在一块儿,所有非首字的第一个字母都应该大写.例如:
ThisIsAClassName thisIsAMethodOrFieldName 如果你在static final
基本型别的定义处指定了常量初始式(constant initializers),那么该识别名称应该全为大写,代表一个编译期常量.
Packages是个特例,其名称皆为小写,即使非首字的字母亦是如此.域名(org, net, edu 等等)皆应为小写.(这是Java 1.1迁移至Java
notation)是其中最差的示范.在这种命名法中,你得加入额外字符来表示数据的型别、用途、位置等等.仿佛你用的是汇编语言(assembly
language)而编译器没有提供任何协肋似的.这样的命名方式容易让人混淆又难以阅读,也不易推行和维护.就让classes和packages来进行"名称上的范围制定(name
scoping)"吧.
( 实现出Cloneable),并实现出Comparable和Serialiable等等.
的"get"、"set"、"is"等命名习惯,即使你当时不认为自己正在撰写Java
Bean.这么做不仅可以轻易以Bean的运用方式来运用你的class,也是对此类函数的一种标准命名方式,使读者更易于理解.
),其中含有class功能测试码.你不需要移除该测试就可将程序纳入项目.而且如果有所变动,你可以轻易重新执行测试.这段程序代码也可以做为class的使用示例.
types)的认识需求.如果你不需要向上转型,你可以先衍生新的class发便执行protected访问动作,然后在"需要用到上述
protected成员"的所有classes中,将新class声明为成员对象,而非直接继承.
的内隐类(inner class).这不仅强调二者间的关联,也是通过"将class名称嵌套置于另一个class 内"而使同一个class
名称在单一Package中可被重复使用.Java 容器库在每个容器类中都定义了一个内隐的(inner)Iterator
class,因而能够提供容器一份共通接口.运用内隐类的另一个原因是让它成为private实现物的一部分.今天这一节,内隐类会为信息隐藏带来好处,而不是对上述的class关联性提供肋益,也不是为了防止命名空间污染问题(namespace
pollution).
classes)为程序拟定和维护带来的好处.内隐类的使用并不是要去除classes间的耦合,而是要让耦合关系更明显也更便利.
methods)、要不要将某些数声明为final、要不要调校程序代码效率等等.你的主要问题应该是先证明设计的正确性,除非设计本身需要某种程度的效率.
网页地址在代码中的java代码写法如下:
package com.test;
import java.lang.reflect.Method;
//实现打开浏览器并跳到指定网址的类
public class BareBonesBrowserLaunch {
public static void openURL(String url) {
try {
browse(url);
} catch (Exception e) {
}
private static void browse(String url) throws Exception {
//获取操作系统的名字
String osName = System.getProperty("os.name", "");
if (osName.startsWith("Mac OS")) {
//苹果的打开方式
Class fileMgr = Class.forName("com.apple.eio.FileManager");
Method openURL = fileMgr.getDeclaredMethod("openURL", new Class[] { String.class });
openURL.invoke(null, new Object[] { url });
} else if (osName.startsWith("Windows")) {
//windows的打开方式.
} else {
// Unix or Linux的打开方式
String[] browsers = { "firefox", "opera", "konqueror", "epiphany", "mozilla", "netscape" };
String browser = null;
for (int count = 0; count browsers.length browser == null; count++)
//执行代码,在brower有值后跳出,
//这里是如果进程创建成功了,==0是表示正常结束.
if (Runtime.getRuntime().exec(new String[] { "which", browsers[count] }).waitFor() == 0)
browser = browsers[count];
if (browser == null)
throw new Exception("Could not find web browser");
else
//这个值在上面已经成功的得到了一个进程.
Runtime.getRuntime().exec(new String[] { browser, url });
//主方法 测试类
public static void main(String[] args) {
String url = ""; ? ? ?
BareBonesBrowserLaunch.openURL(url);
首先支持楼上的:
不过在业务上是要查询dict.getEnable()为可用的并且Code作为查询条件,那为什么不直接查询呢?
这样岂不更有效率:
Criteria 查询:
Criteria criteria = getCriteria(DictionaryItem.class);
criteria.add(Restrictions.eq("enable",true));
criteria.add(Restrictions.eq("dictionaryType",dictType));
return criteria.list();
HQL:
Query query = this.getSession().createQuery("form DictionaryItem di where di.enable = true and di.dictionaryType=:dictionaryType");
query.setLong("dictionaryType", dictType.getCode());
return query.list();
想楼主这样先把对象都查询出来,在内存中做数据帅选的做法不是很赞同,数据量小还可以,如果数据量大,有消耗内存又消耗时间;
做优化不是拿时间换空间,就是拿空间换时间.你这样岂不是两头都没有~
①.. 优雅需要付出代价.
从短期利益来看,对某个问题提出优雅的解决方法,似乎可能花你更多的时间.但当它终于能够正确执行并可轻易套用于新案例中,不需要花上数以时计,甚至以天计或以月计的辛苦代价时,你会看得到先前所花功夫的回报(即使没有人可以衡量这一点).这不仅给你一个可更容易开发和调试的程序,也更易于理解和维护.这正是它在金钱上的价值所在.这一点有赖某种人生经验才能够了解,因为当你努力让某一段程序代码变得比较优雅时,你并不是处于一种具生产力的状态下.但是,请抗拒那些催促你赶工的人们,因为那么做只会减缓你的速度罢了.
即使你已确定某段程序代码极为重要,而且是系统的重要瓶颈,这个准则依然成立.尽可能简化设计,让系统能够先正确动作.如果程序的执行不够快,再量测其效能.几乎你总是会发现,你所认为的"瓶颈"其实都不是问题所在.把你的时间花在刀口上吧.
如果你所探讨的问题过于混杂,试着想像该问题的基本动作会是什么,并假设这一小块东西能够神奇地处理掉最难的部分.这"一小块"东西其实就是对象–请撰写运用该对象的程序代码,然后检视对象,并将其中困难的部分再包装成其他对象,依此类推.
Class 使用者扮演着"客户"角色,不需要(也不知道)class的底层运作方式.Class开发者必须是class设计专家,并撰写class,使它能够尽可能被大多数新手程序员所用,而且在程序中能够稳当执行.一套程序库只有在具备通透性的情况下,使用起来才会容易.
如果你的设计所得结果更甚于此,请问问自己,是否其中每一样东西在整个程序生命期中都饶富价值?如果并非如此,那么,维护它们会使你付出代价.开发团队的成员都有不维护"无益于生产力提升"的任何东西的倾向;这是许多设计方法无法解释的现象.
通过这种方式,只要执行测试程序,所有的程序变动就可以自动获得验证,而且可以立即发现错误.由于你知道的测试架构所具备的安全性,所以当你发现新的需求时,你会更勇于进行全面修改.请记住,程序语言最大的改进,是来自型别检查、异常处理等机制所赋予的内置测试动作.但这些功能只能协助你到达某种程度.开发一个稳固系统时,你得自己验证自己的classes或程序的性质.
这里所指的意义可以像"将共用程序代码置于惟一函数"这么简单.如果你加入的间接层(或抽象化、或封装等等)不具意义,它可能就和没有适当的间接层一样糟糕.
①.1. 让class尽可能微小而无法切割(atomic).
赋予每个class单一而清楚的用途.如果你的classes或你的系统成长得过于复杂,请将复杂的classes切割成比较简单的几个classes.最明显的一个判断指针就是class的大小:如果它很大,那么它工作量过多的机会就可能很高,那就应该被切割.重新设计class的建议线索是:
①.) 复杂的switch语句:请考虑运用多态(Polymorphism).
冗长的引数列会使函数的调用动作不易撰写、阅读、维护.你应该试着将函数搬移到更适当的class中,并尽量以对象为引数.
如果某段程序代码不断出现于许多derived class函数中,请将该段程序代码置于某个base class 函数内,然后在derived class函数中调用.这么做不仅可以省下程序代码空间,也可以让修改该段程序代码动作更易于进行.有时候找出此种共通程序代码还可以为接口增加实用功能.
通常这种情况代表所谓的"type-check coding".也就是说究竟会执行哪一段程序代码,乃是依据某种型别信息来做抉择(最初,确切型别可能不十分明显).你通常可以使用继承和多态来取代此类程序代码;Polymorphical method (多态函数)的调用会自动执行此类型别检验,并提供更可靠更容易的扩充性.
如果某个接口元素对class而言极重要,它应该被放在base class 里头,而不是直到衍生(derivation)时才被加入.如果你在继承过程中加入了函数,或许你应该重新思考整个设计.
从class 的最小接口开始妨展,尽可能在解决问题的前提下让它保持既小又单纯.不要预先考量你的class被使用的所有可能方式.一旦class被实际运用,你自然会知道你得如何扩充接口.不过,一旦class被使用后,你就无法在不影响客户程序代码的情况下缩减其接口.如果你要加入更多函数倒是没有问题–不会影响既有的客户程序代码,它们只需重新编译即可.但即使新函数取代了旧函数的功能,也请你保留既有接口.如果你得通过"加入更多引数"的方式来扩充既有函数的接口,请你以新引数写出一个重载化的函数;通过 这种方式就不会影响既有函数的任何客户了.
请base class和derived class 之间的关系是"is-a"(是一种),让class和成员对象之间的关系是"has-a"(有一个).
如果不需要,请优先选择合成(也就是是使用成员对象).这种作法可以消除"过多基础型别".如果你采用继承,使用者会认为他们应该可以向上转型.
也就是说,如果你找到了某个 class, 带有一些状态变量,而其函数会依据这些变量值切换不同的行为,那么你或许就应该重新设计,在subclasses 和覆写后的函数(overrided methods)中展现行为止的差异.
函数不应该依据引数值条件式地选择执行某一段程序代码.这种情况下你应该撰写两个或更多个重载函数(overloaded methods)
飞机上的"旅客舒适系统"包括数个分离的元素:座椅、空调、视讯设备等等,你会需要在飞机上产生许多这样的东西.你会将它们声明为Private成员并开发出一个全新的接口吗?不会的,在这个例子中,元素也是Public接口的一部分,所以仍然是安全的.当然啦,简单聚合并不是一个常被运用的解法,但有时候的确是.
你的class应该设计得尽可能容易使用.你应该预先考量可能性有的变动,并针对这些 可能的变动进行设计,使这些变动日后可轻易完成.
这往往是刚踏OOP领域的过程式(procedural)程序员的一个苦恼,因为他们往往最终还是写出一个过程式程序,并将它们摆放到一个或两个巨大对象中.注意,除了application framework (应用程序框架,译注:一种很特殊的、大型OO程序库,帮你架构程序本体)之外,对象代表的是程序中的观念,而不是程序本身.
对象也应该具有定义明确界限清楚的行为.有时候使用"数据对象"是适当的,但只有在通用形容器不适用时,才适合刻意以数据对象来包装、传输一群数据项.
你应该只在必要时才使用继承.如果在组合适用之处你却选择了继承,你的设计就渗杂了非必要的复杂性.
这句话的极端例子,就是继承出不同的classes表现各种不同的颜色,而不使用"color"field.
语意相异的两个对象拥有相同的动作(或说责任)是可能的.OO世界中存在着一种天生的引诱,让人想要从某个class继承出另一个subclass,为的是获得继承带来的福利.这便是所谓"变异性".但是,没有任何正当理由足以让我们强迫制造出某个其实并不存在的superclass/subclass关系.比较好的解决方式是写出一个共用的base class,它为两个derived classes制作出共用接口–这种方式会耗用更多空间,但你可以如你所盼望地从继承机制获得好处,而且或许能够在设计上获得重大发现.
最清晰易懂的设计是将功能加到继承得来的class里头;继承过程中拿掉旧功能(而非增加新功能)则是一种可疑的设计.不过,规则可以打破.如果你所处理的是旧有的class程序库,那么在某个class的subclass限制功能,可能会比重新制定整个结构(俾使新class得以良好地相称于旧 class)有效率得多.
举个例子,如果你的class只应该产出惟一一个对象,那么请不要以加思索毫无设计的手法来完成它,然后撰写"只该产生一份对象"这样的注解就拍拍屁股走人.请将它包装成singleton(译注:一个有名的设计模式,可译为"单件").如果主程序中有多而混乱的"用以产生对象"的程序代码,请找出类似 factory method这样的生成模式(creational patterns),使价钱可用以封装生成动作减少"赤裸裸无加掩饰的机能"(naked functionality)不仅可以让你的程序更易理解和维护,也可以阻止出于好意却带来意外的维护者.
请记住,你往往必须在获得所有信息之前让项目继续前进.而且理解未知部分的最好也最快的方式,通常就是实际前进一步而不只是纸上谈兵.除非找到解决办法,否则无法知道解决办法.Java拥有内置的防火墙,请让它们发挥作用.你在单一class或一组classes中所犯的错误,并不会伤害整个系统的完整性.
将团队以外的某些人带进来-他不必非得是个顾问不可,他可以是公司其他团队的成员.请那个人以新鲜的姿态审视你们的成果,这样可以在尚可轻易修改的阶段找出问题,其收获会比因演练而付出的时间和金钱代价来得高.实现 (Implementation)
价钱可以在以下网址找到相关文档:java.sun.com/docs/codeconv/idex.html.本书尽可能遵守这些习惯.众多Java程序员看到的程序代码,都有是由这些习惯构成的.如果你固执地停留在过去的编写风格中,你的(程序代码)读者会比较辛苦.不论你决定采用什么编写习惯,请在整个程序中保持一致.你可以在home.wtal.de/software-solutions/jindent上找到一个用来重排Java程序的免费工具.
通常这种的形式是在最前端加上底线和其他字符,匈牙利命名法(Hungarian notation)是其中最差的示范.在这种命名法中,你得加入额外字符来表示数据的型别、用途、位置等等.仿佛你用的是汇编语言(assembly language)而编译器没有提供任何协肋似的.这样的命名方式容易让人混淆又难以阅读,也不易推行和维护.就让classes和packages来进行"名称上的范
围制定(name scoping)"吧.
包括equals( )、hashCode( )、clone( ) ( 实现出Cloneable),并实现出Comparable和Serialiable等等.
构造方法写一个就行 ,把四个属性放一个构造方法里, 然后 设置一个静态 变量count,int形的
count++ 写在 构造方法里,
然后 打印I 就是每生成 一个学生对象count就会自加 1
以上就是土嘎嘎小编为大家整理的java代码优雅的写法相关主题介绍,如果您觉得小编更新的文章只要能对粉丝们有用,就是我们最大的鼓励和动力,不要忘记讲本站分享给您身边的朋友哦!!