我对Java泛型如何处理继承/多态性感到困惑.
假设以下层次结构 -
动物(父母)
狗 - 猫(儿童)
所以假设我有一个方法doSomething(List<Animal> animals).根据所有继承和多态的规则,我会假设a List<Dog> 是 a List<Animal>而a List<Cat> 是 a List<Animal>- 所以任何一个都可以传递给这个方法.不是这样.如果我想实现这种行为,我必须明确告诉该方法接受一个Animal的任何子类的列表doSomething(List<? extends Animal> animals).
我知道这是Java的行为.我的问题是为什么?为什么多态通常是隐含的,但是当涉及泛型时必须指定它?
java 7中的菱形运算符允许以下代码:
List<String> list = new LinkedList<>();
Run Code Online (Sandbox Code Playgroud)
但是在Java 5/6中,我可以简单地写:
List<String> list = new LinkedList();
Run Code Online (Sandbox Code Playgroud)
我对类型擦除的理解是这些完全相同.(无论如何,通用都会在运行时删除).
为什么要钻石头呢?它允许哪些新功能/类型安全?如果它没有产生任何新功能,为什么他们将其作为功能提及?我对这个概念的理解是否有缺陷?
JAVA由于接口,我实现了以下方法:
public String importDocument(ImportSource source, Map<String, ? extends Object> paramMap);
Run Code Online (Sandbox Code Playgroud)
当我尝试做以下时,我收到编译警告.片段:
paramMap.put("Key", "Value");
Run Code Online (Sandbox Code Playgroud)
错误:
方法put(String,capture#1-of?extends Object)在Map类型中不适用于参数(String,String)
为什么?
我看过一些代码如下
public interface IBean {
}
Run Code Online (Sandbox Code Playgroud)
及其在某些地方的用法
public void persist(List<? extends IBean> beansList) {
}
Run Code Online (Sandbox Code Playgroud)
但是可以使用以下代码来实现
public void persist(List<IBean> beansList) {
}
Run Code Online (Sandbox Code Playgroud)
那么这两种方法有什么区别,除了必须继承IBean接口的对象之外,这两种方法都有什么区别?
这是bean类
public class Category implement IBean {
//related fields
}
public class Product implement IBean {
//related fields
}
Run Code Online (Sandbox Code Playgroud) 以下代码:
List<List<String>> lss = new ArrayList<ArrayList<String>>();
Run Code Online (Sandbox Code Playgroud)
导致此编译时错误:
Type mismatch: cannot convert from ArrayList<ArrayList<String>> to List<List<String>>
Run Code Online (Sandbox Code Playgroud)
修复我将代码更改为:
List<ArrayList<String>> lss = new ArrayList<ArrayList<String>>();
Run Code Online (Sandbox Code Playgroud)
为什么抛出这个错误?这是因为通用类型List in List<List<String>> 是实例化的,因为List是一个接口,这是不可能的?
在Java 8中,类java.util.Optional(javadoc)类提供"Maybe"Monad或Option Type的功能.
更直接:
public final class java.util.Optional <T> extends Object
容器对象,可能包含也可能不包含非null值.如果存在值,则isPresent()将返回true,get()将返回该值.
其中一种方法是:
<U>可选<U>地图(功能<?super T,?extends U> mapper)
如果存在值,则将提供的映射函数应用于该值,如果结果为非null,则返回描述结果的Optional.
问题是为什么map()在类型上使用类型通配符U.
我对类型通配符的理解很简单:
? super T从指定从该组由子类路径给定类型的一些Object到T(两者Object并T包括)联合在拉出任何subinterfacing路径上找到的组接口"作为sidedish"通过implements.
并? extends U简单地从扩展U(U包括)的类集合中指定一些类型.
所以可以写一下:
<U>可选<U>地图(功能<?super T,U> mapper)
没有丢失信息.
或不?