loading...

Effective Java! Favor Generic Methods

kylec32 profile image Kyle Carter ・3 min read

Effective Java Review (36 Part Series)

1) Effective Java Tuesday! Let's Consider Static Factory Methods 2) Effective Java Tuesday! The Builder Pattern! 3 ... 34 3) Effective Java Tuesday! Singletons! 4) Effective Java Tuesday! Utility Classes! 5) Effective Java Tuesday! Prefer Dependency Injection! 6) Effective Java Tuesday! Avoid Creating Unnecessary Objects! 7) Effective Java Tuesday! Don't Leak Object References! 8) Effective Java Tuesday! Avoid Finalizers and Cleaners! 9) Effective Java Tuesday! Prefer try-with-resources 10) Effective Java Tuesday! Obey the `equals` contract 11) Effective Java Tuesday! Obey the `hashCode` contract 12) Effective Java Tuesday! Override `toString` 13) Effective Java Tuesday! Override `clone` judiciously 14) Effective Java Tuesday! Consider Implementing `Comparable` 15) Effective Java Tuesday! Minimize the Accessibility of Classes and Member 16) Effective Java Tuesday! In Public Classes, Use Accessors, Not Public Fields 17) Effective Java Tuesday! Minimize Mutability 18) Effective Java Tuesday! Favor Composition Over Inheritance 19) Effective Java Tuesday! Design and Document Classes for Inheritance or Else Prohibit It. 20) Effective Java Tuesday! Prefer Interfaces to Abstract Classes 21) Effective Java! Design Interfaces for Posterity 22) Effective Java! Use Interfaces Only to Define Types 23) Effective Java! Prefer Class Hierarchies to Tagged Classes 24) Effective Java! Favor Static Members Classes over Non-Static 25) Effective Java! Limit Source Files to a Single Top-Level Class 26) Effective Java! Don't Use Raw Types 27) Effective Java! Elminate Unchecked Warnings 28) Effective Java! Prefer Lists to Array 29) Effective Java! Favor Generic Types 30) Effective Java! Favor Generic Methods 31) Effective Java! Use Bounded Wildcards to Increase API Flexibility 32) Effective Java! Combine Generics and Varargs Judiciously 33) Effective Java! Consider Typesafe Hetergenous Containers 34) Effective Java! Use Enums Instead of int Constants 35) Effective Java! Use Instance Fields Instead of Ordinals 36) Effective Java! Use EnumSet Instead of Bit Fields

This week's chapter continues where our last chapter left off. Whereas last week we talked about generic types, this week we discuss generic methods. As it was with making generic types, one of the main goals of using generic methods is to improve the readability and safety of the code which often can be realized by noticing that there are no casts and no unchecked warnings at compile time. So let's look at some examples.

Let's look at a method that doesn't use generics first:

public static Set union(Set s1, Set s2) {
  Set result = new HashSet(s1);
  result.addAll(s2);
  return result;
}

While the above code works it does throw warnings at compile time as it can't enforce type safety at compile time. The fix is slightly simple. We add a type parameter list which declares the type parameters to be used between the method's modifiers and the return type. From there we can use the type parameter throughout the function. Let's look at our above function in a generic way.

public static <E> Set<E> union(Set<E> s1, Set<E> s2) {
  Set<E> result = new HashSet<>(s1);
  result.addAll(s2);
  return result;
}

It's as easy as that, we now have gotten rid of our warnings as well as provided better type safety. A current limitation of the union function is that the type of the three sets must be exactly the same, we can loosen this requirement using bounded wildcard types which we will get into in the next chapter.

Another capability that we have with generic methods is creating functions that provide typed generic immutable objects. Because generics are implemented via type erasure we can have an immutable class that serves all types. This is one benefit of type erasure. We can see examples of these in the JRE with methods such as Collections.reverseOrder and Collections.emptySet. Let's look at an example of this. Let's imagine we want to implement our own identityFunction. We of course shouldn't do this because it already exists but it is educational to consider.

private static UnaryOperator<Object> IDENTITY_FN = (t) -> t;

@SuppressWarnings("unchecked")
public static <T> UnaryOperator<T> identityFunction() {
  return (UnaryOperator<T>) IDENTITY_FN;
}

We do need to do a cast but we know it's safe due to no actions actually happening on the object in question so we suppress the warnings.

The final thing for us to consider is something called a recursive type bound. What these are is when a type parameter is bounded by some expression involving the type itself. This sounds more confusing than it is. A common place this can be seen used is in connection with the Comparable<T> interface. The type T of Comparable denotes to what type the object can be compared. In practice most types simply are comparable with themselves thus String implements Comparable<String> and Integer implements Comparable<Integer> and so on. So as an example of a recursive type bound let's look at a function that finds the maximum value in a collection.

public static <E extends Comparable<E>> Optional<E> max(Collection<E> c) {
  E result = null;
  for (E e : c) {
    if (result == null || e.compareTo(result) > 0) {
      result = Objects.requireNonNull(e);
    }
  }
  return Optional.ofNullable(result);
}

The type parameter can be read as "any type E that can be compared to itself" which ends up being exactly what we are looking for. While recursive type bounds can get fairly complex hopefully you can see how these can be useful.

Overall, preferring generic methods and types leads to safer code as well as easier to use code. We should do what we can to make our code warning and cast free.

Effective Java Review (36 Part Series)

1) Effective Java Tuesday! Let's Consider Static Factory Methods 2) Effective Java Tuesday! The Builder Pattern! 3 ... 34 3) Effective Java Tuesday! Singletons! 4) Effective Java Tuesday! Utility Classes! 5) Effective Java Tuesday! Prefer Dependency Injection! 6) Effective Java Tuesday! Avoid Creating Unnecessary Objects! 7) Effective Java Tuesday! Don't Leak Object References! 8) Effective Java Tuesday! Avoid Finalizers and Cleaners! 9) Effective Java Tuesday! Prefer try-with-resources 10) Effective Java Tuesday! Obey the `equals` contract 11) Effective Java Tuesday! Obey the `hashCode` contract 12) Effective Java Tuesday! Override `toString` 13) Effective Java Tuesday! Override `clone` judiciously 14) Effective Java Tuesday! Consider Implementing `Comparable` 15) Effective Java Tuesday! Minimize the Accessibility of Classes and Member 16) Effective Java Tuesday! In Public Classes, Use Accessors, Not Public Fields 17) Effective Java Tuesday! Minimize Mutability 18) Effective Java Tuesday! Favor Composition Over Inheritance 19) Effective Java Tuesday! Design and Document Classes for Inheritance or Else Prohibit It. 20) Effective Java Tuesday! Prefer Interfaces to Abstract Classes 21) Effective Java! Design Interfaces for Posterity 22) Effective Java! Use Interfaces Only to Define Types 23) Effective Java! Prefer Class Hierarchies to Tagged Classes 24) Effective Java! Favor Static Members Classes over Non-Static 25) Effective Java! Limit Source Files to a Single Top-Level Class 26) Effective Java! Don't Use Raw Types 27) Effective Java! Elminate Unchecked Warnings 28) Effective Java! Prefer Lists to Array 29) Effective Java! Favor Generic Types 30) Effective Java! Favor Generic Methods 31) Effective Java! Use Bounded Wildcards to Increase API Flexibility 32) Effective Java! Combine Generics and Varargs Judiciously 33) Effective Java! Consider Typesafe Hetergenous Containers 34) Effective Java! Use Enums Instead of int Constants 35) Effective Java! Use Instance Fields Instead of Ordinals 36) Effective Java! Use EnumSet Instead of Bit Fields

Posted on by:

kylec32 profile

Kyle Carter

@kylec32

Backend Architect at MasterControl

Discussion

markdown guide
 

Also take a look at core java interview questions 👉
tutorialsmate.com/2020/06/core-jav...
More than 100 questions in the article. ✅