有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java与<>的区别?方法和变量声明中的超级/扩展字符串>

鉴于:

import java.util.*;

public class Hancock {
    //insert code here
        list.add("foo");
    }
}

在第5行独立插入的哪两个代码片段将在没有警告的情况下编译?(选择两个)

A. public void addString(List list) {
B. public void addString(List<String> list) {
C. public void addString(List<? super String> list) {
D. public void addString(List<? extends String> list) {

正确答案是B&;C

答案A和B对我来说很清楚。有关答案,请参阅C& ;;我知道继承的方向,但是我不理解为什么答案D没有在Eclipse中编译,而其他的都编译(A有关于泛型的警告,B&C没有警告)

Eclipse中答案D的错误为The method add(capture#1-of ? extends String) in the type List<capture#1-of ? extends String> is not applicable for the arguments (String)

另一方面,它编译:

public void addString() {
    List<? extends String> list1 = new ArrayList<String>();
    List<? super String> list2 = new ArrayList<String>();
}

为什么??为什么<? super String>不在方法声明中编译,而在变量声明中编译

我知道String是最后一个类,不能被任何其他类扩展,但这并不能向我解释这里发生了什么


共 (2) 个答案

  1. # 1 楼答案

    首先,让我们看看答案C:

    public void addString(List<? super String> list) {
        list.add("foo");
    }
    

    此方法声明表示将允许您传递List对象,这些对象由String的某个超类参数化,例如StringObject。因此:

    1. 如果您通过List<String>list.add("foo")将完全有效
    2. 如果您传递List<Object>list.add("foo")将完全有效,因为“foo”是一个String(您可以将String添加到List<Object>

    这意味着答案C是正确的


    现在让我们看看答案D

    如果您有这样的方法声明:

    public void addString(List<? extends String> list) {
    
    }
    

    这意味着您将能够传递List对象,这些对象由String的某个未知子类型参数化。因此,当您执行list.add("foo");操作时,编译器不会知道提供的对象是否具有与String未知子类型匹配的类型,因此会引发编译时错误


    如果您有:

    public void addString() {
        List<? extends String> list1 = new ArrayList<String>();
        List<? super String> list2 = new ArrayList<String>();
    }
    

    这个片段编译得很好,因为list1被定义为保存List对象,这些对象属于String的某些未知子类型,包括String本身,这就是它有效的原因。 问题是,除了^{,您将无法添加任何内容

    至于list2,变量可以保存List对象,这些对象由一些超类型的String参数化,包括String本身


    更多信息:

  2. # 2 楼答案

    首先,泛型并不关心String是最终的。他们对期末和非期末课程的学习方式相同

    考虑到这一点,应该很清楚为什么不允许D—如果允许,您可以这样做:

    void test() {
        List<Integer> integers = new ArrayList<Integer>();
        addADouble(integers);
        int a = integers.get(0); // ????
    }
    
    void addADouble(List<? extends Number> list) {
        list.add(new Double(5.0));
    }
    

    List<? extends Number>是一个“扩展数字的事物列表,但您不确切知道它是什么。”它可能是List<Double>、或List<Integer>、或List<Number>、或List<YourCustomSubclassOfNumber>,因此您无法向它添加任何内容,因为您不知道它是否是正确的类型