我在Oracle的网站上读到了Java的类型擦除.
什么时候发生类型擦除?在编译时还是运行时?当班级加载?当类被实例化时?
很多站点(包括上面提到的官方教程)都说在编译时会发生类型擦除.如果在编译时完全删除了类型信息,那么当调用使用泛型的方法而没有类型信息或错误的类型信息时,JDK如何检查类型兼容性?
考虑以下示例:Say class A有一个方法,empty(Box<? extends Number> b).我们编译A.java并获取类文件A.class.
public class A {
public static void empty(Box<? extends Number> b) {}
}
Run Code Online (Sandbox Code Playgroud)
public class Box<T> {}
Run Code Online (Sandbox Code Playgroud)
现在我们创建另一个类B,该类empty使用非参数化参数(原始类型)调用该方法:empty(new Box()).如果我们编译B.java与A.class在类路径中,javac的是足够聪明,引发警告.所以A.class 有一些类型信息存储在其中.
public class B {
public static void invoke() {
// java: unchecked method invocation:
// method empty in class A is applied to given types
// required: Box<? extends java.lang.Number>
// found: …Run Code Online (Sandbox Code Playgroud) 假设我有以下代码:
CompletableFuture<Integer> future
= CompletableFuture.supplyAsync( () -> 0);
Run Code Online (Sandbox Code Playgroud)
thenApply 案件:
future.thenApply( x -> x + 1 )
.thenApply( x -> x + 1 )
.thenAccept( x -> System.out.println(x));
Run Code Online (Sandbox Code Playgroud)
这里输出为2.现在如下thenApplyAsync:
future.thenApplyAsync( x -> x + 1 ) // first step
.thenApplyAsync( x -> x + 1 ) // second step
.thenAccept( x -> System.out.println(x)); // third step
Run Code Online (Sandbox Code Playgroud)
我在这个博客中读到,每个thenApplyAsync都是在一个单独的线程中执行,并且"同时"(这意味着thenApplyAsyncs在thenApplyAsyncs完成之前开始跟随),如果是这样,如果第一步没有完成,第二步的输入参数值是多少?
如果不采取第二步,第一步的结果会在哪里?第三步将采取哪一步的结果?
如果第二步必须等待第一步的结果那么重点是Async什么?
这里x - > x + 1只是为了表明这一点,我想知道的是在非常长的计算情况下.
我试图理解CompletableFuture,并遇到了2个方法,然后是ApplyAsync然后是Make.我试图了解这两者之间的区别.
CompletableFuture<String> completableFuture = CompletableFuture.supplyAsync(() -> {
System.out.println(Thread.currentThread().getName() + " Printing hello");
return "Hello";
}).thenCompose((String s) -> {
return CompletableFuture.supplyAsync(() -> {
System.out.println(Thread.currentThread().getName() + " Adding abc");
return "abc "+s;});
}).thenApplyAsync((String s) -> {
System.out.println(Thread.currentThread().getName() + " Adding world");
return s + " World";
}).thenApplyAsync((String s) -> {
System.out.println(Thread.currentThread().getName() + " Adding name");
if (false) {
throw new RuntimeException("Oh no exception");
}
return s + " player!";
}).handle((String s, Throwable t) -> {
System.out.println(s != null ? s : "BLANK"); …Run Code Online (Sandbox Code Playgroud) 我正在学习CompletableFutures.
我不是在问和之间的区别thenApply()thenCompose().相反,我想问一下感觉不对的代码"气味",以及实际可能证明它的理由.
从CompletableFuture我到目前为止看到的用法来看,似乎你从来没有这样:
CompletableFuture<String> foo = getSomething().thenApply((result) -> { ... });
Run Code Online (Sandbox Code Playgroud)
这不是:
String foo = getSomething().thenCompose((result) -> { ... });
Run Code Online (Sandbox Code Playgroud)
要返回未来,您必须使用thenCompose(),否则thenApply().
然而,从经验来看,语言并没有设法消除每次都做出这种明确的选择,这似乎很奇怪.例如,是否有一个单一的方法,thenDo()其返回类型是从returnlambda中推断出来的(在编译期间)?它可能然后被给予thenApply或thenCompose在编译时般的性能以及.
但我确信有一个很好的理由采用不同的方法,所以我想知道原因.
是因为在Java中从lambda推断返回类型是危险还是不可能?(我也是Java的新手.)
是不是因为有一种情况,单个方法确实不明确,唯一的解决方案是使用单独的方法?(我想象可能,嵌套CompletableFuture或复杂的界面和泛型.)如果是这样,有人可以提供一个明确的例子吗?
是出于其他原因还是有记录的推荐?