import org.eclipse.jdt.annotations.*;
@NonNullByDefault
public class MyClass
{
...
}Object myMethod( Collection parameter )
{
if ( ( parameter != null )
|| ( parameter.size() != 0 ) )
{ return
doSomethingThatMayReturnNull(
parameter );
} else { return null; }
}@NonNull Optional<TypedResult>
myMethod( @Nullable final
Iterable parameter )
{
if ( parameter == null )
return Optional.absent();
return Optional.fromNullable(
doSomethingThatMayReturnNull(
parameter.first() ) );
}
@NonNull Optional<TypedResult>
myBetterMethod(
@NonNull final Optional<TypedParameter>
parameterIfAny )
{
if ( ! parameterIfAny.isPresent() )
return Optional.absent();
return doSomethingOptionalResult(
parameterIfAny.get() ) );
}import org.eclipse.jdt.annotations.NonNullByDefault;
import org.eclipse.jdt.annotations.Nullable;
@NonNullByDefault
public class MyClass
{
Optional<TypedResult>
myMethod( @Nullable final parameter )
{
if ( Strings
.isEmptyOrNull( parameter ) )
return Optional.absent();
return Optional.fromNullable(
doSomethingThatMayReturnNull(
parameter ) );
}
Optional<TypedResult>
myBetterMethod(
final Optional<TypedParameter>
parameterIfAny )
{
if ( ! parameterIfAny.isPresent() )
return Optional.absent();
return doSomethingOptionalResult(
parameterIfAny.get() ) );
}
}if ( parameter != null )
return
( parameter.size() > 0 )
? parameter.get(0)
: nulllocal = Optional.fromNullable( parameter );
return local;// When you have to return something non-null
// but a proper result isn't available
return Optional.absent();
// When you need to ask and use something that
// might be null and a good default is available
Optional<SomeType> result = Optional.fromNullable(
getSomeInstance( arguments ) );
return result.or( aGoodDefault );
// When you need to return an iterable collection
// that might be empty because something wasn't
// available
return FluentIterable.from(
something.isPresent()
? ImmutableList.of( something.get() )
: new ImmutableList.Builder<SomeType>()
.build();
final MyWidget myWidget =
new MyWidget( argA,
argB, ... argZ );
final MySprocket mySprocket =
new MySprocket();
mySprocket.setA( argA );
mySprocket.setB( argB );
...
mySprocket.setZ( argZ );// flexible subset and order
final MyWidget myWidget =
Widget.Builder()
.setA( argA )
.setM( argM )
.setB( argB )
.build();
// fluent narrative
final MyWidget aWidget =
Widget.Builder()
.from( materials )
.in( store )
.assemble( parts )
.build();
aWidget.useIt();Offer Interfaces that state the methods of a service object that are accessible regardless of the particular compiler-time class type or run-time instance type.
Interfaces specify the API contract: name, arguments, returns, exceptions, and nullness
Offer Abstract Classes which implement the Interface that provide harmless or noop behavior for the interface methods.
When a method requires instance properties, don't implement a default method.
Keep the Abstract Class free of instance state.
@NonNullByDefault
public interface Ducky
{
public Ducky quack( final DuckEdible food );
public Ducky fly( final Direction away );
...
}
@NonNullByDefault
public abstract class DuckDefault implements Ducky
{
@Override
public Ducky quack( final DuckEdible food )
{
return this;
}
@Override
public Ducky fly( final Direction away )
{
return this;
}
}
@NonNullByDefault
public class CatDuck extends DuckDefault
{
@Override Ducky quack( final DuckEdible food )
{
meow();
return this;
}
}
final Ducky someDuck = DuckFactory.species()
.with( catNature )
.with( duckNature )
.build();
someDuck.quack( someFood ); // yields meow()
Neither Iterables nor FluentIterables are Collections.
They specify a deferred-execution transformation pipeline.
The filters and transforms are performed when client-code calls the next() (e.g. *.first().get()) method.
They do nothing to the underlying collection when specified in the program logic.
Force the filtering and transforming by serializing the iterator (e.g. iterator.toList())
SomeResult result =
methodWithNumerousArgs(
argA,
new ArgB(),
argC.getC()
...
argZ );SomeResult result =
oneInOneOut( argA )
.noSideEffect( argB )
.easilyUnderstood( argC )
...
.simple( argZ );final FluentIterable<TypeA> Ainstances =
FluentIterable.from( providerOfAs );
final FluentIterable<TypeC> Cinstances =
Ainstances
.filter( unwantedAs() )
.filter( wantedAs() )
.transform( fromAsToBs() )
.filter( unwantedBs() )
.transform( fromBsToCs() )
.filter( wantedCs() )
// perform the first get from the providerOfAs
// and transform that A into a B then into a C
final TypeC someC = Cinstances.first().get();