Better Java -- to teach you how to write a modern Java program

By Gail Knight,2015-11-14 21:30
11 views 0
Better Java -- to teach you how to write a modern Java program

    Better Java -- to teach you how to write a modern Java


    Java is currently the most popular in the worldprogrammingOne of the language, but not everyone is willing to use it.However, Java is actually a decent language, also especially since Java 8 officially released, so I decided to list down some of my practice, libraries, and tools for your reference.

    Style (Style)

    Traditionally, Java is used in lengthy JavaBean way to define a data object, new style may be more clear and ensure accuracy.

    User-defined Structs (structure)

    Programmers in the programming is the most common operation in data transmission, the traditional way is to javabeans, as shown below:

    public class DataHolder { private String data; public DataHolder() { } public void setData(String data) { = data; } public String

    getData() { return; } }

    But this way is tedious and waste of resources, even if your editor should be able to automatically generate the code.As an alternative, I would rather choose to use a C structure styles in the style to write the container data:

    public class DataHolder { public final String data; public DataHolder(String data) { = data; } }

    This way can make code almost half the number of rows, in addition, this class is immutable classes, so in some cases we can rest assured to use it.Is if you want to be able to use a Map or a List of these structures to store objects and makes changes a little bit more simple, can use ImmutableMap or ImmutableList, this chapter discussed below. Builder pattern

    If you have a data structure is more complex, can consider to use the following Builder pattern.Builder patterns in the data class defines a subclass constructor, using state variable, but becomes an irreversible after once created:

    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)

    { = data; return this; } public Builder num(int num) { this.num = num; return this; } public ComplicatedDataHolder build() { return new ComplicatedDataHolder(data, num); // etc } } }

    Then you can follow such as the use of:

    final ComplicatedDataHolder cdh = new ComplicatedDataHolder.Builder() .data("set this") .num(523) .build();

    Dependency injection (di)

    Dependency injection more from belongs to the category of software engineering, rather than the category of Java, but the best way to write testable software is the use of dependency injection.Because the Java strongly recommend the methods of OO design, in order to make the software has good testability, can go to use dependency injection.

    The most classic in the field of Java, DI framework is the Spring, it offers based on code injection and injection mode based on the XML configuration.But the Spring is a bit complicated, if simple just want to use dependency injection this function, can choose Google and SquareDaggerLibrary or Google 'sGuice.

    Avoid a null pointer

    As far as possible avoid using null pointer.Especially in the case of may return a collection of empty must return a collection of content is empty rather than a null.If you are using Java 8, you can use the new Optional type to avoid possible null Pointers: public class FooWidget { private final String data; private final Optional bar; public FooWidget(String data) { this(data, Optional.empty()); } public FooWidget(String data, Optional bar) { = data; = bar; } public Optional getBar() { return bar; } }

    According to the above code can know that the data returned will surely not null type, but is not necessarily present in the bar.

    final Optional fooWidget = maybeGetFooWidget(); final Baz baz =

    fooWidget.flatMap(FooWidget::getBar) .flatMap(BarWidget::getBaz) .orElse(defaultBaz);

    Immutable - by - the default (default Immutable)

    ; java-advantages-of-of-immutable-objects-in-examples

    Unless you have special reason, variables, classes, and should set the default setting is immutable.The variable type can use the final key to set the immutability: 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

    This way for variable operation can be ensured fooWidget is not accidental change point, the final keyword can be applied to the if - else code block and a try-catch block.For collection types, and should in any permission to use

    GuavaImmutableMap,ImmutableListOr,ImmutableSetClass.They all contain the constructor type, you can use the Builder for dynamically constructed eventually call the build method is set to the immutable.

    For the class, you can set its member variables for final type to become immutable type.In addition, can also set the class itself to final type to ensure that its not can be extended or set to the variable type.

    Get lots of Util Classes (Avoid using a large number of tools)

    A do not pay attention, you will find yourself wrote more than N Util class, such as: public class MiscUtil { public static String frobnicateString(String base, int times) { // ... etc } public static void throwIfCondition(boolean condition, String msg) { // ... etc } }

    These classes look very useful, because they do not belong to any logic module, so you can code reuse as much as possible.The so-called drug toxicity is, however, in the program should take these kind of place where they belong to, or the default method using Java 8 add interface to set up some common methods, its usage is as follows:

    public interface Thrower { default void throwIfCondition(boolean condition, String msg) { // ... } default void throwAorB(Throwable a, Throwable b, boolean throwA) { // ... } }

    So everyone classes need to use these interfaces can be customized.


    Formatting itself is no less important programming itself, a lot of good programmers will spend the time of day to add Spaces to the if block so as to make the code looks more neat.If you need a complete code format guidelines, you can refer to Google'sGoogle's Java Style, especially among themProgramming PracticesVery meaningful.


    Add the code for you JavaDoc is also very important, you can refer to the sample:using examples


    Java 8 provides a very Nice Stream API, you can use the following method: final List filtered = .filter(s -> s.startsWith("s")) .map(s -> s.toUpperCase()) .collect(Collectors.toList());

    Instead of:

    final List filtered = new ArrayList<>(); for (String str : list) { if (str.startsWith("s") { filtered.add(str.toUpperCase()); } }

    It will help you write more high readability, fluent code.

    Deploying (deployment)

    Some Java code may require a certain skill, at present in general deployment of Java there are two main ways: use a framework or a localized scalable framework.

    Frameworks (framework)

    Framework is a Java code you deploy a way very well, and there the better choiceDropwizardwithSpring Boot.The other is also a good choice.


    Maven is a very good Java compilation and dependency management tool, through the following ways can be convenient to add Maven dependencies: some-artifact

    About the specific use Maven can refer to the author of the rest of the article Dependence as Convergence (Convergence) rely on

    A great deal of charm in Java is to have a large number of third-party libraries available for reference, it is necessary to put all used API or SDK in Maven that last.But tend to be interdependent between all kinds of libraries, such as:

    Foo library depends on Bar library v1.0 Widget library depends on Bar library v0.9

    usingMaven dependency convergence pluginAt compile time, the alarm has a dependency on different versions, and in general, can be dealt with in the following way:

    1. In the dependenceManagement piece of choosing a specific version.

    2. In the Foo or Widget dependency using Exclude remove the Bar.

    Continuous Integration (ci)

    In large projects, often need some continuous integration tool to continuously based on git build test version, one of themAnsibleIs a good choice.


    Possible Java's best attributes is its extension libraries, this section lists the part on the

    extension of the library.

    The characteristics of Missing the Features (lost)

    Apache Commons

    The Apache Commons projectContains a list of commonly used libraries.

    ; Commons Codec includes plenty of useful method of encoding and decoding.

    ; Commons Lang contains a large number of string processing and character coding method.

    ; Commons IO contains a large number of documents related operations.It

    hasFileUtils.copyDirectory,FileUtils.writeStringToFile,IOUtils.readLinesand much more. Guava

    Guavais Google's excellent here's-what-Java-is-missing library. Gson

    Google'sGsonlibrary 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. TheGson user guidehas many more examples.

    Java Tuples

    The Java standard library has failed to provide the Tuples related data structure is a great pity.Fortunately,Java tuplesFilled the blank of the project:

    Pair func(String input) { // something... return

    Pair.with(stringResult, intResult); }


    LombokIs a very interesting class library, by annotations can be allowed to reduce the redundancy of the existence of Java code, such as the following common Getter/Setter code features:

    public class Foo { @Getter @Setter private int var; }

    Now, so to write:

    final Foo foo = new Foo(); foo.setVar(5);

    Play framework

    Good alternatives :JerseyorSparkwillbe very familiar. It works especially well with Java 8.


    There are a lot of Java logging solutions out there. My favorite isSLF4Jbecause 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.

    Thetwo-page manualis pretty much all you'll need to getstarted.


    I dislike heavy ORM frameworks because I like SQL. So I wrote a lot ofJDBC templatesand it was sort of hard to maintain.jOOQis amuch better solution.

    It lets you write SQL in Java in a type safe way:

    // Typesafely execute the SQL statement directly with jOOQ ResultString>> result =, 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 theDAOpattern, you can make database access a breeze.


jUnit 4

    jUnitneeds 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,rulesto stop you from writingso much boilerplate,theoriesto randomly test certain code,andassumptions.


    If 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.

    jMockis 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 that dep '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 atest fixtureand put assertIsSatisfied in an @After fixture.


    Do you ever do this with jUnit?

    final List result = 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.AssertJsolves 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?


    IntelliJ IDEA

    Good alternatives :EclipseandNetbeans

    The best Java IDE isIntelliJ 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. Chronon

    One of my favorite features of GDB 7 was the ability to travel back in timewhen debugging. This is possible with theChronon 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.


    Continuous 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 whatJRebeldoes. 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 Framework

    Java's type system is pretty weak. It doesn't differentiate between Stringsand Strings that are actually regular expressions, nor does it do any. However,the Checker Frameworkdoes this and more.

    It uses annotations like @Nullable to check types. You can even defineyour own annotationsto make the static analysis done evenmore powerful.

    Eclipse Memory Analyzer

    Memory leaks happen, even in Java. Luckily, there are tools for that. The besttool I've used to fix these is theEclipse 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 (resource)

    Books (Books)

    ; Effective Java

    ; [Java Concurrency in Practice

Report this document

For any questions or suggestions please email