简体   繁体   English

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

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

The Oracle doc about Wildcards in generics says, 关于泛型中的通配符的Oracle 文档说,

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

}

The ? ? character is the wildcard type argument . character是通配符类型参数

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

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

Wildcard can be used with <> operator in a generics concept introduced in java 5, used to represent unknown type . 在java 5中引入的泛型概念中,通配符可与<>运算符一起使用, 用于表示未知类型 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. 这意味着列表可以使用Integer,Long,Short,Byte,因为它们扩展了Number包装类,但没有使用String作为String类,不扩展Number包装类。

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. 但我们可以使用泛型来提供字段作为员工类中的I,N,S等未知类型。 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;    
    }

Wildcards does not have individual existence. 通配符没有个人存在。 They are always used as type parameter of Generic classes Ex : List<? extends Number> 它们总是用作Generic类Ex: List<? extends Number>类型参数List<? extends Number> List<? extends Number> .I give one example covering all scenarios. 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));
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 为什么不能将嵌套通配符分配给带有类型参数的变量? - Why can't a nested wildcard be assigned to a variable with a type parameter? 为什么我不能使用带通配符的多个类型参数? - Why can't I use multiple type parameters with a wildcard? 为什么我不能在参数中使用通配符类型来计算 - Why I cannot use wildcard type in parameter to compute Java中如何使用通配符作为局部变量的类型? - How to use wildcard as the type of local variable in Java? 为什么不能使用Void作为main方法的返回类型 - Why can't use Void as the return type for main method 为什么我不能将类型参数添加到覆盖方法? - Why can't I add a type parameter to an overriding method? 为什么我不能用错误类型的参数调用方法? - Why can't I call a method with a parameter of the wrong type? 为什么不能将GregorianCalendar用作对象类型作为构造函数参数? - Why can't I use GregorianCalendar as an object type as a constructor parameter? 为什么我可以将整数文字分配给短类型变量而不是短类型方法参数? - Why can I assign an integer literal to a short type variable but not to a short type method parameter? 为什么不能在double类型的方法中返回double类型的数组? - Why can't I return an array of type double in a method of type double?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM