摘要:特別是在可能返回空的集合的情況下務必返回一個內容為空的集合而不是一個。對于集合類型,應該在任何允許的情況下使用的或者類。框架框架是你部署代碼的一個很好地方式,其中較好的選擇有與。包含了大量與文件相關的操作。
原文地址:這里
Java是目前世界上最流行的編程語言之一,但是并不是所有人都樂于使用它。不過Java其實是一個還不錯的語言,也別是自從Java 8正式發布之后,所以我決定將我的一些實踐、庫和工具列舉下來以供大家參考。
Style(樣式)傳統而言,Java是習慣以冗長的JavaBean方式來定義某個數據對象,新的樣式可能會更清晰和保證準確性。
Structs(結構體)在編程中程序員最常見的操作就是進行數據傳遞,傳統的方式是JavaBean,如下所示:
public class DataHolder { private String data; public DataHolder() { } public void setData(String data) { this.data = data; } public String getData() { return this.data; } }
不過這種方式是冗長并且浪費資源的,即便你的編輯器能夠自動生成這種代碼。作為替代方法,我寧可選擇使用C風格里的結構體樣式去編寫這種容器數據:
public class DataHolder { public final String data; public DataHolder(String data) { this.data = data; } }
這種方式幾乎可以使得代碼的行數減半,除此之外,這種類是不可變的類,所以在某些情況下我們可以放心的使用它。如果你是希望能夠用Map或者List這些結構體去存儲對象而使得修改變得簡單一點,可以使用ImmutableMap或者ImmutableList,這部分會在下面討論。
Builder模式如果你的數據元結構比較復雜,可以考慮使用如下的Builder模式。Builder模式在數據類構造器中定義了一個子類,使用可變狀態,不過一旦創建之后就會變得不可改變:
public class ComplicatedDataHolder { public final String data; public final int num; // lots more fields and a constructor public static class Builder { private String data; private int num; public Builder data(String data) { this.data = data; return this; } public Builder num(int num) { this.num = num; return this; } public ComplicatedDataHolder build() { return new ComplicatedDataHolder(data, num); // etc } } }
然后可以按照如下去使用:
final ComplicatedDataHolder cdh = new ComplicatedDataHolder.Builder() .data("set this") .num(523) .build();Dependency injection(依賴注入)
依賴注入更多的從屬于軟件工程的范疇而不是Java的范疇,但是去撰寫可測試的軟件的最好的方式就是使用依賴注入。因為Java強烈推薦OO的設計方式,為了讓軟件具有較好的可測試性,可以去使用依賴注入。
在Java領域,最經典的DI框架當屬Spring,它提供了基于代碼的注入以及基于XML配置的注入方式。不過Spring確實有點繁瑣,如果單純的只是想使用依賴注入這個功能,可以選擇Google 和 Square的 Dagger 庫 或者 Google"s Guice.
避免空指針盡可能地避免使用空指針。特別是在可能返回空的集合的情況下務必返回一個內容為空的集合而不是一個null。如果使用的是Java 8 ,可以使用新的Optional類型來避免可能的空指針:
public class FooWidget { private final String data; private final Optionalbar; public FooWidget(String data) { this(data, Optional.empty()); } public FooWidget(String data, Optional bar) { this.data = data; this.bar = bar; } public Optional getBar() { return bar; } }
根據上述代碼可以知道,返回的數據肯定不會為null類型,不過bar不一定是present的。
final OptionalImmutable-by-default(默認不可變)fooWidget = maybeGetFooWidget(); final Baz baz = fooWidget.flatMap(FooWidget::getBar) .flatMap(BarWidget::getBaz) .orElse(defaultBaz);
java-advantages-of-of-immutable-objects-in-examples
除非有特殊的理由,否則變量、類以及集合應該默認設置為不可變。其中變量類型可以使用final關鍵字來設置不可變性:
final FooWidget fooWidget; if (condition()) { fooWidget = getWidget(); } else { try { fooWidget = cachedFooWidget.get(); } catch (CachingException e) { log.error("Couldn"t get cached value", e); throw e; } } // fooWidget is guaranteed to be set here
這種方式進行變量操作就可以確保fooWidget不會被偶然的改變指向,final關鍵字可以作用于if-else代碼塊以及try-catch代碼塊。對于集合類型,應該在任何允許的情況下使用Guava 的ImmutableMap,ImmutableList, 或者 ImmutableSet 類。他們都含有構造器類型,可以使用Builder進行動態構造最終調用build方法設置為不可變。
而對于類,可以通過設置其成員變量為final類型來將其變為不可變類型。另外,也可以將類本身設置為final類型來保證其不可以被擴展或者設置為可變類型。
Avoid lots of Util Classes(避免使用大量工具類)一不注意,就會發現自己寫了N多的Util類,譬如:
public class MiscUtil { public static String frobnicateString(String base, int times) { // ... etc } public static void throwIfCondition(boolean condition, String msg) { // ... etc } }
這些類看上去很有作用,因為它們并不屬于任何邏輯模塊,所以可以盡可能的代碼重用。不過所謂是藥三分毒,在程序中更應當把這些類放置在他們屬于的地方,或者使用Java 8添加的接口中的默認方法來設置一些通用方法,其使用方式如下:
public interface Thrower { default void throwIfCondition(boolean condition, String msg) { // ... } default void throwAorB(Throwable a, Throwable b, boolean throwA) { // ... } }
這樣每個需要使用這些接口的類可以方便的進行自定義。
格式化格式化本身的重要性不亞于編程本身,很多優秀的程序員會花一天的時間去為if代碼塊添加空格從而使代碼看起來更加的整齊。如果需要一個完整的代碼格式指南,可以參考Google的Google"s Java Style ,特別是其中的Programming Practices 非常有意義。
JavaDoc為你的代碼添加JavaDoc同樣非常重要,可以參考這個示例: using examples
StreamsJava 8提供了非常Nice的Stream API,可以用如下的寫法:
final Listfiltered = list.stream() .filter(s -> s.startsWith("s")) .map(s -> s.toUpperCase()) .collect(Collectors.toList());
來替代:
final Listfiltered = new ArrayList<>(); for (String str : list) { if (str.startsWith("s") { filtered.add(str.toUpperCase()); } }
這樣可以幫助你寫更多的高可讀性的、流暢的代碼。
Deploying(部署)部分Java代碼可能需要一定的技巧性,目前一般來說部署Java主要有兩種方式:使用某個框架或者是有一個本地化的可伸縮框架。
Frameworks(框架)框架是你部署Java代碼的一個很好地方式,其中較好的選擇有Dropwizard與Spring Boot。另外Play framework 也是一個不錯的選擇。
MavenMaven是一個非常優秀的Java編譯與依賴管理工具,通過如下方式可以方便的添加Maven依賴項:
org.third.party some-artifact
Dependence Convergence(依賴收斂)關于Maven的具體使用可以參考筆者的其余文章
Java中一個巨大的魅力即在于有大量的第三方類庫可供參考,有必要將所有用到的API或者SDK置于Maven最后那個。不過各種類庫之間往往也是相互依賴的,譬如:
Foo library depends on Bar library v1.0 Widget library depends on Bar library v0.9
利用Maven dependency convergence plugin,在編譯的時候會告警有一個依賴項依賴不同的版本,一般來說,可以用如下方式處理:
1.在dependenceManagement塊選擇一個特定的版本。
2.在Foo或者Widget依賴項中使用Exclude移除Bar。
Continuous Integration(持續集成)在大型項目開發中,往往需要一些持續集成工具來不斷基于git構建測試版本,其中Jenkins 和Travis-CI 是較常見的選擇。另外,在正式的構建之前往往需要使用代碼測試工具,Cobertura就是一個非常好用的測試覆蓋率校驗工具。
Maven Repository在大型項目開發中,往往會需要一個Repo去存放私人的Jars、Wars以及EARs。Artifactory 與 Nexus都是不錯的選擇。
Configuration Management(配置管理)Chef, Puppet, 以及 Ansible 都是不錯的選擇。
Libraries可能Java最優秀的屬性就是它的大量的擴展庫,本部分列舉了部分常用的擴展庫。
Missing Features(遺失的特性) Apache CommonsThe Apache Commons project 包含了一些列常用的庫.
Commons Codec 包含了大量有用的編碼與解碼的方法。
Commons Lang 包含了大量的字符串處理以及字符編碼相關的方法。
Commons IO 包含了大量與文件相關的操作。 It has FileUtils.copyDirectory, FileUtils.writeStringToFile,IOUtils.readLines and much more.
GuavaGuava is Google"s excellent here"s-what-Java-is-missing library.
GsonGoogle"s Gson library is a simple and fast JSON parsing library. Itworks like this:
final Gson gson = new Gson(); final String json = gson.toJson(fooWidget); final FooWidget newFooWidget = gson.fromJson(json, FooWidget.class);
It"s really easy and a pleasure to work with. The Gson user guidehas many more examples.
Java TuplesJava的標準庫未能提供Tuples相關的數據結構是一個很大的遺憾。幸虧 Java tuples項目填補了這個空白:
PairLombokfunc(String input) { // something... return Pair.with(stringResult, intResult); }
Lombok 是一個非常有趣的類庫,通過注解方式可以允許減少Java存在的冗余代碼,譬如以下的常見的Getter/Setter代碼的功能:
public class Foo { @Getter @Setter private int var; }
而現在可以這么寫:
final Foo foo = new Foo(); foo.setVar(5);Play framework
Good alternatives: Jersey or Spark
There are two main camps for doing RESTful web services in Java: JAX-RS and everything else.
JAX-RS is the traditional way. You combine annotations with interfaces andimplementations to form the web service using something like Jersey.What"s nice about this is you can easily make clients out of just the interface class.
The Play framework is a radically different take on web services onthe JVM: you have a routes file and then you write the classes referenced inthose routes. It"s actually an entire MVC framework, but you caneasily use it for just REST web services.
It"s available for both Java and Scala. It suffers slightly from being Scala-first, but it"s still good to use in Java.
If you"re used to micro-frameworks like Flask in Python, Spark willbe very familiar. It works especially well with Java 8.
SLF4JThere are a lot of Java logging solutions out there. My favorite isSLF4J because it"s extremely pluggable and can combine logs from manydifferent logging frameworks at the same time. Have a weird project that usesjava.util.logging, JCL, and log4j? SLF4J is for you.
The two-page manual is pretty much all you"ll need to getstarted.
JOOQI dislike heavy ORM frameworks because I like SQL. So I wrote a lot ofJDBC templates and it was sort of hard to maintain. jOOQ is amuch better solution.
It lets you write SQL in Java in a type safe way:
// Typesafely execute the SQL statement directly with jOOQ Result> result = create.select(BOOK.TITLE, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME) .from(BOOK) .join(AUTHOR) .on(BOOK.AUTHOR_ID.equal(AUTHOR.ID)) .where(BOOK.PUBLISHED_IN.equal(1948)) .fetch();
Using this and the DAO pattern, you can make database access a breeze.
Testing jUnit 4jUnit needs no introduction. It"s the standard tool for unit testingin Java.
But you"re probably not using jUnit to its full potential. jUnit supportsparametrized tests, rules to stop you from writingso much boilerplate, theories to randomly test certain code,and assumptions.
jMockIf you"ve done your dependency injection, this is where it pays off: mockingout code which has side effects (like talking to a REST server) and stillasserting behavior of code that calls it.
jMock is the standard mocking tool for Java. It looks like this:
public class FooWidgetTest { private Mockery context = new Mockery(); @Test public void basicTest() { final FooWidgetDependency dep = context.mock(FooWidgetDependency.class); context.checking(new Expectations() {{ oneOf(dep).call(with(any(String.class))); atLeast(0).of(dep).optionalCall(); }}); final FooWidget foo = new FooWidget(dep); Assert.assertTrue(foo.doThing()); context.assertIsSatisfied(); } }
This sets up a FooWidgetDependency via jMock and then adds expectations. Weexpect that dep"s call method will be called once with some String and thatdep"s optionalCall method will be called zero or more times.
If you have to set up the same dependency over and over, you should probablyput that in a test fixture and put assertIsSatisfied in an@After fixture.
AssertJDo you ever do this with jUnit?
final Listresult = some.testMethod(); assertEquals(4, result.size()); assertTrue(result.contains("some result")); assertTrue(result.contains("some other result")); assertFalse(result.contains("shouldn"t be here"));
This is just annoying boilerplate. AssertJ solves this. You cantransform the same code into this:
assertThat(some.testMethod()).hasSize(4) .contains("some result", "some other result") .doesNotContain("shouldn"t be here");
This fluent interface makes your tests more readable. What more could you want?
Tools IntelliJ IDEAGood alternatives: Eclipse and Netbeans
The best Java IDE is IntelliJ IDEA. It has a ton of awesomefeatures, and is really the main thing that makes the verbosity of Javabareable. Autocomplete is great, the inspections are top notch, and the refactoringtools are really helpful.
The free community edition is good enough for me, but there are loads of greatfeatures in the Ultimate edition like database tools, Spring Framework supportand Chronon.
ChrononOne of my favorite features of GDB 7 was the ability to travel back in timewhen debugging. This is possible with the Chronon IntelliJ pluginwhen you get the Ultimate edition.
You get variable history, step backwards, method history and more. It"s alittle strange to use the first time, but it can help debug some reallyintricate bugs, Heisenbugs and the like.
JRebelContinuous integration is often a goal of software-as-a-service products. Whatif you didn"t even need to wait for the build to finish to see code changeslive?
That"s what JRebel does. Once you hook up your server to your JRebelclient, you can see changes on your server instantly. It"s a huge time savingswhen you want to experiment quickly.
The Checker FrameworkJava"s type system is pretty weak. It doesn"t differentiate between Stringsand Strings that are actually regular expressions, nor does it do anytaint checking. However, the Checker Frameworkdoes this and more.
It uses annotations like @Nullable to check types. You can even define your own annotations to make the static analysis done evenmore powerful.
Eclipse Memory AnalyzerMemory leaks happen, even in Java. Luckily, there are tools for that. The besttool I"ve used to fix these is the Eclipse Memory Analyzer. It takes aheap dump and lets you find the problem.
There"s a few ways to get a heap dump for a JVM process, but I usejmap:
$ jmap -dump:live,format=b,file=heapdump.hprof -F 8152 Attaching to process ID 8152, please wait... Debugger attached successfully. Server compiler detected. JVM version is 23.25-b01 Dumping heap to heapdump.hprof ... ... snip ... Heap dump file created
Then you can open the heapdump.hprof file with the Memory Analyzer and seewhat"s going on fast.
Resources(資源) Books(書籍)Effective Java
[Java Concurrency in Practice
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/64551.html
摘要:從使用到原理學習線程池關于線程池的使用,及原理分析分析角度新穎面向切面編程的基本用法基于注解的實現在軟件開發中,分散于應用中多出的功能被稱為橫切關注點如事務安全緩存等。 Java 程序媛手把手教你設計模式中的撩妹神技 -- 上篇 遇一人白首,擇一城終老,是多么美好的人生境界,她和他歷經風雨慢慢變老,回首走過的點點滴滴,依然清楚的記得當初愛情萌芽的模樣…… Java 進階面試問題列表 -...
摘要:好不容易在月號這天中午點左右接到了來自阿里的面試電話。這里會不斷收集和更新基礎相關的面試題,目前已收集題。面試重難點的和的打包過程多線程機制機制系統啟動過程,啟動過程等等掃清面試障礙最新面試經驗分享,此為第一篇,開篇。 2016 年末,騰訊,百度,華為,搜狗和滴滴面試題匯總 2016 年未,騰訊,百度,華為,搜狗和滴滴面試題匯總 各大公司 Java 后端開發面試題總結 各大公司 Jav...
閱讀 3454·2023-04-26 01:45
閱讀 2233·2021-11-23 09:51
閱讀 3644·2021-10-18 13:29
閱讀 3442·2021-09-07 10:12
閱讀 705·2021-08-27 16:24
閱讀 1775·2019-08-30 15:44
閱讀 2200·2019-08-30 15:43
閱讀 2956·2019-08-30 13:11