Why is the syntax of java generics the way it is - java

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)...

Related

why static generic method should have<T> in front of return type

Why a generic static method have a in addition to return type, but a instance method not?
public class Main<T> {
public static <T> T met(T t) {
return t;
}
public T met1(T t) {
return t;
}
}
An instance method can also define the generic type parameter (<T>) in front of the return type, but it doesn't have to, since it can use a generic type parameter already defined in the class level (public class Main<T>).
On the other hand, a static method cannot use the generic type parameter defined in the class level, so it must declare any generic type parameter it intends to use.
i.e. both of the following are valid
public static <T> T met(T t) {
return t;
}
public <T> T met1(T t) {
return t;
}
On the other hand, in the following
public static T met(T t) {
return t;
}
T is assumed to be a type identifier (i.e. the name of some class or interface), and not a generic type parameter.
First, we need to understand what is the "addition". Is it NOT an addition to the return type. It is a "Bounded Type Parameters"
Bounded Type Parameters There may be times when you want to restrict
the types that can be used as type arguments in a parameterized type.
For example, a method that operates on numbers might only want to
accept instances of Number or its subclasses. This is what bounded
type parameters are for.
When you compile your generic class/method/interface. Java compiler converts generic type to code that JVM understands. This process is call type erasure and it requires to know bounds of generic's type parameters. i.e. <T> get converts to Object because it is unbounded and <T extends Comparable<T>> get converts to Comparable
Second, why does a generic static method requires bounded type parameters whereas a generic instance method does not?
This kind of goes hand in hand with the difference between class method and instance method.
When you use the key word static the method becomes a class method. Which means you can invoke without a creating an instance. And that is the problem. Because static method is shared among all instances of the class including instances of different type parameters, Java doesn't know what T is until you instantiate a type. We need to explicitly tell the compiler what instance the class method should expect.
When you don't use the key word static the method is now an instance method. Which means you can't invoke the method until you create an instance of the class. When creating an instance you would need to specify the type parameter. Java compiler can inherently use that type parameter when you invoke instances method so bounded type parameter is optional for instance method.
There is two aspects to this:
A)
Instance methods implicitly acquire all the class type-parameters whereas the static don't. The reason for this is that at compilation time the type assigned to those type-parameters are specific to each object instance reference, so they would never apply to static methods since these don't have a particular instance associated to them.
B)
All methods, instance or class ones can defined additional type-parameters that only apply to that method. These are placed between the modifiers (public, static, ...) and the return type. That is just an arbitrary syntax choice made by the Java language developers. So they could have done it differently, however it makes more sense to have to declare something before it is ever used (e.g. in the parameter type declaration).

Generic functions in 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 :)

How to call a generic method directly?

Here is the method I am calling:
public static <T extends Something> Group<T> getGroup() { ... }
If I wanted to store the result in a variable, I would do something like this:
Group<SomethingSubClass> group = StaticClass.getGroup();
How would I call the method without storing it in a variable?
StaticClass.getGroup();
The above is what I tried, but I am unsure (mostly don't think it is possible from the way my method is) to add the generic type T.
Solution:
StaticClass.<SomethingSubClass>getGroup();
You don't need anything special. Just invoke it as
StaticClass.getGroup();
You will simply be ignore the return value. The type argument will be inferred as Something, which is what you'd have access to in your method anyway.
You would specify an actual type argument by doing
StaticClass.<SomeTypeThatExtendsSomething>getGroup();
but you don't need that since the only part of your method that makes use of the generic type is the return type, which you are discarding.

What's the difference between <T> T vs T in the return type of a method?

I have a method, like this,
public <T> T doSomething(Class<T> T) {
return T.newInstance();
}
I can also do the same like this,
public T doSomething(Class<T> T) {
return T.newInstance();
}
Is there any difference between these two? Please ignore T.newInstance(), I'm basically going to create a new instance of T somehow and return it.
thanks,
sam
What's the difference between <T> T vs T in the return type of a method?
There is no <T> T. The <T> is not part of the return type; it's a separate thing, indicating the type parameter. (You can also have public <T> void ....)
In the version with <T>, you're declaring T as a type parameter of the method, and the T in the argument and the return-type are referring to that type parameter.
In the version without <T>, you're not declaring T as a type parameter of the method, so it's most likely a type parameter of the containing class or another containing scope. (Alternatively, someone may have named an actual class or interface T, in which case you should give that person a talking-to.)
If both versions compile, then the second is probably the one you want: you probably want to be using the class's type parameter T, rather than adding a new one that hides it. (And if you really do want a new type parameter unrelated to your class's type parameter, then you should use a new name for it to avoid confusion.)
In the first example, you declare a generic method doSomething with its own type parameter <T>. If it's in a generic class, then this <T> is separate from any type parameters that the class may have (even another <T>!).
In the second example, you don't declare a generic type parameter on doSomething. If the class defines <T>, then this method simply uses it. If it doesn't, then T is unrecognized and a compiler error results.
Second option will work only if T is declared as a class generic type. If class doesn't define any generic type and only its member function accepts/returns generic type , you need to explicitly declare it in function declaration.

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