假设我们有一个包含这些类的程序:
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> 不被允许
我没有明白这一点.这可能听起来像新手问题,但我陷入其中
我试图在一定深度上理解下界通配符的用法.我正在尝试编写一个通用方法copy,将一个内容复制List到另一个.我想出了这个方法签名:
<T> void copy(List<T> dest, List<? extends T> src)
Run Code Online (Sandbox Code Playgroud)
我认为这个签名是全面的,以解决所有情况.但是,我在Java Collections类中看到方法签名是这样的:
<T> void copy(List<? super T> dest, List<? extends T> src)
Run Code Online (Sandbox Code Playgroud)
我不明白为什么他们使用List<? super T> dest而不仅仅是List<T> dest.他们的签名是否有一些额外的灵活性?
假设我们有一个声明为的谓词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) 如果我理解正确,Integer[]是一个子类型Object[].你可以这样做
Object[] objs = new Integer[] { 1, 2, 3 };
Run Code Online (Sandbox Code Playgroud)
在玩var-args时我意识到,似乎编译器"过度接近"数组类型没有明显的原因.
例如,下面的程序打印123 123.如果印刷它会不会有意义/更精确123 6?
class Test {
public static Object combine(Object... objs) {
if (objs instanceof Integer[]) {
int sum = 0;
for (Integer i : (Integer[]) objs)
sum += i;
return sum;
} else {
String concat = "";
for (Object o : objs)
concat += o;
return concat;
}
}
public static void main(String[] args) {
System.out.println(combine("1", "2", "3")); …Run Code Online (Sandbox Code Playgroud) 我正在尝试开发一个通用的表加载器,该模式在运行时是已知的.这需要具有包含不同类型的元素的列表,并支持各种get和诸如设置方法的类getInt(int index),asString(int index),asStringList(int index).元素我考虑的类型有Integer,Double,String,和List<Integer>,List<Double>和List<String>.每个元素的实际类型在运行时是已知的,我将它们存储在描述其模式的List中以供进一步处理.
我的问题是:我应该将这些元素列表存储在List<Object>或中List<? extends Object>吗?还是有更好的方法来实现这样的课程?
我有一个POJO指定为:MyClass<U>,其中U是泛型类型参数.我正在尝试编写一个实用程序方法,它接受类引用Class<T>并填充类型Map<String, T>的地图(接受要填充的地图).
这种方法实现如下:
static void populateMap(Map<String, T> map, Class<T> type) {
...
// Parses into the specified type and returns an object of that type.
T obj = parse(..., type);
map.put (key, obj);
...
return map;
}
Run Code Online (Sandbox Code Playgroud)
编译好了.在我的调用者中,我尝试使用任何MyClass实例(无论类型)填充地图作为值.因此我使用以下代码:
// Loses type information
Map<String, MyClass<?>> m = new HashMap<>();
populateMap(m, MyClass.class);
Run Code Online (Sandbox Code Playgroud)
这不编译.编译错误:
populate(Map<String,T>, Class<T>)类型...中的方法不适用于参数(Map<String,MyClass<?>>, Class<MyClass>)
我怎样才能解决这个问题?
Collections.copy 定义为:
public static <T> void copy(List<? super T> dest, List<? extends T> src)
Run Code Online (Sandbox Code Playgroud)
我理解它是如何工作的,没有任何问题.我尝试用另一种方式展示相同的:
public static <T, E extends T> void copy(List<T> dest, List<E> src){
for(E e: src){
dest.add(e);
}//ignore implementation. it has flaws. The focus is declaration of copy
}
Run Code Online (Sandbox Code Playgroud)
这个想法很简单.对于从源读取的任何类型,目标类型应为其超类型.所以现在你可以这样做:
copy(new ArrayList<Number>(), new ArrayList<Number>());
copy(new ArrayList<Number>(), new ArrayList<Integer>());
copy(new ArrayList<Object>(), new ArrayList<Number>());
copy(new ArrayList<Object>(), new ArrayList<Double>());
Run Code Online (Sandbox Code Playgroud)
它看起来还不错.但是与实际的Collections.copy相比,上面有任何缺陷吗?从类型信息的角度来看,实际上是否超过上述的任何地方?
我正在阅读java源代码,我发现如下:http:
//www.java2s.com/Code/JavaAPI/java.util/newTreeSetEComparatorsuperEc.htm
我不明白为什么这个构造函数的参数是<? super E>.
正如我的理解,应该是<? extend E>代替<? super E>,因为如果E是可比的,E的儿童必须在可比,而E的父母可能不.
可能重复:
在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.
java ×10
generics ×8
collections ×2
types ×2
comparator ×1
inheritance ×1
object ×1
polymorphism ×1