Oracle doc about Wildcards in generics说,
通配符可用于各种情况:作为a的类型 参数,字段或本地变量;有时作为返回类型 (虽然更好的编程实践更具体)。
我已经尝试了以下类中的所有四个,并且每个都遇到了编译器错误。为什么?我做错了什么?
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
}
答案 0 :(得分:9)
文章以
开头在通用代码中,问号(?),称为通配符, 代表一种未知的类型。
您可以使用该语法的唯一地方是通用代码的一部分,即。泛型类型参数。下一句是指使用通配符的通用代码。所以,例如
作为参数的类型
你可以
public static void shuffle(List<?> list) {
或
作为局部变量
public void method() {
List<?> list = Arrays.asList(1, 2, 3);
Collections.shuffle(list);
System.out.println(list);
}
但是
通配符从不用作泛型方法的类型参数 调用,泛型类实例创建或超类型。
您无法将其用作
Arrays.<?>asList(1, "", '5');
List<?> list = new ArrayList<?>();
...
public class MyList implements List<?> {/* whatever */}
答案 1 :(得分:9)
教程非常明确。您不能对列出的任何内容使用通配符。您可以使用泛型类型,其中包含通配符。
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
}
}
答案 2 :(得分:2)
通配符可与&lt;&gt;一起使用在Java 5中引入的泛型概念中的运算符,用于表示未知类型。泛型用于定义具有通用格式成员的类。如果要在创建对象时提供工具,用户将指定成员的类型,然后您可以使用泛型的概念。它只能用于实例成员不能与静态成员一起使用,因为静态内存只会被分配一次。
在泛型中引入的通配符概念用于限制unknow类型,假设我有一个包含通配符的列表,这个通配符扩展了数字包装类。这意味着列表可以使用Integer,Long,Short,Byte,因为它们扩展了Number包装类,但没有使用String作为String类,不扩展Number包装类。
List<? extends Number> lt = new ArrayList<>();
来到你的程序,你使用了错误的语法,因为我已经提到过,通配符可以和&lt;&gt;一起使用操作
我们不能在实例化上面提到的类时使用通配符 -
List<?> lt = new ArrayList<?>();
但是我们可以使用泛型来提供字段作为员工类中的I,N,S等未知类型。这是我们在创建类的对象时将提供的类型 -
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<>();
通配符作为方法参数 -
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);
将局部变量声明为通配符 -
List<?> lt = new ArayList<String>();
List<?> lt = new ArayList<Integer>();
我们可以使用通配符和泛型作为返回类型的方法。 以下是泛型作为返回类型方法的示例 -
public T getName(ClassName obj, Key key)
{
return (Type<T>)obj.getType(Key);
}
以下是通配符作为返回类型的方法的示例 -
List<?> method(List<?> data)
{
return data;
}
答案 3 :(得分:1)
通配符没有个人存在。它们总是用作Generic类Ex: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));
}
}