Collection<String>=new ArrayList<>();这样子会什么会报错
时间: 2024-04-15 07:27:16 浏览: 236
在Java中,`ArrayList`是`List`接口的一个实现类,而`Collection`是`List`接口的父接口。因此,你可以将`ArrayList`赋值给`Collection`类型的变量,例如:
```java
Collection<String> collection = new ArrayList<>();
```
这样的赋值是合法的,不会报错。但是,如果你将`ArrayList`赋值给一个泛型声明为`Collection<String>`的变量,会出现编译错误。
```java
Collection<String> collection = new ArrayList<>(); // 正确
Collection<String> collection = new ArrayList<String>(); // 也可以
```
但如果你使用了Diamond Operator (`<>`),在Java 7之前是不允许的,会导致编译错误。要解决这个问题,你可以将代码修改为以下形式:
```java
Collection<String> collection = new ArrayList<String>();
```
或者直接使用Diamond Operator:
```java
Collection<String> collection = new ArrayList<>();
```
总结起来,将 `Collection<String>` 赋值为 `new ArrayList<>()` 是合法的,不会报错。
相关问题
Error:(32, 17) java: 对于invokeAll(ss), 找不到合适的方法 方法 java.util.concurrent.ExecutorService.<T>invokeAll(java.util.Collection<? extends java.util.concurrent.Callable<T>>)不适用 (无法推断类型变量 T (参数不匹配; ss无法转换为java.util.Collection<? extends java.util.concurrent.Callable<T>>)) 方法 java.util.concurrent.ExecutorService.<T>invokeAll(java.util.Collection<? extends java.util.concurrent.Callable<T>>,long,java.util.concurrent.TimeUnit)不适用 (无法推断类型变量 T (实际参数列表和形式参数列表长度不同))
这个报错信息提示在第32行中的invokeAll方法调用参数不匹配,无法找到合适的方法。可能有两个问题:
1. ss类没有实现Callable接口,导致无法将其转换为Callable类型的集合,所以参数不匹配。
2. invokeAll方法需要传入一个Callable的集合,而你只传入了一个ss对象,和一个ss类型的集合也无法匹配,所以报错。
你可以将ss改为实现Callable接口,然后将其放入一个Callable类型的集合中,再将集合传入invokeAll方法中。代码示例如下:
```
public class test {
public static void main(String[] args) throws InterruptedException {
// 创建一个固定大小的线程池
ExecutorService service = Executors.newFixedThreadPool(3);
Callable<String> t1 = new ss();
List<Callable<String>> list = new ArrayList<>();
list.add(t1);
service.invokeAll(list);
// 关闭启动线程
service.shutdown();
// 等待子线程结束,再继续执行下面的代码
service.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
//System.out.println("all thread complete");
}
}
class ss implements Callable<String> {
@Override
public String call() {
System.out.println(Thread.currentThread().getName() + "执行call方法");
return null;
}
}
```
这样就可以避免参数不匹配的问题了。
Collection<?>
### Java 中 `Collection<?>` 泛型集合的使用方法
#### 1. **通配符的作用**
在 Java 的泛型机制中,`Collection<?>` 表示一个未知类型的集合。这里的问号 (`?`) 是一种通配符 (wildcard),表示该集合可以接受任何类型的对象作为其元素[^3]。
#### 2. **读取数据的安全性**
当使用 `Collection<?>` 时,虽然无法向其中添加新元素(因为编译器不知道具体类型),但是可以从集合中安全地读取数据并将其视为 `Object` 类型。这是因为所有的 Java 对象都继承自 `Object`,因此这种转换总是合法的[^4]。
```java
Collection<?> collection = Arrays.asList(1, "two", 3.0);
for (Object element : collection) {
System.out.println(element); // 输出每个元素
}
```
#### 3. **受限通配符的应用**
有时需要更精确地控制集合中的元素类型,这时可以使用受限制的通配符:
- 上界通配符:`<? extends T>`
定义了一个上限,表明集合中的元素必须是某个特定类或其子类的实例。
- 下界通配符:`<? super T>`
定义了一个下限,允许集合包含指定类及其父类的实例。
以下是上界通配符的一个典型应用案例:
```java
public static double sumNumbers(Collection<? extends Number> numbers) {
double sum = 0;
for (Number number : numbers) {
sum += number.doubleValue();
}
return sum;
}
// 测试代码
Collection<Integer> integers = List.of(1, 2, 3);
System.out.println(sumNumbers(integers)); // 正确运行
```
这里通过 `< ? extends Number >` 约束了输入参数只能为 `Number` 及其子类的集合[^5]。
#### 4. **常见问题分析**
##### a. 添加失败的原因
尝试往 `Collection<?>` 中写入数据会引发编译错误,原因是编译期无法确认具体的类型信息。例如下面这段代码不会通过验证:
```java
Collection<?> collection = new ArrayList<>();
collection.add(new Object()); // 编译报错
```
这是由于编译器只知道这是一个某种类型的集合,但不清楚确切的内容类型,从而阻止潜在不兼容的操作发生。
##### b. 类型擦除的影响
Java 的泛型实现基于类型擦除技术,在运行时期并不会保留泛型的具体类型信息。这意味着即使声明的是带有泛型限定的列表,最终也会退化成普通的非泛型形式。比如以下情况展示了如何借助反射绕过正常约束来破坏安全性[^1]:
```java
List<String> list = new ArrayList<>();
Method addMethod = ArrayList.class.getMethod("add", Object.class);
addMethod.invoke(list, Integer.valueOf(1));
String item = list.get(0); // ClassCastException at runtime when accessed as String.
```
尽管如此,在日常编码实践中应尽量避免此类做法以维护程序健壮性和可预测行为。
---
### 总结
通过对上述知识点的学习可知,合理运用泛型能够显著提升代码质量和灵活性;然而同时也需留意伴随而来的局限性如不可随意增删项以及可能遭遇的性能开销等问题。掌握这些细节有助于开发者更好地理解和实践面向对象设计原则下的高级特性——即Java中的泛型支持。
阅读全文
相关推荐












