为什么我不能将通配符 (?) 用作参数类型、字段、局部变量或方法的 return 类型?

Why can't I use the wildcard (?) as type of parameter, field, local variable, or as return type of a method?

Oracle doc about Wildcards in generics 说,

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

我已经尝试了以下所有四种 class,并且每一种都出现编译器错误。为什么?我做错了什么?

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

}

? 字符是 wildcard type argument

文章开头为

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

您唯一可以使用该语法的地方是作为通用代码的一部分,即。泛型类型参数。下一句是指使用通配符的通用代码。所以,例如

as the type of a parameter

你可以

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

as a local variable

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

但是

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

您不能将其用作

Arrays.<?>asList(1, "", '5');
List<?> list = new ArrayList<?>();
...
public class MyList implements List<?> {/* whatever */}

通配符可以和<>运算符一起使用在泛型概念中引入java5,用于表示未知类型.泛型用于在广义 format.If 中定义一个 class 成员,你想提供便利,在创建对象时,用户将指定成员的类型,然后你可以使用泛型的概念。它只能用于实例成员,不能与静态成员一起使用,因为静态成员的内存只会分配一次。

泛型中引入的通配符概念来限制未知类型,假设我有一个包含通配符的列表,并且这个通配符扩展了 Number wrapper class。这意味着列表可以与 Integer、Long、Short、Byte 一起使用,因为它们扩展了 Number wrapper class 但不能与 String 一起使用,因为 String class 不扩展 Number wrapper class。

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

来到你的程序,你使用了错误的语法,正如我提到的,通配符可以与 <> 运算符一起使用。

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

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

但我们可以使用泛型将字段提供为未知类型,例如员工 class 中的 I、N、S。这是我们在创建 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);
}

这里是通配符的例子,作为return类型的方法-

    List<?> method(List<?> data) 
    {
        return data;    
    }

该教程措辞糟糕。您不能对列出的任何内容使用通配符。对于这些事情,您可以使用带有通配符的通用类型

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
    }
}

通配符没有单独的存在。它们总是用作泛型的类型参数 类 例如:List<? extends Number>。我举一个涵盖所有场景的例子。

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));
    }
}