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.
Related
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)...
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).
In Java, when I get a ResultSet I made a method that would map that to a specified class. It more or less looks like this:
public <T> T mapRow(ResultSet results, Class<T> type) {
So, when I actually call the class, it looks like this:
mapRow(results, Row.class);
Please help me understand this conceptually.
Why can I not just do something like mapRow<Row>(results);?
Also, the current way I'm invoking mapRow, is there an implied <Row> before the method call?
You can call:
object.<Row>mapRow(results, Row.class);
but you still need the second parameter anyway, you cannot remove it for what you are trying to do.
This is because there is no way to know the type of T at runtime when mapRow is called, due to generics erasure.
the current way I'm invoking mapRow, is there an implied before the method call?
The point of the <T> T mapRow() declaration is that T is inferred from the method arguments or the LHS type to which the result is being assigned. In your case, you pass in a class object which serves to infer the return type.
The above is only one half of the purpose of the class argument, the second part being reflection: mapRow will call newInstance() on it to create the object to return.
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.
I've a method in which I'm passing a generic argument. To execute one required method I need the class instance of the same. How can I get it.
There is a workaround which I'm using but I want to know how can we get the Class instance.
The snippet I'm using is:
public <T> T readModelWithId(Class<T> c, Serializable pk) {
// Some code here.
T t = (T)session.get(c, pk);
// Some code here.
return t;
}
The problem is that I don't want to pass the Class instance in this method as it is same as the return type T which is of generic type.
There's no way you can get to something like T.class within that method, so you must pass the class argument since you need it to get your model object from the session.
Moreover, this adds a bit of extra "type-safety". You will force the caller to specify the return type as an argument, so the returned type will not just be "anything a caller may expect" (although I agree this makes it redundant).
You can't do it because Java implements Generics using "type erasure".
http://docs.oracle.com/javase/tutorial/java/generics/erasure.html
Looks like you are doing a generic DAO. I've done something similar here:
http://www.matthews-grout.co.uk/2012/01/my-generic-hibernate-dao.html
You cannot do anything with generics that you could not do with non-generics with casts. Consider the non-generic version of your code:
public Object readModelWithId(Class c, Serializable pk) {
// Some code here.
Object t = session.get(c, pk);
// Some code here.
return t;
}
Now ask the same question, can you get rid of the class instance argument c?
Generics are more for compile time type safety - you need class instance so compiler does not complain about missing cast. Alternatively you can ditch generics altogether and cast result