16

The Oracle doc about Wildcards in generics says,

The wildcard can be used in a variety of situations: as the type of a parameter, field, or local variable; sometimes as a return type (though it is better programming practice to be more specific).

I have tried all four in the following class, and got compiler errors on each one. Why? What am I doing wrong?

public class MainClass {
    private ? instanceFieldWithWildCardType;//ERROR
    private static ? staticFieldWithWildCardType;//ERROR

    private void methodWithWildCardParam(? param) {}//ERROR

    private void methodWithWildCardLocalVariable() {
        ? localVariableWithWildCardType;//ERROR
    }

    private ? methodWithWildCardReturnType() {//ERROR
        return null;
    }

    private void methodWithWildCardParam(? param) {}//ERROR

}
Solace
  • 8,612
  • 22
  • 95
  • 183
  • 2
    Because that is not valid syntax. I don't see any generics, just `?`s. – Sean Bright Jun 23 '16 at 17:53
  • Better read the sub sections (https://docs.oracle.com/javase/tutorial/java/generics/upperBounded.html) of wildcards in the generic chapter. You can't use the wildcards directly to replace the types. Also refer lot more examples provide by various sources on the web. – S.K. Venkat Jul 13 '16 at 10:57

4 Answers4

12

The tutorial is terribly phrased. You cannot use a wildcard for any of the things listed. You can use a generic type with a wildcard in it for those things.

public class Example {
    ? field1;        // invalid
    List<?> field2;  // valid

    private ? method1(? param) {return param;}              // invalid
    private List<?> method2(List<?> param) {return param;}  // valid

    private void method3() {
        ? var1;        // invalid
        List<?> var2;  // valid
    }
}
user2357112
  • 260,549
  • 28
  • 431
  • 505
  • I'm not sure "terribly phrased" is appropirate description of the content of this tutorial. Maybe misleading or simply wrong would be better. I wander if we can say, that we can use generic type as a parameter (of class, interface, method) and wildcard as an "argument" using such "parametrized" class/interface/method – Zbyszek Oct 30 '20 at 15:44
10

The ? character is the wildcard type argument.

The article begins with

In generic code, the question mark (?), called the wildcard, represents an unknown type.

The only place you can use that syntax is as part of generic code, ie. a generic type argument. The next sentence refers to generic code using the wildcard. So, for example

as the type of a parameter

you could have

public static void shuffle(List<?> list) {

Or for

as a local variable

public void method() {
    List<?> list = Arrays.asList(1, 2, 3);
    Collections.shuffle(list);
    System.out.println(list);
}

But

The wildcard is never used as a type argument for a generic method invocation, a generic class instance creation, or a supertype.

You can't use it as

Arrays.<?>asList(1, "", '5');
List<?> list = new ArrayList<?>();
...
public class MyList implements List<?> {/* whatever */}
Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724
  • Also worth noting that the same code in the last snippet would be valid if it used `T` in place of `?` for its typing – Jeremy Kato Jun 23 '16 at 18:04
  • In all those examples, `?` is Not used as a type, rather `List>` is used as a type. `?` is different from `List>`. I am confused :s – Solace Jun 23 '16 at 18:10
  • 1
    @Solace `?` is the [wildcard type argument](http://docs.oracle.com/javase/specs/jls/se8/html/jls-4.html#jls-4.5.1). It cannot be used outside the context of generic types. – Sotirios Delimanolis Jun 23 '16 at 18:19
  • ? is *part* of a type parameter, not a type in itself. It is not legal syntax for a type name, thus when you used it as a type name - KABLOOEY! – Lew Bloch Jun 23 '16 at 20:37
2

Wildcard can be used with <> operator in a generics concept introduced in java 5, used to represent unknown type. Generics is used to define a class with member in generalized format.If you want to provide facility that while creating the object, user will specify the type of member then you can use the concept of generics. It can be used only for the instance member can't be used with static member cause memory for static will be allocated only once.

Wildcard concept introduced in generics to restrict unknow type, let's say I have list which has wildcard and this wildcard extend Number wrapper class. That means list can work with Integer, Long, Short, Byte cause they extend Number wrapper class but not with String as String class do not extends Number wrapper class.

List<? extends Number> lt = new ArrayList<>();

Coming to you program, you have used wrong syntax, as i have mentioned wildcard can be used with <> operator.

We can't use wildcard while instantiating class like mentioned bellow -

 List<?> lt = new ArrayList<?>();

but we can use generics to provide the field as unknown type like I,N,S in employee class. It's type we will provide while creating the object of the class -

class Employee<I,N,S>
{
    I eid;
    N empName;
    S empSalary;
}

class Name
{
   String firstName;
   String middleName;
   String lastName;
}

class salary
{
    double basic;
    float it;
    float tds;
    double netsal;
}

class CustomId
{
   int empId;
   String department;
   int branchId;
} 

main method 
------------

    Employee<Integer,String,Double> emp = new Employee<>();
    Employee<String,Name,Salary> emp2 = new Employee<>();
    Employee<CustomId,String,Salary> emp3 = new Employee<>();

Wildcard as method parameter -

public void sortList(List<?> lt)
{
   // code to sort the list whether it is integer, String etc
}
call sortList() method
-----------------------
List<String> lt = new List<>();
lt.add("sss");
lt.add("aaa");
sortList(lt);

List<Integer> lt = new List<>();
lt.add(11);
lt.add(12);
sortList(lt);

Declaring local variable as wildcard -

 List<?> lt = new ArayList<String>();
 List<?> lt = new ArayList<Integer>();

We can use wildcard and generics as return type of method. Here is the example of generics as return type of method -

public T getName(ClassName obj, Key key)
{
    return (Type<T>)obj.getType(Key);
}

Here is the example of wildcard as return type of method -

    List<?> method(List<?> data) 
    {
        return data;    
    }
RCS
  • 1,370
  • 11
  • 27
1

Wildcards does not have individual existence. They are always used as type parameter of Generic classes Ex : List<? extends Number>.I give one example covering all scenarios.

import java.util.ArrayList;
import java.util.List;

class A{

    // I have not make use of this anywhere in this example
    List<? extends Number> l1; //Field;

    //Just taking l2 as parameter
    //Wont be using it also
    //Just tp show wildcard with generic as parameter
    public List<? extends Number> operate(List<? extends Number> l2){ //As return Type; Not recommended Approach

        List<Integer> list = new ArrayList<>();
        list.add(new Integer(6));
        return list;
    }

}



public class Main {

    public static void main(String[] args) {

        List<? extends Number> ar = new ArrayList<Integer>(); //Local Variable
        A obj = new A();
        System.out.println(obj.operate(ar));
    }
}
Number945
  • 4,631
  • 8
  • 45
  • 83