[盘点错误]加泛型<E>系列

https://gitee.com/fuqiqiqi/test/blob/master/U11/Test5.java

1.运算符 的操作数类型错误 ^ 第一个类型: Object 第二个类型: int:

ListIterator<Integer> it = a.listIterator();   // 关键:加 <Integer>
while (it.hasNext()) {
    int val = it.next();     // 现在 val 是 int
    if (val % 2 == 0) {
        b.add(val);
    }
}

2.        System.out.println(Arrays.toString(add(a, b).toArray()));
                                              ^
  需要: List<Integer>,List<Integer>
  找到: List,List

  final static List a =new ArrayList<>(
        Arrays.asList(1,2,3,4,5)
    );
    final static List b =new ArrayList<>(
        Arrays.asList(4,5,6)
    );

改成

final static List<Integer> a =new ArrayList<>(
        Arrays.asList(1,2,3,4,5)
    );
    final static List<Integer> b =new ArrayList<>(
        Arrays.asList(4,5,6)
    );

3.警告: [unchecked] 未经检查的转换
        List<Integer> c = add(a, b);
                             ^
  需要: List<Integer>
  找到:    List

static List add(List<Integer> a,List<Integer> b){
        List<Integer> c = new ArrayList<>();
        for (int i = b.size()-1; i >=0; i--) {
            if(a.contains(b.get(i))) c.add(b.get(i));
        }
        return c;

    }

改成:

static List<Integer> add(List<Integer> a,List<Integer> b){
        List<Integer> c = new ArrayList<>();
        for (int i = b.size()-1; i >=0; i--) {
            if(a.contains(b.get(i))) c.add(b.get(i));
        }
        return c;

    }

在 Java 中,只有在 “编译器无法自行推断出类型参数,或者推断出的类型不符合你的意图” 时,才需要显式写出 <Integer>(或任何其他具体类型实参)。下面按常见场景做一个系统归纳,方便你快速判断“到底要不要写 <Integer>”。


一、调用 泛型方法 时

1. 必须写 <Integer> 的典型场景
  • 方法实参列表为空,因此编译器拿不到任何推断线

    Collections.<Integer>emptyList();   // 必须写
  • 方法实参存在,但推断结果不是你想要的

    Arrays.asList(1, 2, 3);           // 推断为 List<Integer>,符合预期,可省
    Arrays.asList(1, 2.0);            // 推断为 List<Number & Comparable<?>>,不符合预期
    <Integer>Arrays.asList(1, 2.0);   // 编译错误,类型不兼容
    Arrays.<Integer>asList(1, 2.0);   // 编译错误,2.0 不是 Integer
  • 链式调用,需要中途显式固定类

    Optional.<Integer>empty()
            .orElseThrow();
2. 可以不写 <Integer> 的场景
  • 实参已能唯一、正确地推断出类

    Collections.singletonList(42);      // 推断为 List<Integer>

二、调用 构造方法(泛型类) 时

1. 必须写 <Integer> 的场景
  • 菱形语法 <> 未引入前(Java 7 以前

    List<Integer> list = new ArrayList<Integer>(); // 必须写
  • 构造函数本身是泛型方法(很少见

    class Foo<T> {
        <E> Foo(E e) { }
    }
    Foo<Integer> f = new <String>Foo<Integer>(""); // 左边 Integer,右边 String
2. 可以不写的场景
  • Java 7+ 支持菱形语

    List<Integer> list = new ArrayList<>();  // 可省

三、调用 父类构造器 或 super(...) 时

  • 匿名内部类继承泛型父类 时,需要显式指

    abstract class Bar<T> {}
    Bar<Integer> b = new <Integer>Bar<Integer>() {};

四、静态导入 泛型方法 时

  • 静态导入后,如果方法不带参数,也必须

    import static java.util.Collections.emptyList;
    List<Integer> list = emptyList();   // 编译错误,无法推断
    List<Integer> list = Collections.<Integer>emptyList(); // OK

五、方法引用 / Lambda 中作为 “显式类型实参” 的特例

  • 方法引用本身不能写 <Integer

    Function<String, Integer> f = Integer::valueOf;   // 编译器推断
  • Lambda 表达式体内如果调用泛型方法且需要显式指定,写法与普通调用一

    Supplier<List<Integer>> s = () -> Collections.<Integer>emptyList();

六、总结成一句话

只要编译器能根据上下文或实参推断出你想要的 Integer,就可以不写 <Integer>;否则就必须显式指定。

把常见“必须写”的情况再快速背一遍:

场景必须写 <Integer> 吗?
Collections.<Integer>emptyList()
new ArrayList<>()(Java 7+)
new ArrayList<Integer>()(Java 6)
Arrays.asList(1, 2)
Arrays.<Integer>asList(1, 2)❌(画蛇添足)
new <String>Foo<Integer>(...)✅(泛型构造)
super(…) / this(…) 调用父类泛型构造视推断而定

记住这些典型例子,实际编码时就能一眼判断要不要加 <Integer>


        我是伏琪,关注订阅号伏琪了解更多。 

### Java 的使用方法及意义 Java中的是一种强大的机制,允许在定义类、接口和方法时指定类参数。通过使用,可以编写更安全、更灵活的代码[^4]。 #### 的基本概念 的核心思想是将类作为参数传递给类或方法,从而在编译时提供更强的类检查。例如,在`ArrayList<Student>`中,`<Student>`表示该集合只能存储`Student`类的对象[^4]。 #### 指定的意义 指定的主要目的是提高代码的安全性和可读性。通过明确声明集合中元素的类,可以在编译阶段捕获类错误,避免运行时出现`ClassCastException`等异常[^4]。 #### 的工作原理 当创建一个带有的类或方法时,类参数会在编译时被替换为具体的类。例如,`ArrayList<Student>`会被视为只包含`Student`对象的列表。如果尝试向其中添其他类的对象,编译器会抛出错误。 #### 示例代码:使用<Student> ```java import java.util.ArrayList; // 定义Student类 class Student { private String name; private int age; // 构造方法 public Student(String name, int age) { this.name = name; this.age = age; } // Getter和Setter方法 public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "姓名: " + name + ", 年龄: " + age; } } public class Main { public static void main(String[] args) { // 创建ArrayList,指定为Student ArrayList<Student> students = new ArrayList<>(); // 添Student对象到ArrayList students.add(new Student("张三", 20)); students.add(new Student("李四", 22)); // 遍历并输出学生信息 for (Student student : students) { System.out.println(student.toString()); } } } ``` 上述代码展示了如何使用`<Student>`来确保`ArrayList`只能存储`Student`类的对象,并通过重写`toString`方法简化对象的输出[^3]。 #### 与继承的关系 支持通配符`?`,用于表示未知类。例如,`List<? extends Number>`表示可以存储任何`Number`子类的列表。这种机制增强了的灵活性[^4]。 #### 与方法 除了类之外,方法也可以使用。例如: ```java public <T> void printArray(T[] array) { for (T element : array) { System.out.println(element); } } ``` 此方法可以接受任何类的数组并打印其内容[^4]。 ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值