有人可以解释一下这两种方法之间的区别吗?它们一样吗?就他们解决的问题而言,他们看起来与我相同.如果它们相同,为什么需要?
?
方法#1,无界限
public static void printList(List<?> list) {
for (Object elem : list)
System.out.println(elem + " ");
System.out.println();
}
Run Code Online (Sandbox Code Playgroud)
方法#2,无界:
public static <T> void printList(List<T> list) {
for (Object elem : list)
System.out.println(elem + " ");
System.out.println();
}
Run Code Online (Sandbox Code Playgroud)
方法#1,有界
public static void printList(List<? extends Number> list) {
for (Object elem : list)
System.out.println(elem + " ");
System.out.println();
}
Run Code Online (Sandbox Code Playgroud)
方法#2,有界:
public static <T extends Number> void printList(List<T> list) {
for (Object elem : list)
System.out.println(elem + " ");
System.out.println(); …
Run Code Online (Sandbox Code Playgroud) 我知道为什么不应该这样做.但有没有办法向外行人解释为什么这是不可能的.你可以轻松地向外行解释:Animal animal = new Dog();
.狗是一种动物,但是一系列的狗并不是动物的清单.
在Java中我可以演员:
List<?> j = null;
List<Integer> j2 = (List<Integer>)j;
Run Code Online (Sandbox Code Playgroud)
那么为什么以下失败呢?
List<List<?>> i = null;
List<List<Integer>> i2 = (List<List<Integer>>)i;
Run Code Online (Sandbox Code Playgroud) 我得到以下编译消息:
[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) 简单的课程:
class Pair<K,V> {
}
Run Code Online (Sandbox Code Playgroud)
还有一些任务:
Collection<Pair<String,Long>> c1 = new ArrayList<Pair<String,Long>>();
Collection<Pair<String,Long>> c2 = c1; // ok
Collection<Pair<String,?>> c3 = c1; // this does not compile
Collection<? extends Pair<String,?>> c4 = c1; // ok
Run Code Online (Sandbox Code Playgroud)
为什么第三个子弹不能编译而第四个完全合法?
编译错误:
Type mismatch: cannot convert from Collection<Pair<String,Long>> to Collection<Pair<String,?>>
Run Code Online (Sandbox Code Playgroud) 在下面的代码中,get()
调用它并将结果分配给类型为的变量List<List<?>>
.get()
返回a List<List<T>>
并在类型参数T
设置为的实例上调用?
,因此它应该适合.
import java.util.List;
class Test {
void foo(NestedListProducer<?> test) {
List<List<?>> a = test.get();
}
interface NestedListProducer<T> {
List<List<T>> get();
}
}
Run Code Online (Sandbox Code Playgroud)
但IntelliJ IDEA和Oracle的javac
1.7.0_45版都拒绝我的代码无效.这是'javac'的错误消息:
java: incompatible types
required: java.util.List<java.util.List<?>>
found: java.util.List<java.util.List<capture#1 of ?>>
Run Code Online (Sandbox Code Playgroud)
为什么这段代码无效,即如果允许则会出错?
对于以下代码示例:
public static class Abc<X> { }
public static class Def<Y> { }
public static class Ghi<Z> { }
public void doThis() {
List<?> listOne;
List<Abc<?>> listTwo;
List<Abc<Def<?>>> listThree;
List<Abc<Def<Ghi<?>>>> listFour;
List<Abc<Def<Ghi<String>>>> listFive;
Abc<Def<Ghi<String>>> abcdef;
abcdef = new Abc<Def<Ghi<String>>>();
listOne.add(abcdef); // line 1
listTwo.add(abcdef); // line 2
listThree.add(abcdef); // line 3
listFour.add(abcdef); // line 4
listFive.add(abcdef); // line 5
}
Run Code Online (Sandbox Code Playgroud)
第1,3和4行不编译:
(第1行)
The method add(capture#1-of ?) in the type List<capture#1-of ?> is not applicable for the arguments (Abc<Def<Ghi<String>>>)
Run Code Online (Sandbox Code Playgroud)
(第3行)
The …
Run Code Online (Sandbox Code Playgroud) 我在Java泛型中遇到了有界嵌套通配符的问题.
这是一个常见的案例:
public void doSomething(Set<? extends Number> set) {}
public void callDoSomething() {
Set<Integer> set = new HashSet<Integer>();
doSomething(set);
}
Run Code Online (Sandbox Code Playgroud)
这是标准的Java泛型,工作正常.
但是,如果通配符变为嵌套,则它不再起作用:
public void doSomething(Map<String, Set<? extends Number>> map) {}
public void callDoSomething() {
Map<String, Set<Integer>> map = new HashMap<String, Set<Integer>>();
doSomething(map);
}
Run Code Online (Sandbox Code Playgroud)
这会导致编译器错误.
我尝试了各种演员表和通配符排列,但我无法使其正常工作.我不记得以前看过这个问题了,多年来我一直在使用仿制药.我是否太累了,错过了一些明显的东西?
我有两个嵌套泛型的类.有没有办法摆脱
类型不匹配:无法转换Msg<Value<String>>
为Msg<Value<?>>
错误?在最后一次任务中
public class Value<V> {
V val;
public Value(V val) {
this.val = val;
}
@Override
public String toString() {
return "" + val;
}
}
public class Msg<T> {
T holder;
public Msg( T holder) {
this.holder = holder ;
}
public String toString() {
return "" + holder;
}
public static void main(String[] args) {
Msg<Value<String>>strMsg = new Msg(new Value<String>("abc"));
// This is OK
Msg<?>objMsg = strMsg;
// Type mismatch: cannot convert from …
Run Code Online (Sandbox Code Playgroud) 我有以下BeanValidation代码可以正常工作,并允许验证带有注释的bean:
@EnumValue(enumClass = MyTestEnum.class)
private String field;
public enum MyTestEnum {
VAL1, VAL2;
}
Run Code Online (Sandbox Code Playgroud)
仅在字段值为"VAL1"或"VAL2"时才会进行验证.
public class EnumNameValidator implements ConstraintValidator<EnumValue, String> {
private Set<String> AVAILABLE_ENUM_NAMES;
@Override
public void initialize(EnumValue enumValue) {
Class<? extends Enum<?>> enumSelected = enumValue.enumClass();
Set<? extends Enum<?>> enumInstances = Sets.newHashSet(enumSelected.getEnumConstants());
AVAILABLE_ENUM_NAMES = FluentIterable
.from(enumInstances)
.transform(PrimitiveGuavaFunctions.ENUM_TO_NAME)
.toImmutableSet();
}
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
if ( value == null ) {
return true;
} else {
return AVAILABLE_ENUM_NAMES.contains(value);
}
}
}
Run Code Online (Sandbox Code Playgroud)
我不明白的是为什么我的第一次尝试失败了.使用enumSelected.getEnumConstants()
以上代码代替以上代码:
Set<? extends …
Run Code Online (Sandbox Code Playgroud)