How to optimize Java 8 Optional Objects?

Is there an efficient way to execute upstream when using the Advanced object. Here is a sample code:

class A{} class B extends A{} B func(){ //do something return new B(); } Optional<B> func2(){ //do something return Optional.of(new B()); } main() { A a = func(); // Upcasting works fine B b = func(); // Upcasting works fine Optional<B> b = func2(); // 1. Upcasting works fine Optional<A> a = func2(); // 2. Upcasting would not work } 

(2.) gives an error. I can solve this by creating another function.

But is there an efficient way so func2 () can be used for both (1.) and (2.)?

+5
source share
3 answers

I would write a method like this:

 @SuppressWarnings("unchecked") // Safe. See below. static <T> Optional<T> copyOf(Optional<? extends T> opt) { return (Optional<T>) opt; } 

(If you don't like the name copyOf , see my comment on Guava ImmutableList below)

This is very effective in terms of speed of execution: at startup, the execution time of the casting ends:

 static <T> java.util.Optional<T> copyOf(java.util.Optional<? extends T>); Code: 0: aload_0 # Read the parameter. 1: areturn # Return the parameter. 

therefore, the only cost is the cost of invoking the method; This is easy to do using JIT.

Then you can call:

 Optional<A> a = copyOf(func2()); 

This is safe because Optional has the following property: it is guaranteed not to have any state changes caused by setter methods using parameters that depend on a variable of type T Phew Pretty sip. I will make it more specific.

Because Optional

  • it does not have setter methods (of any type, but, as a rule, there are no parameters that accept parameters of type T , SomeGenericType<T> , etc.)
  • is final (so you cannot subclass it to add a setter to break the previous point)

there is nothing that can be done for the value stored in Optional<T> (or its absence), which will make it not an instance of T (or its absence).

And since each instance of T also an instance of its superclasses, there is nothing unsafe about it:

 SuperclassOfT s = optionalOfT.get(); 

As such, this method is type safe (it will fail if you call it optional optional, but it is not a type error).

You will find similar code in Guava ImmutableList.copyOf (the inspiration for calling it “ copyOf ” above, although this is not really a copy). There are setter methods (for example, add ), but these methods immediately throw UnsupportedOperationException s and thus do not affect the state of the list.


Please note that while immutable types have the necessary properties described above to make such a safe cast, the type does not have to be immutable for safe execution.

For example, you might have an ErasableOptional<T> type that has an erase() method on it that, when called, converts the "real" value to a "missing" value (that is, get() no longer runs), It would be safe use such an instance for ErasableOptional<SupertypeOfT> , because the value is either T or absent; you cannot make it non-instance SupertypeOfT or be absent.

+5
source

You can try using the matching function:

 Optional<A> oa = func2().map(v -> (A) v); 

Note that you really don't need to put (A) , but that makes things a little easier.

+3
source

Optional, quote from java doc:

a container object that may or may not contain a non-zero value .... Additional methods that depend on the presence or absence (for example, orElse () ...

As we can see, the additional container uses a common type to determine which object to contain.

 Optional <T> 

so you can do this:

 Optional<? extends A> a = func2(); // 2. Upcasting Will work :) 

and to access an optional object, an object of type A:

 a.get(); 
+2
source

Source: https://habr.com/ru/post/1269381/


All Articles