简体   繁体   中英

Type inference in Java 7, When and why should it be used?

@Test
public void TypeInferenceTest() {
    inference();
    uncheckedAssignment();
    explicit();
}

private void inference() {
    ArrayList<String> strings = new ArrayList<>();
    strings.add("abc");
    String s = strings.get(0);

    assertThat(s, is("abc"));
}

private void uncheckedAssignment() {
    ArrayList<String> strings = new ArrayList();
    strings.add("abc");
    String s = strings.get(0);

    assertThat(s, is("abc"));
}

private void explicit() {
    ArrayList<String> strings = new ArrayList<String>();
    strings.add("abc");
    String s = strings.get(0);

    assertThat(s, is("abc"));
}

The code above used three ways to instantiate a list: type inference, open generic type and closed generic type.

But if I decompile the generated bytecode using JD-GUI, this is the result:

  @Test
  public void TypeInferenceTest() {
    inference();
    uncheckedAssignment();
    explicit();
  }

  private void inference() {
    ArrayList strings = new ArrayList();
    strings.add("abc");
    String s = (String)strings.get(0);

    Assert.assertThat(s, Matchers.is("abc"));
  }

  private void uncheckedAssignment() {
    ArrayList strings = new ArrayList();
    strings.add("abc");
    String s = (String)strings.get(0);

    Assert.assertThat(s, Matchers.is("abc"));
  }

  private void explicit() {
    ArrayList strings = new ArrayList();
    strings.add("abc");
    String s = (String)strings.get(0);

    Assert.assertThat(s, Matchers.is("abc"));
  }

Looks like they generated the same bytebote.

So when and why should we use type inference instead of the other two?

Others have covered why it generates the same code. So, to answer the actual question - the short answer is to prefer this:

   ArrayList<String> strings = new ArrayList<>();

Because it's briefer than this, while conveying the same meaning (to humans and to the compiler):

   ArrayList<String> strings = new ArrayList<String>();

But avoids unnecessarily causing a warning like this:

   ArrayList<String> strings = new ArrayList();

As for being briefer, this:

   ArrayList<String> strings = new ArrayList<String>();

Isn't that bad, and there's no real harm in typing it out (after all, we've all been doing it for years). But if you wind up writing something like:

   Map<String, Map<Widget<Spork>, Bar<Llama>>> myMap = new HashMap<>();

It becomes far more tedious if you have to type this twice:

<String, Map<Widget<Spork>, Bar<Llama>>>

The type inference is just a shortcut for an unnecessarily long way of instantiating paremeterized types. Generics are still implemented by type-erasure, so your bytecode will only have the raw types.

As your example demonstrates, Java generics are implemented by type erasure and generic code is no different from non-generic code at runtime. This makes generics purely a compile-time feature - added type safety for the benefit of the developer.

In the case of your example, there's really no difference between new ArrayList() , new ArrayList<String>() , and new ArrayList<>() - all that matters is the type of the variable it gets assigned to. Using new ArrayList() is still discouraged because it looks like legacy code and may confuse another developer. It will cause compilers/IDEs to show the standard "raw types" warning and is therefore distracting. But that's it, for a no-arg constructor at least.

However, providing a type argument or using type inference really is important for any constructor that takes generic arguments. Consider this example:

Collection<Integer> ints = Arrays.asList(1, 2, 3);

List<String> strings1 = new ArrayList(ints);         // compiles!
List<String> strings2 = new ArrayList<String>(ints); // won't compile
List<String> strings3 = new ArrayList<>(ints);       // won't compile

As for why to use new ArrayList<>(ints) over new ArrayList<String>(ints) , well, it's less verbose and avoids repeating the generic type already specified in the variable being assigned to.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM