Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Odd method call in java using a dot operator to access a generic list

I came across some advanced java code (advanced for me :) ) I need help understanding.

In a class there is a nested class as below:

private final class CoverageCRUDaoCallable implements
        Callable<List<ClientCoverageCRU>>
{
    private final long oid;
    private final long sourceContextId;

    private CoverageCRUDaoCallable(long oid, long sourceContextId)
    {
        this.oid = oid;
        this.sourceContextId = sourceContextId;
    }

    @Override
    public List<ClientCoverageCRU> call() throws Exception
    {
        return coverageCRUDao.getCoverageCRUData(oid, sourceContextId);
    }
}

Later in the outer class, there is an instance of the callable class being created. I have no idea what this is:

ConnectionHelper.<List<ClientCoverageCRU>> tryExecute(coverageCRUDaoCallable);

It doesn't look like java syntax to me. Could you please elaborate what's going on in this cryptic syntax? You can see it being used below in the code excerpt.

CoverageCRUDaoCallable coverageCRUDaoCallable = new CoverageCRUDaoCallable(
        dalClient.getOid(), sourceContextId);

// use Connection helper to make coverageCRUDao call.
List<ClientCoverageCRU> coverageCRUList = ConnectionHelper
        .<List<ClientCoverageCRU>> tryExecute(coverageCRUDaoCallable);

EDITED added the ConnectionHelper class.

public class ConnectionHelper<T>
{
    private static final Logger logger =
        LoggerFactory.getLogger(ConnectionHelper.class);

    private static final int    CONNECTION_RETRIES = 3;

    private static final int    MIN_TIMEOUT        = 100;

    public static <T> T tryExecute(Callable<T> command)
    { 
        T returnValue = null;
        long delay = 0;

        for (int retry = 0; retry < CONNECTION_RETRIES; retry++)
        { 
            try
            { 
                // Sleep before retry
                Thread.sleep(delay);

                if (retry != 0)
                {
                    logger.info("Connection retry #"+ retry);
                }

                // make the actual connection call
                returnValue = command.call();
                break;

            } 
            catch (Exception e)
            {
                Throwable cause = e.getCause();
                if (retry == CONNECTION_RETRIES - 1)
                {
                    logger.info("Connection retries have exhausted. Not trying "                        
                            + "to connect any more.");

                    throw new RuntimeException(cause);
                }

                // Delay increased exponentially with every retry.
                delay = (long) (MIN_TIMEOUT * Math.pow(2, retry));

                String origCause = ExceptionUtils.getRootCauseMessage(e);

                logger.info("Connection retry #" + (retry + 1)
                        + " scheduled in " + delay + " msec due to "
                        + origCause);
                        + origCause);
            }
        }
        return returnValue;
    }
like image 689
Horse Voice Avatar asked Jan 23 '14 02:01

Horse Voice


People also ask

What is the dot operator called in Java?

Dot operator is a syntactic element, i.e. it denotes the separation between class and package, method and class, variable and reference variable. It can also be called as separator operator.

What does the dot operator do in Java?

It is also known as separator or period or member operator. It is used to separate a variable and method from a reference variable. It is also used to access classes and sub-packages from a package. It is also used to access the member of a package or a class.

What is the use of dot operator give an example?

(dot) operator is used to access class, structure, or union members. The member is specified by a postfix expression, followed by a . (dot) operator, followed by a possibly qualified identifier or a pseudo-destructor name. (A pseudo-destructor is a destructor of a nonclass type.)


3 Answers

You more often think of classes as being generic, but methods can be generic too. A common example is Arrays.asList.

Most of the time, you don't have to use the syntax with angle brackets <...>, even when you're invoking a generic method, because this is the one place in which the Java compiler is actually capable of doing basic type inference in some circumstances. For example, the snippet given in the Arrays.asList documentation omits the type:

List<String> stooges = Arrays.asList("Larry", "Moe", "Curly");

But it's equivalent to this version in which the generic type is given explicitly:

List<String> stooges = Arrays.<String>asList("Larry", "Moe", "Curly");
like image 133
Chris Martin Avatar answered Nov 13 '22 18:11

Chris Martin


That is because, until Java 7, generics do not fully support target typing, so you need to help the compiler a little with what is called a type witness like in ConnectionHelper.<List<ClientCoverageCRU>>.

Note however that Java 8 significantly improves target typing and in your specific example the type witness is not required in Java 8.

like image 22
assylias Avatar answered Nov 13 '22 19:11

assylias


It's ugly, but valid.

Whatever ConnectionHelper is, it has a static tryExecute method that needs to infer a generic type.

Something like:

public static <T> T tryExecute() { ... }

Edit from updated Question: Java has type inference for generic types. The first <T> in the method signature signifies the type will be inferred when the method is called.

In your updated post you show tryExecute() defined to take a generic argument:

public static <T> T tryExecute(Callable<T> command)

This actually means the use of that syntax is completely redundant and unnecessary; T (the type) is inferred from the command being passed in which has to implement Callable<T>. The method is defined to return something of the inferred type T.

             Infer a type
               |
               v
public static <T> T tryExecute(Callable<T> command)
                  ^                     ^
                  |                     |
  <-return type--------------------------                           

In your example, coverageCRUDaoCallable has to be implementing Callable<List<ClientCoverageCRU>> because the method is returning List<ClientCoverageCRU>

In my example above you'd have to use the syntax you were asking about because nothing is being passed in from which to infer the type. T has to be explicitly provided via using ConnectionHelper.<List<ClientCoverageCRU>>tryExecute()

like image 3
Brian Roach Avatar answered Nov 13 '22 19:11

Brian Roach