我今天碰到了一些我发现有问题的代码.这是一个简化的例子(不现实).
public interface IListable {
//returns first n items from list
public ArrayList getFirstNThings(int n);
//returns last n items from list
public ArrayList getLastNThings(int n);
}
Run Code Online (Sandbox Code Playgroud)
然后有一个像这样的实现者:
public GroceryList implements IListable {
private ArrayList<GroceryItem> groceries;
public GroceryList() {
this.groceries = new ArrayList<GroceryItem>();
}
public ArrayList<GroceryItem> getFirstNThings(int n) {
ArrayList<GroceryItem> firstNThings = new ArrayList<GroceryItem>();
for (int i=0; i < n; i++) {
firstNThings.add(this.groceries.get(i));
}
return firstNThings
}
public ArrayList<GroceryItem> getLastNThings(int n) {
ArrayList<GroceryItem> lastNThings = new ArrayList<GroceryItem>();
for (int i=this.groceries.size(); i …Run Code Online (Sandbox Code Playgroud) 我正在查看Java Generics文档并找到这段代码,
public class WildcardError {
void foo(List<?> l) {
//This give a compile time error
l.set(0,l.get(0));
}
}
Run Code Online (Sandbox Code Playgroud)
我可以理解,我们从a中获取一个元素List<?>并尝试将其设置为另一个元素List<?>.所以编译器会出错.我的问题是,当2个列表不同时,l.set(0, m.get(0))这里列出l并且m不同,这是有道理的.但在上面的例子中,l和l列表相同.为什么编译器不够聪明才能看到它?实施起来难吗?
编辑:我知道我可以通过辅助方法或使用T而不是使用?.来修复它.只是想知道为什么编译器不会为我做这件事.
在阅读了Sun关于泛型的文档之后,我转到了http://docs.oracle.com/javase/tutorial/java/generics/QandE/generics-questions.html上的Q和E部分.
对于Q8 -
编写一个通用方法来查找列表[begin,end]范围内的最大元素.
我写的代码是:
private static <T extends Comparable<T>> T max(List<T> l, int i, int j) {
List<T> sublist = l.subList(i, j);
System.out.println("Sublist "+sublist);
int c = 0;T max = null;
for(T elem: sublist) {
if(c == 0 || max.compareTo(elem) < 0) {
max = elem;
} ++c;
}
return max;
}
Run Code Online (Sandbox Code Playgroud)
而Sun的回答是:
public static <T extends Object & Comparable<? super T>>
T max(List<? extends T> list, int begin, int end) {
T maxElem = list.get(begin);
for …Run Code Online (Sandbox Code Playgroud) 以下代码给出了该行的错误 l.add
List<? extends Number> l = new ArrayList<Integer>();
l.add(1);
Run Code Online (Sandbox Code Playgroud)
并强迫我把它写成 l.add(1, null);
为什么会这样?
有时候,我很多时候会在文档中看到这种情况.它让我想知道要输入什么.有人可以用明确的愚蠢的文字向我解释这个含义:D.怎么样:
ArrayList(Collection<? extends E> c)
Run Code Online (Sandbox Code Playgroud)
最终用作这个:
new ArrayList<>(Arrays.asList("a","b","c"));
Run Code Online (Sandbox Code Playgroud)
所以我不需要通过谷歌搜索来问这个"问题",而是能够自己解决这个问题.
Collections.copy方法签名是,
public static <T> void copy(List<? super T> dest, List<? extends T> src)
Run Code Online (Sandbox Code Playgroud)
只是想知道dest类型是否必须<? super T>而不仅仅是<T>?
public static void main(String[] args)
{
simpleCopy(new ArrayList<Number>(), new ArrayList<Number>());
simpleCopy(new ArrayList<Number>(), new ArrayList<Integer>());
}
public static <T> void simpleCopy(Collection<T> dest, Collection<? extends T> src)
{
for (T element : src)
dest.add(element);
}
Run Code Online (Sandbox Code Playgroud) 鉴于:
public class Testcase {
public static <E> List<List<E>> transform(List<List<E>> list) {
return list;
}
public static <E> List<List<? extends E>> transform2(List<List<? extends E>> list) {
return list;
}
public static void main(String[] args) {
List<List<Integer>> known = new ArrayList<>();
List<List<? extends Number>> unknown = new ArrayList<>();
transform(known); // works
transform(unknown); // fails
transform2(known); // fails
transform2(unknown); // works
}
}
Run Code Online (Sandbox Code Playgroud)
编译器接受transform(known)但抱怨:
cannot infer type-variable(s) E
(argument mismatch; List<List<? extends Number>> cannot be converted to List<List<E>>)
where E …Run Code Online (Sandbox Code Playgroud) 这可能是一个非常愚蠢的问题,但即使在长时间挠头之后我也无法理解这种差异.
我正在浏览scala泛型页面:https://docs.scala-lang.org/tour/generic-classes.html
据说这里
注意:泛型类型的子类型是不变的.这意味着如果我们有一堆Stack [Char]类型的字符,那么它就不能用作Stack [Int]类型的整数堆栈.这将是不合理的,因为它将使我们能够在字符堆栈中输入真正的整数.总之,Stack [A]只是Stack [B]的子类型,当且仅当B = A时.
我完全理解这一点,我无法Char在Int需要的地方使用.但是,我的Stack班级只接受A类型(即invariant).如果我把Apple,Banana或Fruit放入其中,它们都会被接受.
class Fruit
class Apple extends Fruit
class Banana extends Fruit
val stack2 = new Stack[Fruit]
stack2.push(new Fruit)
stack2.push(new Banana)
stack2.push(new Apple)
Run Code Online (Sandbox Code Playgroud)
但是,在下一页(https://docs.scala-lang.org/tour/variances.html)上,它说类型参数应该是协变的+A,那么即使是添加子类型,Fruit示例如何工作呢?invariant.
希望我对我的问题很清楚.如果有更多信息,请告诉我.需要添加.
有
class BaseClass implements IData ();
class ChildClassA() extends BaseClass;
class ChildClassB() extends BaseClass;
Run Code Online (Sandbox Code Playgroud)
既然做不到
List<BaseClass> aList = new ArrayList<ChildClassA>()
Run Code Online (Sandbox Code Playgroud)
所以有一个
List<? extends IData> aList
for pointint to either
ArrayList<ChildClassA>(),
or
ArrayList<ChildClassB>()
Run Code Online (Sandbox Code Playgroud)
的aList是通过其他路由在运行时建立,并且该代码部分具有如下功能:取List<IData>从所述aList
问题是如果List<? extends IData> aList 指向ArrayList<ChildClassA>() 或 ArrayList<ChildClassB>(),
可以ListData<IData> outputList = (List<IData>) aList吗?如下所示:
(似乎它正在工作,但不确定是否有更好的方法来分配除了强制转换之外的泛型数组.)
编辑:输出List<IData> outputList 是为了只读使用(不可变),没有插入/删除,它只会迭代IData以对IData真正的反应作出反应.
List<? extends IData> aList = new ArrayList<ChildClassA>();
ListData<IData> outputList = (List<IData>)aList
List<? extends IData> aList = new ArrayList<ChildClassB>();
ListData<IData> …Run Code Online (Sandbox Code Playgroud) 为什么map将其输入作为 aFunction类型<? super P_OUT, ? extends R>而不是<P_OUT, ? extends R>?
例如,当我这样做时,
List<Integer> list = new ArrayList<>();
list.stream().map(xyz -> {}); // Here xyz is always of type Integer for this instance.
// Then why does it take input as "? super Integer"?
Run Code Online (Sandbox Code Playgroud)
是不是因为没有限制方法引用?这是唯一的用例吗?
java ×9
generics ×7
collections ×2
interface ×1
java-8 ×1
java-stream ×1
javadoc ×1
oop ×1
scala ×1
wildcard ×1