8

I had an interview test and saw the following code:

EDIT:

public class TestValue {
    private Value<SomeValue> defaultValue;

    @Test
    public void Empty_Value_Has_No_Value() {
        Assert.assertFalse(Value.<SomeValue> createEmptyValue()
            .hasValue());
    }

    @Test
    public void Default_Value_IsEmpty() {
        Assert.assertEquals(Value.<SomeValue> createEmptyValue(),
            defaultValue);
    }

    @Test
    public void Non_Empty_Value_Has_Value() {
        Assert.assertTrue(new Value<SomeValue>(true, new SomeValue())
            .hasValue());
    }
}

I had never seen Java generic like

Value.<SomeValue>

The test is to implement Value class with the given unit test code above.

I tried to figure out the Value method signature below (need implementation):

public interface Value<T> {

    public boolean hasValue();
    public Value<T> createEmptyValue();
}

Any one know, please help?

Thank you

EDIT: Should be like this according to answers below @marlon

public class Value<T> {

    public boolean hasValue(){}
    public static <M> Value<M> createEmptyValue(){}; //need <M>
}

The key syntax to know:

Value.<SomeValue>  //ClassName.<Type>method

is way to invoke static method of a class with parameterized argument.

EDIT: according to @snipes83, syntax to invoke non-static method of a class with parameterized argument.

SomeObject.<Type>method
Eric
  • 1,031
  • 4
  • 14
  • 29
  • 3
    It could be a typo? `Value.createEmptyValue()` makes more sense. – Felix Glas Jun 05 '13 at 01:31
  • Was that a whiteboard coding? Maybe it is only a reference to a type which can be anything by definition, just meaning they provide a value of that type, but the type doesn't really matter? That's what I would assume in that case. – clement Jun 05 '13 at 01:34
  • Yeah; kind of curious myself. – Edward Falk Jun 05 '13 at 01:34
  • 1
    I made some research and there are actually cases where you need to use the `SomeObject.method`-syntax without the method beeing static. See my answer for an explanation. – Felix Glas Jun 05 '13 at 02:55
  • The `.method` syntax has nothing to do with the method being static or the type having a type argument. It **only** aplies if the *method* has a type argument (that can not be inferred)! – Joachim Sauer Jun 05 '13 at 14:57

4 Answers4

6

Value.<SomeValue> it's the way generics are represented for methods.

Using Google Guava's Optional as an example:

Optional<String> email = Optional.<String>of(strEmail);

See Generic Types - Invoking generic methods

Since interfaces cannot declare static methods (shame on you java), just declare your method as static and forget about the interface, like this:

class Value<T> {

    public static <T> Value<T> createEmptyValue(){
        return null;
    }
}
Marlon Bernardes
  • 13,265
  • 7
  • 37
  • 44
  • Do you mean createEmptyValue() in the above should be static? like public static Value createEmptyValue(); //compile error: Cannot make a static reference to the non-static type T – Eric Jun 05 '13 at 02:07
  • 1
    @Eric: Almost, but you'd parameterize the static method on ``, like `public static Value createEmptyValue() {...}`. As the compiler is pointing out, you can't reference a non-static parameter T on the class from a static method. – Ryan Stewart Jun 05 '13 at 02:14
  • @Eric,Ryan Stewart Updated my answer to reflect your comments. – Marlon Bernardes Jun 05 '13 at 02:18
  • 3
    Static has nothing to do with it, although in this case it appears to be a statics method. Both instance and static methods may be typed – Bohemian Jun 05 '13 at 03:57
3

Look at the class Test with the method getEmptyList below:

public class Test {
    public <T> List<T> getEmptyList() {
        return new ArrayList<T>();
    }
}

It returns an empty List containing objects of type T.

If you use Test like this

Test t = new Test();
List<Integer> list = t.getEmptyList();

Then the type inference mechanism is able to infer the type parameter based on the variable type.

However if you need to use the return value of getEmptyList within a method invocation expression like in the following example where the method printList expects a single argument of type List<Integer>, then the type can not be infered from any variable type.

public void printList(List<Integer> list) {
    for (int i : list) {
        System.out.print(i);
    }
}

printList(t.getEmptyList()); // This will FAIL.

In this case you need to specify the type using the following:

printList(t.<Integer>getEmptyList());
Felix Glas
  • 15,065
  • 7
  • 53
  • 82
2

1) This is how generic methods are invoked. Refer >> http://docs.oracle.com/javase/tutorial/java/generics/methods.html

2) <SomeValue> in Value.<SomeValue> is optional. Compiler can infer the type. This is called TypeInference. Refer >> http://docs.oracle.com/javase/tutorial/java/generics/genTypeInference.html

Answer Updated:

3) Value.<SomeValue> createEmptyValue() is right and Value.<SomeValue>createEmptyValue() is right too. Both ways are legal. Just tested it. Didn't notice before.

Ravi Trivedi
  • 2,340
  • 2
  • 14
  • 20
  • As it is currently written, the only difference between the two examples given in number (3) is the whitespace; could you elaborate on the supposed difference? – wchargin Jun 05 '13 at 02:24
  • Awww, just tested it. It does work. Damn it, didn't notice before. – Ravi Trivedi Jun 05 '13 at 02:27
1

Although Value is itself obviously typed ( based on the instance variable type of Value<SomeValue>), the static createEmptyValue() method is also typed.

A reasonable assumption, if naming conventions have been adhered to, is that SomeValue extends (or implements) Value.

Although there us no one correct answer, a likely possibility for the signature of Value is:

public class Value<T extend Value> {
    public static <V extends Value> V createEmptyValue() {
        // some impl
    }
}
Bohemian
  • 412,405
  • 93
  • 575
  • 722