在阅读Stream界面源代码时,我发现了这个方法签名:
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
Run Code Online (Sandbox Code Playgroud)
我想知道为什么输入类型mapper是? super T输出类型? extends R,为什么不? extends用于两者?
我知道已经发布了类似的问题,虽然我认为我的情况有所不同......
假设您有两种方法:
// Bounded type parameter
private static <T extends Number> void processList(List<T> someList) {
}
// Upper bound wildcard
private static void processList2(List<? extends Number> someList) {
// ...
}
Run Code Online (Sandbox Code Playgroud)
据我所知,这两种方法接受参数,是List类型Number或List的亚型的Number.
但毕竟这两种方法有什么区别?
我得到以下编译消息:
[javac] ... error: incompatible types
[javac] exceptionClassHolder = new Holder<>( (new Exception()).getClass() );
[javac] ^
[javac] required: Holder<Class<? extends Exception>>
[javac] found: Holder<Class<CAP#1>>
[javac] where CAP#1 is a fresh type-variable:
[javac] CAP#1 extends Exception from capture of ? extends Exception
[javac] 1 error
Run Code Online (Sandbox Code Playgroud)
在我看来,根据信息所有应该是正确的.CAP#1确实扩展了Exception.那么如何理解上述信息呢?下面的SSCCE(最初没有发布,因为我希望在一般情况下理解错误消息本身):
class Holder<T> {
public T t;
public Holder(T t) {
this.t = t;
}
}
public class FooMain {
public static void main(String args[]) throws Exception {
Holder<Class<? extends Exception>> exceptionClassHolder;
exceptionClassHolder = …Run Code Online (Sandbox Code Playgroud) 我刚学会了Scala.现在我对Contravariance和Covariance很困惑.
从这个页面,我学到了以下内容:
协方差
也许子类型最明显的特征是能够用表达式中较窄类型的值替换较宽类型的值.例如,假设我有一些类型的Real,Integer <: Real和一些不相关的类型Boolean.我可以定义一个is_positive :: Real -> Boolean对Real值进行操作的函数,但我也可以将此函数应用于类型Integer(或任何其他子类型Real)的值.用更窄(后代)类型替换更宽(祖先)类型被称为covariance.这个概念covariance允许我们编写通用代码,在推理面向对象编程语言中的继承和函数式语言中的多态时非常有用.
但是,我也从其他地方看到了一些东西:
scala> class Animal? defined class Animal
scala> class Dog extends Animal? defined class Dog
scala> class Beagle extends Dog? defined class Beagle
scala> def foo(x: List[Dog]) = x? foo: (x: List[Dog])List[Dog] // Given a List[Dog], just returns it?
scala> val an: List[Animal] = foo(List(new Beagle))? an: List[Animal] = List(Beagle@284a6c0) …Run Code Online (Sandbox Code Playgroud) 在处理面试问题时,我遇到了以下代码:
List<Object> list = new ArrayList();
Map<Object, ? super ArrayList> m = new HashMap<Object, ArrayList>();
m.put(1, new Object());
m.put(2, list);
Run Code Online (Sandbox Code Playgroud)
上面两个put方法都是抛出编译时错误.但是,当我添加m.put(3, new ArrayList());它时添加到map没有编译时错误.
我很清楚我可以添加new Object()一个值,HashMap因为map声明属于类型< ? super ArrayList>; 这意味着我可以补充一点,高于任何值ArrayList(即超级的ArrayList)和ArrayList下面反对过,但没有什么ArrayList.
这个特殊的概念在Kathy Sierra和Bert Bates的SCJP 6中写得非常好,基于该理论和实例,我认为它应该按照我的理解工作.有人可以帮我理解错误吗?
我试着做:
public class HelloWorld {
public static void main(String... args){
final String string = "a";
final Supplier<?> supplier = string::isEmpty;
System.out.println(supplier);
}
}
Run Code Online (Sandbox Code Playgroud)
我得到:
HelloWorld$$Lambda$1/471910020@548c4f57
Run Code Online (Sandbox Code Playgroud)
我想拿线isEmpty。我怎样才能做到这一点?
编辑:我创建的方法的代码是此之一:
public class EnumHelper {
private final static String values = "values";
private final static String errorTpl = "Can't find element with value `{0}` for enum {1} using getter {2}()";
public static <T extends Enum<T>, U> T getFromValue(T enumT, U value, String getter) {
@SuppressWarnings("unchecked")
final T[] elements = (T[]) ReflectionHelper.callMethod(enumT, values); …Run Code Online (Sandbox Code Playgroud) 假设我们有一个包含这些类的程序:
public interface AbstractItem {
}
public SharpItem implements AbstractItem {
}
public BluntItem implements AbstractItem {
}
public interface AbstractToolbox {
//well the problem starts here...
public List<AbstractItem> getItems();
}
public ExpensiveToolbox implements AbstractToolbox {
private List<SharpItem> items = new ArrayList()<SharpItems>;
public List<SharpItem> getItems() { return this.items; }
}
public CheapTooblox implements AbstractToolbox {
private List<BluntItem> items = new ArrayList()<BluntItem>;
public List<BluntItem> getItems() { return this.items; }
}
Run Code Online (Sandbox Code Playgroud)
容易,对吗?好吧,我们现在想要制作一个这样的方法(在一些随机类中):
public void doImportantStuff(AbstractToolbox toolbox) {
//important stuff!
//this obviously won't …Run Code Online (Sandbox Code Playgroud) 在泛型
class A<T extends Number> 被允许
但
class A<T super Integer> 不被允许
我没有明白这一点.这可能听起来像新手问题,但我陷入其中
假设我们有一个声明为的谓词Predicate<? super SomeClass>.我天真地期望它适用于SomeClass层次结构中的任何超类,包括Object.
但是这个谓词不适用于Object.我收到以下错误:
Predicate类型中的方法测试(捕获超级SomeClass的#3)不适用于参数(Object)
演示.
为什么Predicate<? super SomeClass>不适用于某个实例Object?
代码:
import java.util.*;
import java.lang.*;
import java.io.*;
import java.net.URL;
import java.util.function.Predicate;
/* Name of the class has to be "Main" only if the class is public. */
class Ideone
{
public static void main (String[] args) throws java.lang.Exception
{
Predicate<? super URL> p = u -> u.getFile().isEmpty();
p.test(new Object());
}
}
Run Code Online (Sandbox Code Playgroud) java ×8
generics ×7
java-8 ×2
scala ×2
collections ×1
covariance ×1
hashmap ×1
inheritance ×1
methods ×1
polymorphism ×1
superclass ×1
wildcard ×1