This question already has answers here:
Why does this Java method appear to have two return types?
(3 answers)
Closed last month.
I have a question about generics, I know what <E> means, but what does <E> void mean?
public static <E> void append(List<E> list) {
}
I thought about <E> void but I don't know what it means.
void is the return type for the append method, that's independent of the generic type E.
In that method declaration, void is the return type. <E> is the declaration of the method's type parameter, which is necessary when the class itself does not have a matching type parameter because the method argument uses <E> as a type parameter.
In this case, <E> and void have nothing to do with each other.
Related
This question already has answers here:
What is a raw type and why shouldn't we use it?
(16 answers)
Why does javac complain about generics unrelated to the class' type arguments? [duplicate]
(1 answer)
Closed 5 years ago.
Edit:
I found the second duplicate matched my question the best and was the most useful.
I have a generic class which has a method with a generic return type. The return type's concrete class is given in the definition. When I use the method, the compiler gives unchecked conversion warning.
An example will explain it better.
public class MyGenericClass<T> {
public List<String> getStringList() {
return new ArrayList<String>();
}
}
public class Test {
public static void main(String[] args) {
MyGenericClass mgc = new MyGenericClass<>();
List<String> myStringList = mgc.getStringList();
}
}
The last line in the main method causes the compiler warning:
warning: [unchecked] unchecked conversion
List<String> myStringList = mgc.getStringList();
^
required: List<String>
found: List
This problem does not occur when I specify T. For example when I use Integer as T, the problem does not occur.
It is not good to use a generic class without specifying a type but I couldn't understand why the return type 'List<String>' becomes 'List' when I don't specify T. Does anyone know the logic behind this, and can you point me to the related section of JLS?
This question already has answers here:
Why does this Java method appear to have two return types?
(3 answers)
Closed 5 years ago.
This signature:
public static <E extends Enum<E>> String getEnumString(Class<E> clazz, String s)
is not found anywhere I could see in the Oracle Java documentation for Generics. It appears to use a generic typecast of the returned String value but that cannot be since a real string is returned. Any insight would be greatly appreciated.
Referencing the answer to this thread: Java: Generic method for Enums
The method:
public static <E extends Enum<E>>String getEnumString(Class<E> clazz, String s){
for(E en : EnumSet.allOf(clazz)){
if(en.name().equalsIgnoreCase(s)){
return en.name();
}
}
return null;
}
The construction
<E extends Enum<E>> String getEnumString(...
is not a "Generic Modifying Standard Type".
It is a declaration of a type parameter (the <E extends Enum<E>>) followed by the return type of the method and its arguments. It specifies that the method is generic and provides a type parameter and its bounds.
The type parameter does not modify String at all. It declares a bounded type parameter E that is used later in the argument list at Class<E> clazz to specify that the set of acceptable Class instances is limited to enumeration types.
This question already has answers here:
How is an overloaded method chosen when a parameter is the literal null value?
(8 answers)
Closed 6 years ago.
Which overloaded method will be called for the below method and why?
I executed this code and it calls the overloaded method with List but why does it happen?
public class AmbigiousOverload {
public static void add(Object o) {
System.out.println("Overloaded method with Object.");
}
public static void add(List l) {
System.out.println("Overloaded method with List.");
}
public static void main(String[] args) {
add(null);
}
}
Output: Overloaded method with List.
The List overload is called because the List overload is the most specific matching overload, as all List implementations are subclasses of Object.
From JLS Sec 15.12.2.5:
The informal intuition is that one method is more specific than another if any invocation handled by the first method could be passed on to the other one without a compile-time error.
Since any parameter you can pass to add(List) can also be passed to add(Object), add(List) is more specific. As such, given that null can be passed to both, the more specific method is the one chosen.
Note that it wouldn't compile if you had an add(String) overload, since List and String are "equally" specific. (Or any other class: it doesn't have to be String).
What is the purpose of using a wildcard for unbounded or upper-bounded generics? More specifically:
Why would I say public static void foo(List<?> bar) instead of public static <E> void foo(List<E> bar)?
Why would I say public static void foo(List<? extends Baz> bar) instead of public static <E extends Baz> void foo(List<E> bar)?
If you are not ever going to refer to E in the code that follows, there is no need to declare it.
Reduces programmer memory strain.
The versions with a wildcard are preferred. If a parameter has type List<?> it is clear that any List will be accepted. If any List is accepted, there's no reason to give the type parameter a name, so writing <E> would just be clutter. On the other hand, if the type parameter appears twice in the signature, then you cannot use wildcards. For example, this signature needs a type parameter.
public static <E> List<E> combineLists(List<E> list1, List<E> list2)
Actually in that example it would probably be better if the arguments had type List<? extends E> (the only way to do that without wildcards would be to have three type parameters, a total mess).
In Effective Java, it is recommended that even if the type parameter is needed in the body of the method, you should prefer the version of the signature with a wildcard, and write a private helper method to make this possible. For example:
public static void swapFirstAndLast(List<?> list) {
helper(list);
}
private static <E> void helper(List<E> list) {
int size = list.size();
E e = list.get(0);
list.set(0, list.get(size - 1)); // These lines would not be possible
list.set(size - 1, e); // If the type of list were List<?>
}
If the type of the list is decided at runtime, then you will need to use wildcards.
The following program will print a List<String> if run with any command-line arguments; otherwise it will print a List<Number>:
public class Test {
public static List<String> listOfStrings = Arrays.asList("hello", "world");
public static List<Number> listOfNumbers = Arrays.asList(1, 2, 3, 4.5);
public static List<?> getListOfUnknown(boolean arg) {
if(arg) return listOfStrings;
else return listOfNumbers;
}
public static void main(String[] args) {
System.out.println(getListOfUnknown(args.length > 0));
}
}
The official tutorial for generic method already explained well enough.
... the type parameter T is used only once. The return type doesn't depend on the type parameter, nor does any other argument to the method (in this case, there simply is only one argument). This tells us that the type argument is being used for polymorphism; its only effect is to allow a variety of actual argument types to be used at different invocation sites. If that is the case, one should use wildcards. ...
Generic methods allow type parameters to be used to express dependencies among the types of one or more arguments to a method and/or its return type. If there isn't such a dependency, a generic method should not be used.
Browsing through Guava libraries I saw this weird signature on a readLines method from Files class:
public static <T> T readLines(File file,
Charset charset,
LineProcessor<T> callback)
I know a little bit about generics in java, but this baffled me.
What does the double T mean here? And why is the first one in angled brackets?
UPDATE: Thanks for the answers. I am still not clear as to why I should use a T inside the brackets. Why for example can't it just be:
public static <> T readLines()
or
pulibc static <K> T readLines()
Or does the java syntax dictate that the SAME letter must be used?
Now this is even wierder:
static <T> void fromArrayToCollection(T[] a, Collection<T> c) {
how can a method have a generic-return type and be void?
It's a generic method -- the T is called a type parameter, and can represent any type. So if I have a method with this signature:
public <T> T foo(T[] bar)
I can call it on any array, and it will return a single object of the same type. If I pass it a String array, I'll get back a String, and so on. More information in the Sun tutorials for "generic methods".
Edit: In answer to your updated question, bear in mind that the first <T> isn't part of the return type: it's just an indicator that T is a type parameter. So look at the example you quoted:
static <T> void fromArrayToCollection(T[] a, Collection<T> c)
That just means that fromArrayToCollection will accept any array and any collection, but that they must be an array and collection of the same type. So you can pass in a String[] and a Collection<String>, or an Integer[] and a Collection<Integer>, but not a String[] and a Collection<Integer>. No matter what type you put in for T, the method returns nothing.
The first T inside the angle brackets mean that the method itself is generic. The second T is the return type. T can be any type within its bounds. In this case, T has no bounds.
T will be determined at the call site, and in this case, inferred from the LineProcessor<T> parameter.
I am still not clear as to why I should use a T inside the brackets. Why for example can't it just be:
public static <> T readLines()
or
public static <K> T readLines()
Or does the java syntax dictate that the SAME letter must be used?
The <T> or <K> is the type parameter. If you write <K> T, then the T isn't a type parameter - rather, you're using the specific class T. This won't work if you don't have a class that's literally named T in scope.
Now this is even wierder:
static <T> void fromArrayToCollection(T[] a, Collection<T> c) {
how can a method have a generic-return type and be void?
It doesn't; the <T> is not a "generic return type", it's just the type parameter to the method. You're saying that the method is generic, and T is the type parameter. The return type of the method is void.
Instead of being generic at class level only the method readLines uses generics.
The first <T> declares the generic types used by the method
The following T is the return type.
The first one uses the same syntax as a generic class to declare the generic types. Instead you could write
class Generic <T>
{
public static T readLines(File file,
Charset charset,
LineProcessor<T> callback)
}
This however would make all instances of the class generic.
Extended Example:
public static <ElementType,ListType extends List<ElementType>> ListType add(ListType list,ElementType elem)
{
list.add(elem);
return list;
}
ArrayList<String> = add(add(new ArrayList<String>(),"Hello"),"World");
The method adds a given Element to a List and returns the List.
The method uses two generic Types one for the elements of the list and one for the list itself.
The names used are nothing special, using a T for a generic type is like using i for an integer.
ElementType is the name used for the generic Type of the elements (any valid variable name / identifier could be used)
ListType is the name for the generic list Type, the classes used have to extend/implement List for the ElementType.
The example calls the method with:
ElementType = String
ListType = ArrayList
which would result in
public static ArrayList<String> add(ArrayList<String> list, String elem)
Bloat end :-)
This is a generic method.
Actually there are three Ts, the third on LineProcessor<T> specifies T when you use the method.