Generic functions in Java - java

I am not very familiar with some of the generic syntax in Java.
I came across some code like this:
public static<T> T foo(T... a)
Can somebody explain what it means in a succinct way?
Does it mean foo() takes in an array of type T and returns type T?
Why isn't the syntax like this below?
public static T foo(T[] a)
I had a look at the Oracle docs but the example they have seems much easier to understand: Oracle Generics

Two things:
1) This is a varargs method, a method that takes a variable number of arguments. That is not the same as a method that takes an array (even though under the hoods it is implemented using an array).
You call this method as foo(a,b,c) (as opposed to foo(arrayWithABC)).
2) If you want to use the generic type placeholder T, you have to declare it. This is exactly what the first <T> does.
The difference between public static T foo(T a) and public static <T> T foo(T a) is that the latter introduced a "local" T for the scope of this method. That means "method returns an instance of whatever type parameter a has". In the first version, the T would need to be a type placeholder declared elsewhere (such as on the class as a whole), or a class name.
Since <T> is completely unrestricted you can pass anything. What the generics do is bind the return value to the same type. If you just had public static Object foo(Object a), you could pass in an Integer and get back a String. The T prevents that.
If you wanted to restrict the acceptable types, you could do public static <T extends Number> T foo(T a).

T... a
means variable number of T type objects arguments for the method whereas
T[] a
means a single argument of array of T objects

This means the type 'T' will match to any real type. Its like a wild-card type :)

Related

Why is the syntax of java generics the way it is

In the java docs, an example of the java generics is like this.
/**
* Generic version of the Box class.
* #param <T> the type of the value being boxed
*/
public class Box<T> {
// T stands for "Type"
private T t;
public void set(T t) { this.t = t; }
public T get() { return t; }
}
Why is the <T> right after Box. I know that T stands for the Type the user will use.
But if you look at the rest of the syntax, T always comes first.
For example in private T t; T comes before t.
In the methods get() and set(T t), we again see that T comes before the method name and not after the name of the object or method we are creating.
It is my understanding that a class such as Box is also an Object, so why don't we write:
public class T Box { //... }
Or, alternatively,
public <T> class Box { //... }
I would like to know this because it confuses me. Whenever I am writing a generic method, I have to go back to existing code to see which comes first so maybe if I knew why one has to come first and why the other has to come last I will not have to go back to my already existing code and use it as a reference.
T is called a type parameter, and it is very similar to a method parameter. In the description below, the word "class" also covers "interface", but using the common word "type" would be confusing.
You declare a method with a formal parameter like this:
void foo(Animal a)
You declare a generic class with a type parameter like this:
class Foo<A extends Animal>
Of course a is a value, a reference to an Animal instance, while A is a type, a compiler reference to a class.
a is called a parameter variable, and A is called a type variable.
You call the method like this:
foo(a)
You use the generic class like this:
Foo<Dog>
a is the method argument (sometimes called the actual parameter), and Dog is the generic type argument.
It is that similarity to method parameters that make the placement of generic type parameter intuitive to use, at least once you realize the similarity.
The placement of generic method type parameters is less intuitive, until you recognize that the type parameter should be defined before it's used, and the first possible use is the return type, so the type parameters are declared right before that:
<A extends Animal> A foo(A a)
Less obvious is on the method call, if the compiler cannot infer the type argument:
myobj.<Dog>foo(mydog)
But that's where they decided to put it, probably for code parsing reasons.
I know that T stands for the Type the user will use.
That's correct. Keep reminding yourself of that.
For example in private T t; T comes before t.
That's because T is the type. If it were an Integer, the line would look like private Integer t; and if it were a Boolean, then it would look like private Boolean t;. That's simply the syntax of Java: modifiers, then the type, then the variable name being declared.
In a generic, T (or whatever placeholder you want to use) is the placeholder for the type, inside that class, so you put a T instead of Integer or Boolean or whatever.
Box<T> is a type with parameter T in the same way that void box(int t) is method with parameter t. The angle brackets indicate type parameters, while the round parentheses indicate method parameters.
The T is a parameter of the class Box and nothing else, which is why it doesn't appear in angle brackets anywhere else.
The generic method syntax: <T> void box(T t); is a little harder to understand. box is not a type, so it doesn't take type parameters, and that's why the <T> doesn't come after box. There is no type in that declaration to attach it to. It probably goes before the method declaration so that it doesn't confuse the meaning of the rest of the declaration.
T is like a variable for a class/type.
Just replace all the Ts in your question with e.g. String or Integer etc. and you get regular Java Syntax.
E.g. private T foo(T t) becomes private String foo(String t)...

When is it acceptable to pass a Class<T> argument to a generic method?

Methods that are generic using the T parameter can for sure be handy. However, I am curious what the use of a generic method would be if you pass an argument such as Class<T> clazz to the method. I've come up with a case that maybe could be an possible use. Perhaps you only want to run a part of the method based on the type of class. For example:
/** load(File, Collection<T>, Class<T>)
* Creates an object T from an xml. It also prints the contents of the collection if T is a House object.
* #return T
* Throws Exception
*/
private static <T> T void load(File xml, Collection<T> t, Class<T> clazz) throws Exception{
T type = (T) Jaxb.unmarshalFile(xml.getAbsolutePath(), clazz); // This method accepts a class argument. Is there an alternative to passing the class here without "clazz"? How can I put "T" in replace of "clazz" here?
if (clazz == House.class) {
System.out.println(t.toString());
} else {
t.clear();
}
return T;
}
Is this an accepted practice? When is the Class<T> clazz argument useful with generic methods?
Is this an accepted practice?
Well, to me.. no not really. To me, it seems somewhat pointless when you can simply define some boundaries on the type of T. For example:
private static <T extends House> void load(Collection<T> t)
This will guarantee that either the object is of type House or of a subclass of House, but then again if you only want an instance of type House or it's subclasses, it should really just be:
private static void load(Collection<House> houses)
The idea of generics is to make a method or a class more malleable and extensible, so to me it seems counter-intuitive to start comparing class types in the method body, when the very notion of generics is to abstract away from such details.
I'd only pass class objects if the generic type could not be derived otherwise. In your case, the compiler should be able to infer T from the collection. To treat specific objects differently, I'd use polymorphism - e.g. House#something() and Other#something(), and just call anyObject.something().
I think it is acceptable but if it can be avoided then you should. Typically, if you can have different methods which accepts different type, then do it instead of one method which uses if clauses to do something different depending on the type of the parameter. You could also delegates to the class the operation you want to make specific for a given type.
In your case, you could simply test the type of each element of the collection using instanceof, to do what you need for the specific type. But it won't work if the list is empty.
A typical use is if you need to get the type to create it and you can find it from another way. For instance, Spring uses it to load a bean from its name:
<T> T getBean(Class<T> requiredType)
In that case, it cannot be avoided (without having to cast).
If the returned value or other parameters types are dependent or need to be equal, generics will add compile time checks, so that there's no need to cast to T.
Examples
<T> T createNewInstanceOfType(Class<T> type);
<T> void addValueToCollection(Collection<T> collection,T value);
<T> List<Class<? extends T>> findSubClassesInClasspath(Class<T> superType);
Raw types
It is still possible to defer a casting error until runtime (ClassCastException) with some casts, e.g. with implicit casts from non-generic (raw) types to generic ones:
List nonGenericList = new ArrayList();
nonGenericList.add(new Integer(42));
List<String> wreckedList = nonGenericList;
The compiler will generate a bunch of warnings, unless you suppress them with annotations or compiler settings.
Compiler Settings (Eclipse):
For example, the usage of raw types generates a warning per default, one can treat warnings as errors and even as fatal errors:
You would pass a Class<T> argument in generics if, and only if, you would pass a Class argument before generics. In other words, only if the Class object is used in some way. Generics serves as a compile-time type checking tool. However, what arguments you pass should be determined by the runtime logic of the program, and should be irrelevant of generics.
I haven't seen passing a Class object in order to check the runtime type of an object as a common use case for generics. If you're doing that, there's a good chance that there's a better way to set up your class structure.
What I have seen is if you need to create a new instance of the class in question, or otherwise use reflection. In that case you do have to pass the Class object, because Java cannot derive it at runtime thanks to type erasure.
In your case actually having the Generic parameter is not strictly needed.
Since the output of the function you are describing does not depend on the type of the input you might as well use wild cards.
private static void stuff(Collection<?> t){
Object next = t.iterator().next(); //this is ugly and inefficient though
if(next instanceof House){
System.out.print(next.toString());
}else{
t.clear();
}
}
The only time you should use generic parameter is when the type of the result of a function will be dependent of the type of the parameters.
You will need to pass the Class corresponding to the type when your code will need it; most of the time this happens when:
- You need to cast/type check objects to T
- There is serialization/deserialization involved.
- You cannot access any instance of T in your function and you cannot call the getClass() method when you need it.
Passing a Class on every generic function will result in you passing an unnecessary parameter most of the time, which is regarded as bad practice.
I answered a similar discussion in the past:
When to use generic methods and when to use wild-card?

Generic class on two types

I want to create a Java class with two generic types.
public class BinaryContractInfo<T, U>
The thing is that I would like U to be either the same type of T or T[].
Basically I would like to know if T extends T[] or vice versa. Then I could do something like
public class BinaryContractInfo<T, U extends T[]>
Is that possible? Is there a way to do that?
You cannot specify a type as being either T or T[] Instead you can use varargs
public void method(T... ts);
which can be called either
method(t);
method(t1, t2, t3);
T[] ts =
method(ts);
For return types you can specify
public T[] method();
if the caller assumes there is only one return value
T t = method()[0];
No, AFAIK, you can't do that, not to mention that arrays and generics don't play well together. The simplest thing would be to wrap your array in a collection type (List or a very thin wrapper over an array), if you are allowed to do it that is.
Also, why not just use T[] directly in your code instead of having a separate type parameter for it? If you can't, then do explain why you can't.

Can someone explain the declaration of these java generic methods?

I'm reading "Generics in the Java Programming Language" by Gilad Bracha and I'm confused about a style of declaration. The following code is found on page 8:
interface Collection<E>
{
public boolean containsAll(Collection<?> c);
public boolean addAll(Collection<? extends E> c);
}
interface Collection<E>
{
public <T> boolean containsAll(Collection<T> c);
public <T extends E> boolean addAll(Collection<T> c);
// hey, type variables can have bounds too!
}
My point of confusion comes from the second declaration. It's not clear to me what the purpose the <T> declaration serves in the following line:
public <T> boolean containsAll(Collection<T> c);
The method already has a type (boolean) associated with it.
Why would you use the <T> and what does it tell the complier?
I think my question needs to be a bit more specific.
Why would you write:
public <T> boolean containsAll(Collection<T> c);
vs
public boolean containsAll(Collection<T> c);
It's not clear to me, what the purpose of <T> is, in the first declaration of containsAll.
As far as I can tell, in this case <T> doesn't provide anything useful at all. It creates a method that is completely functionally equivalent to those using the wildcard instead.
Here are a couple of examples where it would be useful:
public List<?> transform(List<?> in);
//vs
public <T> List<T> transform(List<T> in);
In the above, you can correlate the return type with the input type. The first example cannot correlate the runtime type of the two wildcards.
public void add(List<?> list, Object obj);
//vs
public <T> void add(List<? super T> list, T obj);
In the above, the first method won't even be able to add obj to list since it can't be deemed to be type safe. The generic parameter in the second ensures that list can hold whatever type obj is.
The method already has a type (boolean) associated with it.
That is the return type. The full type of the method is “method that takes a Collection<T> (for some T) parameter and returns a boolean”.
And this is where T comes in: the parameter of the function uses it. In other words, this method can be called with different types as argument. The only restriction of these types is that they must implement the Collection<T> interface, which itself relies on a generic argument T (the type of the objects stored in the collection).
The ? is simply a wildcard. It means that the method will accept a Collection of any type.
The <T> is a type parameter for the method. It is essentially assigning the wildcard a name which can then be referred to elsewhere in the method declaration and definition.
A better illustration of the difference would be if the return type of the method varied based on the type that was passed in.
Say you started with a method like
Object getRandomElement( Collection<?> c )
This will accept any Collection, but there's no way to constrain its return type. So a caller would have to cast the result back to whatever type it expected -- which should work, but raises unsafe type-conversion warnings.
With a type parameter you would instead write
<T> T getRandomElement( Collection<T> c )
In this case, if you call this method with a Collection<String>, the compiler knows that it will return a String.
<T> as used here (in method declaration, before return type) is a generic type declaration. You can define new generic type for use within a method: http://download.oracle.com/javase/tutorial/java/generics/genmethods.html
Try compiling it without the <T>.
Basically, it's telling the compiler that this method contains a generic. It isn't required in the first example because ? is a special case, and the second method is referencing the type defined in the Interface itself.
On an unrelated note, public is not required in an Interface. Methods in an interface are public by default, so can save you a bit of typing.
It declares the generic type T used by the method. While the generic type E is the same for the whole interface T is limited to the method it is declared for.

Java : What is - public static<T> foo() {...}?

I saw a java function that looked something like this-
public static<T> foo() {...}
I know what generics are but can someone explain the in this context? Who decides what T is equal to? Whats going on here?
EDIT: Can someone please show me an example of a function like this.
You've missed the return type out, but apart from that it's a generic method. As with generic types, T stands in for any reference type (within bounds if given).
For methods, generic parameters are typically inferred by the compiler. In certain situations you might want to specify the generic arguments yourself, using a slightly peculiar syntax:
List<String> strings = Collections.<String>emptyList();
In this case, the compiler could have inferred the type, but it's not always obvious whether the compiler can or can't. Note, the <> is after the dot. For syntactical reasons the type name or target object must always be specified.
It's possible to have generic constructors, but I've never seen one in the wild and the syntax gets worse.
I believe C++ and C# syntaxes place the generic types after the method/function name.
The context is a generic method as opposed to a class. The variable <T> applies only to the call of the method.. The Collections class has a number of these; the class itself is not generic, but many of the methods are.
The compiler decides what T is equal to -- it equals whatever gets the types to work. Sometimes this is easier then others.
For example, the method static <T> Set<T> Collections.singleton(T o) the type is defined in the parameter:
Collections.singleton(String T)
will return a Set<String>.
Sometimes the type is hard to define. For example sometimes there is not easily enough information to type Collection.emptyList(). In that case you can specify the type directly: Collection.<String>emptyList().
T it's the formal type parameter wich will be replaced by the actual type
argument used at the instantiation of the object.
For example, here is the List and Iterator definitios in package java.util:
public interface List<E>{
void add(E x);
Iterator<E> iterator();
}
public interface Iterator<E>{
E next();
boolean hasNext();
}
Then you can instantiate a List this way:
List<String> ls = new ArrayList<String>()
Where you might imagine that List stands for a version of List where E has
been uniformly replaced by String:
public interface StringList{
void add(String x)
Iterator<String> iterator();
}

Categories

Resources