我决定用Java编写一些常见的高阶函数(map,filter,reduce等),这些函数通过泛型是安全类型的,并且我遇到了在一个特定函数中匹配通配符的问题.
为了完整,函子接口是这样的:
/**
* The interface containing the method used to map a sequence into another.
* @param <S> The type of the elements in the source sequence.
* @param <R> The type of the elements in the destination sequence.
*/
public interface Transformation<S, R> {
/**
* The method that will be used in map.
* @param sourceObject An element from the source sequence.
* @return The element in the destination sequence.
*/
public R apply(S sourceObject);
}
Run Code Online (Sandbox Code Playgroud)
令人不安的功能就像一个 …
假设我有以下内容:
class x {
public static void main(String [] args) {
List <?> a = new LinkedList<Object>();
List <? extends Object> b = new LinkedList<Object>();
List <? super Object> c = new LinkedList<Object>();
abc(a, "Hello"); // (1) Error
abc(b, "Hello"); // (2) Error
abc(c, "Hello"); // (3) ok
def(b); // (4) ok
// Showing inference at work
Integer[] a = {10, 20, 30}; // (5)
T is inferred to be ? extends Object
Method signature: ppp(? extends Object, ? extends …Run Code Online (Sandbox Code Playgroud) 可能重复:
在Java中创建泛型类型的实例?
我有一些代码:
public class foo<K> {
public void bar() {
K cheese = new K();
// stuff
}
}
Run Code Online (Sandbox Code Playgroud)
这不编译,Intellij的linter告诉我Type parameter 'K' cannot be instantiated directly.
我将如何实例化新副本K.
有一种方法:
public static <T> void addandDisp(Collection<T> cs, T t)
以下列方式调用:
List<? extends Object> ls2 = new LinkedList<Number>();
addandDisp(ls2,new Object());
Run Code Online (Sandbox Code Playgroud)
这给出了编译时错误.另一方面,如果我们只有一个参数,则调用成功.这是为什么 ?
此外,这是成功的:
List<? super String> ls1 = new LinkedList<String>();
addandDisp(ls1,new String());
Run Code Online (Sandbox Code Playgroud)
虽然这不是:
List<? super String> ls1 = new LinkedList<Object>();
addandDisp(ls1,new Object());
Run Code Online (Sandbox Code Playgroud)
底层逻辑是什么?
以下代码的结果:
public class ListIntegerDemo1 {
public static void addToList(List list) {list.add("0067");list.add("bb");}
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
addToList(list);
System.out.println(list.get(0));
}
}
Run Code Online (Sandbox Code Playgroud)
是"0067".
我本来期望RuntimeException或类似的,因为我将一个String添加到整数列表.
为什么它没有任何问题?
假设我有这两个ArrayLists:
ArrayList<Book> book = new ArrayList<>();
ArrayList<Journal> journal = new ArrayList<>();
Run Code Online (Sandbox Code Playgroud)
Book并且Journal是两个不同的类.
两者Book和Journal对象都有一个getYear()方法.我想创建一个传入未知ArrayList类型的方法,并将传入的年份与列表中的对象进行比较.以下代码为main:
public static void fooBar(int year, ArrayList<?> list)
{
if(list.get(0).getYear() == year) // does not work!
{
}
}
Run Code Online (Sandbox Code Playgroud)
如果将未知类型传递给方法,则无法使用该对象的方法(getYear()).如果不做两个做同样事情的方法(一个用于Book一个用于一个Journal),我怎么能这样做呢?
我正在尝试通过阅读以下内容来学习Java Generics通配符:http: //www.angelikalanger.com/GenericsFAQ/FAQSections/TypeArguments.html#FAQ103
材料中有一个例子:
public class Collections {
public static <T> void copy (List<? super T> dest, List<? extends T> src) {
for (int i=0; i<src.size(); i++)
dest.set(i,src.get(i));
}
}
Run Code Online (Sandbox Code Playgroud)
我想知道我是否可以更改方法签名如下:
public static <T> void copy(List<? super T> dest, List<? extends T> src) {
Run Code Online (Sandbox Code Playgroud)
↓
public static <T> void copy(List<T> dest, List<? extends T> src) {
Run Code Online (Sandbox Code Playgroud)
这两种方法是否存在差异?
例子将不胜感激.
为什么
Predicate<? super Integer> isGreaterThanZero = num -> num.intValue() > 0;
Run Code Online (Sandbox Code Playgroud)
效劳于
isGreaterThanZero.test( new Integer( 2 ));
Run Code Online (Sandbox Code Playgroud)
并不是
Predicate<? extends Number> isGreaterThanZero = num -> num.intValue() > 0;
Run Code Online (Sandbox Code Playgroud)
我认为它们是相同的,因为它Integer 是-a Number
我想这样做:
<T extends java.util.Date> T a(@Nonnull T... dates) {
return b(dates); // compile error
}
<T extends Comparable<T>> T b(T... comparables) {
return comparables[0];
}
Run Code Online (Sandbox Code Playgroud)
但是除非我在其中插入强制类型转换,否则它无法编译a:
<T extends java.util.Date> T a(@Nonnull T... dates) {
return (T) b(dates); // warning about unsafe cast in IntelliJ
}
<T extends Comparable<T>> T b(T... comparables) {
return comparables[0];
}
Run Code Online (Sandbox Code Playgroud)
有趣的是,如果我从a它的泛型中删除它:
java.util.Date a(java.util.Date... dates) {
return b(dates);
}
<T extends Comparable<T>> T b(T... comparables) {
return comparables[0];
}
Run Code Online (Sandbox Code Playgroud)
而且,如果我将原始代码移植到Kotlin,它也可以工作(这使我认为这是Java的限制,而不是根本上不可知的东西):
fun <T: …Run Code Online (Sandbox Code Playgroud) 我总是很难将泛型与集合和通配符一起使用.
所以这是以下地图.我想保留特定类型的数据包类的处理程序集合.
private ConcurrentHashMap<Class<? extends Packet>, List<PacketListener<? extends Packet>>> listeners = new ConcurrentHashMap<>();
Run Code Online (Sandbox Code Playgroud)
而且 PacketListener
public interface PacketListener<T extends Packet> {
public void onOutgoingPacket(Streamer streamer, T packet);
public void onIncomingPacket(Streamer streamer, T packet);
}
Run Code Online (Sandbox Code Playgroud)
现在我想做的是根据传入的数据包类获取侦听器,如下所示:
public <T extends Packet> void addPacketListener(Class<T> clazz, PacketListener<T> listener) {
if (listeners.containsKey(clazz) == false) {
listeners.putIfAbsent(clazz, new LinkedList<PacketListener<T>>()); // ERROR
}
List<PacketListener<? extends Packet>> list = listeners.get(clazz);
list.add(listener);
}
public <T extends Packet> List<PacketListener<T>> getPacketListeners(Class<T> clazz) {
List<PacketListener<T>> list = listeners.get(clazz);// ERROR
if (list == …Run Code Online (Sandbox Code Playgroud)