?超级字符串下限Java

时间:2016-06-22 07:58:42

标签: java generics bounded-wildcard lower-bound

我正在为作者的观看本书阅读 Boyarsky和Scott Selikoff,书籍说:Page#122

    List<? super String> superString = new ArrayList<>();
    superString.add(new String());// Valid 
    superString.add(new Object()); // Not Valid ? Why?. Object is a super class of String 

使用下限,我们告诉Java该列表将是 String对象列表或者 一些超类String

的对象列表
List<? super IOException> exceptions = new ArrayList<Exception>();
exceptions.add(new Exception()); // Invalid, why ? Exception is a superclass of IOException
exceptions.add(new IOException());
exceptions.add(new FileNotFoundException());

其他示例:

List<? super IOException> exceptions = new ArrayList<Exception>();

我认为这句话

  

使用下限,我们告诉Java该列表将是 String对象列表或者   一些超类String

的对象列表

  

使用下限,我们告诉Java该列表将是 String对象列表或者   一些对象的列表 whoes super class is String

如果这种情况属实,那么为什么我们使用

List<? super IOException> exceptions = new ArrayList<IOException>();

而不是

var assignedContentData = {
    "AssignedContentData": [{
        "description": "Capital",
        "newsletter": 2,
        "press_release": 12,
        "letter": 1,
        "notice": 0,
        "bulletin_memorandum": 0
    }, {
        "description": "NA",
        "newsletter": 0,
        "press_release": 0,
        "letter": 0,
        "notice": 1,
        "bulletin_memorandum": 0
    }, {
        "description": "Equity",
        "newsletter": 0,
        "press_release": 4,
        "letter": 0,
        "notice": 5,
        "bulletin_memorandum": 12
    }]
};

var oAssignContentModel = new sap.ui.model.json.JSONModel({
    data: assignedContentData
});

sap.ui.getCore().setModel(oAssignContentModel, "oAssignContentModel");
var assignedContentBarChart = new sap.viz.ui5.controls.VizFrame("assignedContentBarChart", {
    vizType: "stacked_column"
});

var oDatasetAssignedContentBar = new sap.viz.ui5.data.FlattenedDataset({
    dimensions: [{
        name: "Description",
        value: "{description}"
    }],
    measures: [{
        name: "Newsletter",
        value: "{newsletter}"
    }],
    data: {
        path: "/data/AssignedContentData"
    }
});

var feedValueAxis1 = new sap.viz.ui5.controls.common.feeds.FeedItem({
    'uid': "valueAxis",
    'type': "Measure",
    'values': ["Newsletter"]
});
var feedCategoryAxis1 = new sap.viz.ui5.controls.common.feeds.FeedItem({
    'uid': "categoryAxis",
    'type': "Dimension",
    'values': ["Description"]
});
var feedColorAxis1 = new sap.viz.ui5.controls.common.feeds.FeedItem({
    'uid': "color",
    'type': "Dimension",
    'values': ["Newsletter", "Press_Release", "Letter", "Notice", "Bulletin_memorandum"]
});
assignedContentBarChart.setVizProperties({
    plotArea: {
        dataLabel: {
            visible: true,
            formatString: "#,##0"
        }
    },
    legend: {
        title: {
            visible: false
        }
    },

    title: {
        visible: true,
        text: 'Bar Chart'
    }
});

assignedContentBarChart.setDataset(oDatasetAssignedContentBar);
assignedContentBarChart.addFeed(feedValueAxis1);
assignedContentBarChart.addFeed(feedCategoryAxis1);

2 个答案:

答案 0 :(得分:2)

您需要了解这些边界(下限和上限)是否存在用于限制/指定变量的类型,而不是用于限制/指定此类集合中元素的类型。

一个例子:

List<? super String> variable = new ArrayList<CharSequence>();

使用此声明,您首先要创建一个ArrayList,其元素可以是CharSequence类型或其子类型(例如StringStringBuilder)。

通过该声明,您应该清楚,您无法在此列表中添加Object。它根本没有实现CharSequence接口。编译器会处理这个问题。

存在用于制作泛型类型的子类型的下限和上限。它们的使用在this question about PECS中解释。

实际上,List<? super String>是具有具体元素类型的列表,但此时此类具体类型尚不清楚。看我的示例初始化。具体类型是CharSequence。它只是意味着所有元素都是具体类型(或子类型),但在变量的类型中不知道。

答案 1 :(得分:1)

这是指向良好解释Difference between <? super T> and <? extends T> in Java

的链接

这本书是正确的&#34;?超级字符串&#34;表示该列表可能包含字符串或字符串的超类型(例如,Object,CharSequence)

在你的例子中:

List<? super String> superString = new ArrayList<>();
    superString.add(new String());// 1 
    superString.add(new Object()); // 2

写操作:

1 - 对于您可以创建的任何类型的列表都有效,因为String是一个Object,一个CharSequence ......

List<? super String> list = new ArrayList<Object>();
list.add("String");

2 - 无效,因为它不涵盖所有案件

List<? super String> list = new ArrayList<String>();
list.add(new Object());

鉴于声明的类型List<? super String>,您只能添加字符串(和字符串子类型),任何小于字符串(超类型)的内容都可能与实际的元素类型不对应。

示例:

以下是一个例子:

interface MyInterface {

}

class MyInterfaceImpl implements MyInterface {

}

class MyInterfaceImplExtra extends MyInterfaceImpl {

}

您可能遇到以下情况:

List<? super MyInterfaceImpl> myList = new ArrayList<MyInterfaceImpl>();

不编译,因为myList变量可能指向MyInterfaceImpl或MyInterface或Object的列表。当添加到列表时,它不清楚您实际具有哪种类型的列表,因此您只允许适用于所有情况的值。

myList.add(new MyInterface(){}); // - compile error "not applicable for the arguments"
myList.add(new MyInterfaceImpl()); // - works fine
myList.add(new MyInterfaceImplExtra()); // - works fine

获取值列表的示例。元素类型是Object,不能保证更具体的类型。例如,你在这里期待字符串,但得到一个List<? super String>实际上包含对象,所以你得到一个java.lang.ClassCastException

List<String> result = (List<String>) getList();
 System.out.println(result.get(0));

 public static List<? super String> getList(){
    List<Object> list = new ArrayList<Object>();
    list.add(new Object());
    return list;
 }

Java 8中的用法示例:

您在Stream接口中有以下方法声明,它将谓词类型限制为T或超类型。

Stream<T> filter(Predicate<? super T> predicate);

这确保给定一个定义名称的Person和扩展Person的Employee并定义一个额外的字段id,你不能这样做:

List<Person> list = new ArrayList<Person>() {{
        add(new Person("John"));
        add(new Person("Max"));
        add(new Person("Megan"));
    }};

list.stream().filter((Employee e) -> e.getId().startsWith("1")); // compile error