如何写出更好的Java代码

倾然丶 夕夏残阳落幕 提交于 2019-11-29 00:44:28

编码风格

传统的Java编码方式是非常啰嗦的企业级JavaBean的风格。新的风格更简洁准确,对眼睛也更好。

结构体

我们这些码农干的最简单的事情就是传递数据了。传统的方式就是定义一个JavaBean:

<code style="margin: 0px; padding: 0px; max-width: 100%; font-family: Fixedsys; color: rgb(51, 51, 51); background-color: rgb(248, 248, 248); box-sizing: border-box !important; overflow-wrap: break-word !important;">public class DataHolder {<br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> nbsp nbsppublic final String data;<br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"><br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> nbsp nbsppublic DataHolder(String data) {<br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> nbsp nbsp nbsp nbspthis.data = data;<br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> nbsp nbsp}<br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;">} nbsp </code>

这不仅拖沓而且浪费。尽管你的IDE可以自动地生成这个,但这还是浪费。因此,不要这么写。

相反的,我更喜欢C的结构体的风格,写出来的类只是包装数据:

<code style="margin: 0px; padding: 0px; max-width: 100%; font-family: Fixedsys; color: rgb(51, 51, 51); background-color: rgb(248, 248, 248); box-sizing: border-box !important; overflow-wrap: break-word !important;">public class DataHolder {<br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> nbsp nbsp public final String data;<br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> nbsp nbsp public DataHolder(String data) {<br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> nbsp nbsp nbsp nbsp this.data = data;<br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> nbsp nbsp }<br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;">}</code>

这样写减少了一半的代码。不仅如此,除非你继承它,不然这个类是不可变的,由于它是不可变的,因此推断它的值就简单多了。

如果你存储的是Map或者List这些可以容易被修改的数据,你可以使用ImmutableMap或者ImmutableList,这个在不可变性这节中会有讨论。

Builder模式

如果你有一个相对复杂的对象,可以考虑下Builder模式。

你在对象里边创建一个子类,用来构造你的这个对象。它使用的是可修改的状态,但一旦你调用了build方法,它会生成一个不可变对象。

想象一下我们有一个非常复杂的对象DataHolder。它的构造器看起来应该是这样的:

<code style="margin: 0px; padding: 0px; max-width: 100%; font-family: Fixedsys; color: rgb(51, 51, 51); background-color: rgb(248, 248, 248); box-sizing: border-box !important; overflow-wrap: break-word !important;">public class ComplicatedDataHolder {<br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> nbsp nbsp public final String data;<br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> nbsp nbsp public final int num;<br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> nbsp nbsp // lots more fields and a constructor<br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> nbsp nbsp public class Builder {<br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> nbsp nbsp nbsp nbsp private String data;<br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> nbsp nbsp nbsp nbsp private int num;<br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> nbsp nbsp public Builder data(String data) {<br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> nbsp nbsp nbsp nbsp this.data = data;<br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> nbsp nbsp nbsp nbsp return this;<br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> nbsp nbsp }<br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> nbsp nbsp public Builder num(int num) {<br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> nbsp nbsp nbsp nbsp this.num = num;<br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> nbsp nbsp nbsp nbsp return this;<br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> nbsp nbsp }<br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> nbsp nbsp public ComplicatedDataHolder build() {<br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> nbsp nbsp nbsp nbsp return new ComplicatedDataHolder(data, num);<br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> nbsp nbsp nbsp nbsp // etc<br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> nbsp nbsp }<br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> nbsp nbsp } <br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;">}</code>

现在你可以使用它了:

<code style="margin: 0px; padding: 0px; max-width: 100%; font-family: Fixedsys; color: rgb(51, 51, 51); background-color: rgb(248, 248, 248); box-sizing: border-box !important; overflow-wrap: break-word !important;">final ComplicatedDataHolder <br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;">cdh = new ComplicatedDataHolder.Builder()<br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> nbsp nbsp .data("set this")<br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> nbsp nbsp .num(523)<br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> nbsp nbsp .build();</code>

关于Builder的使用这里还有些更好的例子,我这里举的例子只是想让你大概感受一下。当然这会产生许多我们希望避免的样板代码,不过好处就是你有了一个不可变对象以及一个连贯接口。

依赖注入

这更像是一个软件工程的章节而不是Java的,写出可测的软件的一个最佳方式就是使用依赖注入(Dependency injection,DI)。由于Java强烈鼓励使用面向对象设计 ,因此想写出可测性强的软件,你需要使用DI。

在Java中,这个通常都是用Spring框架来完成的。它有一个基于XML配置的绑定方式,并且仍然相当流行。

重要的一点是你不要因为它的基于XML的配置格式而过度使用它了。在XML中应该没有任何的逻辑和控制结构。它只应该是依赖注入。

还有一个不错的方式是使用Dagger库以及Google的Guice。它们并没有使用Spring的XML配置文件的格式,而是将注入的逻辑放到了注解和代码里。

避免null值

如果有可能的话尽量避免使用null值。你可以返回一个空的集合,但不要返回null集合。如果你准备使用null的话,考虑一下@Nullable注解。IntelliJ IDEA对于@Nullable注解有内建的支持。

如果你使用的是Java 8的话,可以考虑下新的Optional类型。如果一个值可能存在也可能不存在,把它封装到Optional类里面,就像这样:

<code style="margin: 0px; padding: 0px; max-width: 100%; font-family: Fixedsys; color: rgb(51, 51, 51); background-color: rgb(248, 248, 248); box-sizing: border-box !important; overflow-wrap: break-word !important;">public class FooWidget {<br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> nbsp nbsp private final String data;<br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> nbsp nbsp private final OptionalltBargt bar;<br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> nbsp nbsp <br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> nbsp nbsp nbsp nbsp public FooWidget(String data) {<br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> nbsp nbsp nbsp nbsp nbsp nbsp this(data, Optional.empty());<br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> nbsp nbsp nbsp nbsp }<br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> nbsp nbsp nbsp nbsp public FooWidget(String data, OptionalltBargt bar) {<br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> nbsp nbsp nbsp nbsp nbsp nbsp this.data = data;<br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> nbsp nbsp nbsp nbsp nbsp nbsp this.bar = bar;<br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> nbsp nbsp nbsp nbsp }<br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> nbsp nbsp nbsp nbsp public OptionalltBargt getBar() {<br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> nbsp nbsp nbsp nbsp nbsp nbsp return bar;<br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> nbsp nbsp nbsp nbsp }<br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;">}</code>

现在问题就清楚了,data是不会为null的,而bar可能为空。Optional类有一些像isPresent这样的方法,这让它感觉跟检查null没什么区别。

不过有了它你可以写出这样的语句:

<code style="margin: 0px; padding: 0px; max-width: 100%; font-family: Fixedsys; color: rgb(51, 51, 51); background-color: rgb(248, 248, 248); box-sizing: border-box !important; overflow-wrap: break-word !important;">final OptionalltFooWidgetgt <br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;">fooWidget = maybeGetFooWidget(); <br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;">final Baz baz = fooWidget.flatMap(FooWidget::getBar)<br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp.flatMap(BarWidget::getBaz)<br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp.orElse(defaultBaz); nbsp </code>

这比使用if来检查null好多了。唯一的缺点就是标准类库中对Optional的支持并不是很好,因此你还是需要对null进行检查的。

不可变

变量,类,集合,这些都应该是不可变的,除非你有更好的理由它们的确需要进行修改。

变量可以通过final来设置成不可变的:

<code style="margin: 0px; padding: 0px; max-width: 100%; font-family: Fixedsys; color: rgb(51, 51, 51); background-color: rgb(248, 248, 248); box-sizing: border-box !important; overflow-wrap: break-word !important;">final FooWidget fooWidget;<br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> nbsp nbspif (condition()) {<br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> nbsp nbsp nbsp nbspfooWidget = getWidget();<br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> nbsp nbsp} else {<br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> nbsp nbsp nbsp nbsptry {<br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> nbsp nbsp nbsp nbsp nbsp nbspfooWidget = cachedFooWidget.get();<br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> nbsp nbsp nbsp nbsp} catch (CachingException e) {<br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> nbsp nbsp nbsp nbsp nbsp nbsplog.error("Couldn't get cached value", e);<br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> nbsp nbsp nbsp nbsp nbsp nbspthrow e; nbsp<br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> nbsp nbsp nbsp nbsp} <br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> nbsp nbsp } // fooWidget is guaranteed to be set here nbsp </code>

现在你可以确认fooWidget不会不小心被重新赋值了。final关键字可以和if/else块以及try/catch块配合使用。当然了,如果fooWidget对象不是不可变的,你也可以很容易地对它进行修改。

有可能的话,集合都应该尽量使用Guava的ImmutableMap, ImmutableList, or ImmutableSet类。这些类都有自己的构造器,你可以动态的创建它们,然后将它们设置成不可变的。

要使一个类不可变,你可以将它的字段声明成不可变的(设置成final)。你也可以把类自身也设置成final的这样它就不能被扩展并且修改了,当然这是可选的。

避免大量的工具类

如果你发现自己添加了许多方法到一个Util类里,你要注意了。

<code style="margin: 0px; padding: 0px; max-width: 100%; font-family: Fixedsys; color: rgb(51, 51, 51); background-color: rgb(248, 248, 248); box-sizing: border-box !important; overflow-wrap: break-word !important;">public class MiscUtil {<br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> nbsp nbsp public static String frobnicateString(String base, int times) {<br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> nbsp nbsp // ... etc<br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> nbsp nbsp }<br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> nbsp nbsp public static void throwIfCondition(boolean condition, String msg) {<br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> nbsp nbsp // ... etc<br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> nbsp nbsp }<br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;">}</code>

这些类乍一看挺吸引人的,因为它们里面的这些方法不属于任何一个地方。因此你以代码重用之名将它们全都扔到这里了。

这么解决问题结果更糟。把它们放回它们原本属于的地方吧,如果你确实有一些类似的常用方法,考虑下Java 8里接口的默认方法。并且由于它们是接口,你可以实现多个方法。

<code style="margin: 0px; padding: 0px; max-width: 100%; font-family: Fixedsys; color: rgb(51, 51, 51); background-color: rgb(248, 248, 248); box-sizing: border-box !important; overflow-wrap: break-word !important;">public interface Thrower {<br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> nbsp nbsp public void throwIfCondition(boolean condition, String msg) {<br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> nbsp nbsp // ... nbsp nbsp<br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> nbsp nbsp } nbsp nbsp<br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> nbsp nbsp public void throwAorB(Throwable a, Throwable b, boolean throwA) { nbsp <br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> nbsp nbsp // ... nbsp <br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> nbsp nbsp }<br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> }</code>

这样需要使用它的类只需简单的实现下这个接口就可以了。

格式

格式远比许多程序员相像的要重要的多。一致的格式说明你关注自己的代码或者对别人有所帮助?

是的。不过你先不要着急为了让代码整齐点而浪费一整天的时间在那给if块加空格了。

如果你确实需要一份代码格式规范,我强烈推荐Google的Java风格指南。这份指南最精彩的部分就是编程实践这节了。非常值得一读。

文档

面向用户的代码编写下文档还是很重要的。这意味着你需要提供一些使用的示例,同时你的变量方法和类名都应该有适当的描述信息。

结论就是不要给不需要文档的地方添加文档。如果对于某个参数你没什么可说的,或者它已经非常明显了,别写文档了。模板化的文档比没有文档更糟糕,因为它欺骗了你的用户,让他觉得这里有文档。

Java 8有一个漂亮的流和lambda表达式的语法。你的代码可以这么写:

<code style="margin: 0px; padding: 0px; max-width: 100%; font-family: Fixedsys; color: rgb(51, 51, 51); background-color: rgb(248, 248, 248); box-sizing: border-box !important; overflow-wrap: break-word !important;">final ListltStringgt <br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;">filtered = list.stream()<br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> nbsp nbsp .filter(s -gt s.startsWith("s")) nbsp nbsp<br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> nbsp nbsp .map(s -gt s.toUpperCase()); </code>

而不是这样:

<code style="margin: 0px; padding: 0px; max-width: 100%; font-family: Fixedsys; color: rgb(51, 51, 51); background-color: rgb(248, 248, 248); box-sizing: border-box !important; overflow-wrap: break-word !important;">final ListltStringgt <br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;">filtered = Lists.newArrayList(); <br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;">for (String str : list) {<br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> nbsp nbsp if (str.startsWith("s") {<br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> nbsp nbsp nbsp nbsp filtered.add(str.toUpperCase());<br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> nbsp nbsp }<br data-filtered="filtered" style="line-height: normal; margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;">}</code>

这样你能写出更连贯的代码,可读性也更强。

部署

正确地部署Java程序还是需要点技巧的。现在部署Java代码的主流方式有两种 :使用框架或者使用自家摸索出来的解决方案,当然那样更灵活。

框架

由于部署Java程序并不容易,因此才有了各种框架来用于部署。最好的两个是Dropwizard以及Spring Boot。Play Framework也可以算是一个部署框架。

这些框架都试图降低部署程序的门槛。如果你是一个Java的新手或者你需要快速把事情搞定的话,那么框架就派上用场了。单个jar的部署当然会比复杂的WAR或者EAR部署要更容易一些。

然而,这些框架的灵活性不够,并且相当顽固,因此如果这些框架的开发人员给出的方式不太适合你的项目的话,你只能自己进行配置了。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!