这是来自第三方库API的真实示例,但已简化.
使用Oracle JDK 8u72编译
考虑这两种方法:
<X extends CharSequence> X getCharSequence() {
return (X) "hello";
}
<X extends String> X getString() {
return (X) "hello";
}
Run Code Online (Sandbox Code Playgroud)
两者都报告了"未经检查的演员"警告 - 我明白了.困扰我的是我为什么打电话
Integer x = getCharSequence();
Run Code Online (Sandbox Code Playgroud)
它编译?编译器应该知道Integer没有实现CharSequence.打电话给
Integer y = getString();
Run Code Online (Sandbox Code Playgroud)
给出错误(如预期的那样)
Run Code Online (Sandbox Code Playgroud)incompatible types: inference variable X has incompatible upper bounds java.lang.Integer,java.lang.String
有人可以解释为什么这种行为被认为是有效的?它会有用吗?
客户端不知道此调用是不安全的 - 客户端的代码在没有警告的情况下编译.为什么编译器不会警告/发出错误?
另外,它与这个例子有什么不同:
<X extends CharSequence> void doCharSequence(List<X> l) {
}
List<CharSequence> chsL = new ArrayList<>();
doCharSequence(chsL); // compiles
List<Integer> intL = new ArrayList<>();
doCharSequence(intL); // …Run Code Online (Sandbox Code Playgroud) 有人可以向我解释以下行为吗?
我有一个列表X并使用该addAll()方法添加元素.这些元素由使用泛型类型的方法返回.方法getA()返回< T extends A >与A作为一类.方法getI()返回< T extends I >与I作为一个接口(见下面的代码).
差异:listX.addAll(getA())我得到编译错误(如预期的那样),但是listX.addAll(getI())编译(当元素被强制转换时抛出运行时错误X).
简化代码:
interface I {}
class A implements I {}
class X {}
public void test() {
List<X> listX = new ArrayList<>();
listX.addAll(getA());
listX.addAll(getI());
for (X x : listX) {}
}
public <T extends A> List<T> getA() {
return new ArrayList<>();
}
public <T extends I> List<T> getI() …Run Code Online (Sandbox Code Playgroud) 我知道之前已经发布了类似的类型推断问题(Java编译器选择了错误的重载或为什么Java 8泛型类型推断选择了这个重载?)但我认为我们在这里选择了一个更有趣的案例.
public class TemplateMethod {
public static void main(String[] args) {
System.out.println(System.getProperty("java.version"));
method("a", "b");
method("a", 5);
method("a", new B().get());
}
public static void method(String s, String cause) {
System.out.println("String");
}
public static void method(String s, Object parameters) {
System.out.println("Object");
}
public static interface Base {
String methodToImplement();
}
public static class Impl implements Base {
public String methodToImplement() {
return "Impl.methodToImplement";
}
}
public static class B {
public <T extends Base> T get() { …Run Code Online (Sandbox Code Playgroud) 有这样的方法吗?
public <P, T extends List<P>> T getAwesomeList() {
// ...
}
Run Code Online (Sandbox Code Playgroud)
怎么编译没有任何警告?
Set<String> test = getAwesomeList();
Run Code Online (Sandbox Code Playgroud)
我认为这与通用擦除有关,但不确定编译器是怎么回事.这种情况发生在Java 7上,8时你会收到编译错误.
J8上有什么变化让这个不能编译?
更新:
经过仔细检查后,它还可以在Java 8上编译.
我最近被以下 Java 代码惊呆了:
interface Common {}
interface A extends Common {}
static class B implements Common {}
static class Impl {
private A a;
public <T extends A> T translate() {
return (T) a;
}
}
static class Usage {
public void use() {
Impl impl = new Impl();
B b = impl.translate(); // Why does this compile?
}
}
Run Code Online (Sandbox Code Playgroud)
我本来期望的是在类型约束Impl.translate不会允许将结果存储在类型B由编译器所接受,考虑到B不延长A。代码UncheckedCastException在运行时抛出一个,而不是编译器错误。
这仅在方法返回类型时发生T;如果它是方法参数:
public <T extends A> …Run Code Online (Sandbox Code Playgroud) 与2的Mockito,应当ArgumentMarchers.any()被用来代替像更具体的匹配器ArgumentMatchers.anyString()或ArgumentMatchers.anyList()例如?应该使用特定的匹配器使代码更具可读性吗?
根据经验,使用本机时OBJETS( ,int,long,double),boolean特定的匹配器anyInt(),anyLong(),anyDouble()或anyBoolean()是优选的。但是其他匹配器呢?有任何想法吗?谢谢。