在 Java 中,? 符号通常出现在三元运算符,泛型(Generics)和通配符(Wildcard)的上下文中。它表示一种不确定的类型,即所谓的“未知类型”。? 通配符可以用于以下几种情况
1.三元运算符(Conditional Operator)
三元运算符是一种简化的 if-else 结构,它允许你在一行内执行条件判断并返回结果。语法如下:
result = (condition) ? valueIfTrue : valueIfFalse;
•condition:是一个布尔表达式,如果为真 (true),则整个表达式的值为 valueIfTrue;否则为 valueIfFalse。
•valueIfTrue 和 valueIfFalse:必须是兼容的类型,因为它们最终会被赋值给同一个变量 result。
int a = 5;
int b = 10;
String result = (a > b) ? "A is greater" : "B is greater or equal";
System.out.println(result); // 输出: B is greater or equal
在这个例子中,a > b 是条件表达式,"A is greater" 是当条件为真时的结果,"B is greater or equal" 是当条件为假时的结果。根据条件的结果,result 将被赋予相应的字符串值。
public class Temperature {
private double temperature;
public Temperature(double temperature) {
this.temperature = temperature;
}
public String getTemperatureStatus() {
return temperature > 30 ? "Hot" : "Not Hot";
}
public static void main(String[] args) {
Temperature temp = new Temperature(35);
System.out.println(temp.getTemperatureStatus()); // 输出: Hot
}
}
2.无界通配符(Unbounded Wildcards)
当你想要创建一个可以接受任何类型的对象时,可以使用 ? 作为通配符,这被称为无界通配符。例如:
List<?> list;
这段代码声明了一个 List 类型的变量 list,它可以引用任何类型的 List 实例,如 List<String>、List<Integer> 等等。但是,你只能从这个列表中读取元素,而不能向其中添加元素(除了 null),因为你不知道列表的实际类型参数是什么。
public static double sumOfList(List<? extends Number> list) {
double sum = 0.0;
for (Number num : list) {
sum += num.doubleValue();
}
return sum;
}
// 使用示例
public static void main(String[] args) {
List<Integer> intList = Arrays.asList(1, 2, 3);
List<Double> doubleList = Arrays.asList(1.1, 2.2, 3.3);
System.out.println(sumOfList(intList)); // 输出: 6.0
System.out.println(sumOfList(doubleList)); // 输出: 6.6
}
3.上界通配符(Upper Bounded Wildcards)
有时你可能希望限定通配符所代表的类型为某个特定类或其子类。这时你可以使用上界通配符 ? extends T,其中 T 是你指定的类型。例如:
List<? extends Number> numberList;
这里的 numberList 可以引用 List<Number> 或者它的任何子类类型的列表,如 List<Integer> 或 List<Double>。与无界通配符一样,你只能从中读取元素,因为编译器只知道这些元素是 Number 或其子类的实例。
public static double sumOfList(List<? extends Number> list) {
double sum = 0.0;
for (Number num : list) {
sum += num.doubleValue();
}
return sum;
}
// 使用示例
public static void main(String[] args) {
List<Integer> intList = Arrays.asList(1, 2, 3);
List<Double> doubleList = Arrays.asList(1.1, 2.2, 3.3);
System.out.println(sumOfList(intList)); // 输出: 6.0
System.out.println(sumOfList(doubleList)); // 输出: 6.6
}
4.下界通配符(Lower Bounded Wildcards)
相反地,如果你想要限定通配符所代表的类型为某个特定类或其父类,则可以使用下界通配符 ? super T。例如:
List<? super Integer> integerList;
这里,integerList 可以引用 List<Integer>、List<Number> 或 List<Object>。这意味着你可以向这个列表中添加 Integer 类型的对象,但你从列表中读取出来的对象只能被当作 Object 处理,因为你无法确定列表的确切类型。
public static void addStringToList(List<? super String> list) {
list.add("New String");
}
// 使用示例
public static void main(String[] args) {
List<Object> objectList = new ArrayList<>();
List<String> stringList = new ArrayList<>();
addStringToList(objectList); // 可以向 Object 列表中添加字符串
addStringToList(stringList); // 也可以向 String 列表中添加字符串
System.out.println(objectList); // 输出: [New String]
System.out.println(stringList); // 输出: [New String]
}
总结
•?:表示未知类型,主要用于泛型和通配符。
•无界通配符:?,表示未知类型。
•上界通配符:? extends T,表示未知类型,但它是 T 或 T 的子类型。
•下界通配符:? super T,表示未知类型,但它是 T 或 T 的父类型。
•三元运算符:(condition) ? valueIfTrue : valueIfFalse,用于简化条件判断逻辑,提供了一种更紧凑的方式来表达 if-else 语句。
这两种用法虽然符号相同,但用途完全不同。在泛型中,? 表示一种未知类型;而在三元运算符中,? 是条件运算的一部分,用于决定两个值中的哪一个将被选择。