public @interface InnerAnnotation {
String value() default "hello";
}
public @interface OuterAnnotation {
InnerAnnotation value() default ???
}
Run Code Online (Sandbox Code Playgroud)
还有一种情况:
public @interface AnotherOuterAnnotation {
InnerAnnotation[] value() default ??? UPD: {}
}
Run Code Online (Sandbox Code Playgroud) 这直接受到这个问题的启发.
有许多引用/声明,当应用于布尔运算符时,按位运算符不会短路.换句话说boolean a = f() & g(),where f()和g()both都返回boolean,两者都将被评估.
但是,JLS只说:
15.22.2布尔逻辑运算符&,^和|
当两个操作数都是&,^或|时 operator的类型为boolean或Boolean,则按位运算符表达式的类型为boolean.在所有情况下,操作数都根据需要进行拆箱转换(第5.1.8节).对于&,如果两个操作数值都为真,则结果值为true; 否则,结果是错误的.
对于^,如果操作数值不同,则结果值为true; 否则,结果是错误的.
对于|,如果两个操作数值都为false,则结果值为false; 否则,结果是真的.
这如何保证两个操作数都被实际评估?除此之外xor,如果其中一个参数(可能是第二个/右边首先被评估)违反条件,您仍然可以中断并返回结果.
例如.a & b只需要评估b为false就可以将表达式计算为false.
请注意:我不是问它是否以这种方式实现(不会短路) - 当然是.
我在问:
短路实施会违反语言标准吗?
这是来自JLS 17.5:
最终字段的使用模型很简单.在该对象的构造函数中设置对象的最终字段.在对象的构造函数完成之前,不要在另一个线程可以看到的位置写入对正在构造的对象的引用.如果遵循此原因,那么当另一个线程看到该对象时,该线程将始终看到该对象的最终字段的正确构造版本.它还将看到那些最终字段引用的任何对象或数组的版本,这些字段至少与最终字段一样是最新的.
JLS 17.5中的讨论包括以下示例代码:
class FinalFieldExample {
final int x;
int y;
static FinalFieldExample f;
public FinalFieldExample() {
x = 3;
y = 4;
}
static void writer() {
f = new FinalFieldExample();
}
static void reader() {
if (f != null) {
int i = f.x; // guaranteed to see 3
int j = f.y; // could see 0
}
}
}
Run Code Online (Sandbox Code Playgroud)
我尝试重用这段代码来复制上面的情况,这就是我所拥有的:
public class FinalFieldThread extends Thread {
public static void main(String[] args) {
ThreadA …Run Code Online (Sandbox Code Playgroud) 我一直以为enum hashCode在Java中引用了序数,因为序数似乎是hashCode的完美候选者,但事实证明它的枚举hashCode实际上是指默认的hashCode对象实现.
我明白,这并不与JLS相矛盾,但这让我感到惊讶,我想不出为什么会这样做.虽然我猜JVM,可能依赖于它以某种方式提供独特的保证,但这不再适用于64位JVM.
我已经检查过JDK 1.6和最新的JDK 7,这两种方式都是一样的.
有没有人知道原因,是这样做的?
使用序数作为hashCode是完全合理的,因为它满足了所需的所有凭证,而且从一个JVM开始到另一个JVM开始甚至是一致的,这不是必需的,但是很好.
设C是声明受保护成员的类.仅允许在C的子类S的主体内访问.
此外,如果Id表示实例字段或实例方法,则:
如果访问是通过限定名称Q.Id,其中Q是ExpressionName,则当且仅当表达式Q的类型是S或S的子类时才允许访问.
如果访问是通过字段访问表达式E.Id,其中E是主表达式,或通过方法调用表达式E.Id(...),其中E是主表达式,则允许访问当且仅当如果E的类型是S或S的子类.
限定名称和字段访问表达式之间有什么区别?
我将通过JLS 7来理解类型转换第5.5.1节.
它说:给定编译时引用类型S(源)和编译时引用类型T(目标),如果由于以下规则没有发生编译时错误,则从S到T存在转换转换.如果S是类类型:
他们说得很清楚,如果S和T有两种类型的第4.10节,然后
我无法找到| S |的含义 .请帮助我理解| S |的含义 ?它是指属性的数量和类型还是其他东西.我试图在JLS中搜索它,但找不到它的含义.提前致谢.
以下(Java)代码是否合法?
class Test {
Object foo() {return "";}
boolean bar() {return foo() == true;}
}
Run Code Online (Sandbox Code Playgroud)
它不会针对JDK 6编译,但在7+上似乎没问题.规格有变化吗?修复了一个错误吗?我一直在http://bugs.eclipse.org/bugs/show_bug.cgi?id=416950上讨论过这个问题.
我正在阅读jls 8,我被卡在例8.1.2-1上,Mutually Recursive Type Variable Bounds我搜索了stackoverflow,并发现了一个什么是相互递归类型的问题?但这不是Java方面的问题.
例8.1.2-1.相互递归类型变量边界
interface ConvertibleTo<T> {
T convert();
}
class ReprChange<T extends ConvertibleTo<S>,
S extends ConvertibleTo<T>> {
T t;
void set(S s) { t = s.convert(); }
S get() { return t.convert(); }
}
Run Code Online (Sandbox Code Playgroud)
这是什么递归类型和相互递归类型在Java中意味着什么?
这T extends ConvertibleTo<S>, S extends ConvertibleTo<T>意味着什么?
如果我只是用T extends ConvertibleTo<S>作为类型参数类ReprChange我收到编译时错误?
JLS 的内存模型部分(17.4)以合理的细节描述了volatile非volatile读写的语义,以及与某些其他结构(如监视器进入和退出)的交互.
然而,这并不能完全解释的语义compareAndSwap,也不lazySet在java.util.concurrent.atomic中*类.因为compareAndSet,你有javadoc包中的blurb :
compareAndSet and all other read-and-update operations such as getAndIncrement
have the memory effects of both reading and writing volatile variables.
Run Code Online (Sandbox Code Playgroud)
lazySet 提供了一些更难以理解的模糊:
lazySet has the memory effects of writing (assigning) a volatile variable
except that it permits reorderings with subsequent (but not previous)
memory actions that do not themselves impose reordering constraints with
ordinary non-volatile writes. Among other usage contexts, lazySet may …Run Code Online (Sandbox Code Playgroud) 背景:最近我写了一个答案,建议我编写以下代码:
Files.write(Paths.get("PostgradStudent.csv"),
Arrays.stream(PGstudentArray).map(Object::toString).collect(Collectors.toList()),
StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
Run Code Online (Sandbox Code Playgroud)
经过一番思考,我说:“我实际上不需要这里的列表,我只需要一个Iterable<? extends CharSequence>”。
就像Stream<T>一种方法一样Iterator<T> iterator(),然后我想到了,这很容易:
Iterable<? extends CharSequence> iterable = () -> Arrays.stream(arr).map(Object::toString).iterator();
Run Code Online (Sandbox Code Playgroud)
(针对这个问题,我将其提取到一个局部变量中,我想最后进行内联。)
不幸的是,如果没有其他类型提示,则无法编译该代码:
error: incompatible types: bad return type in lambda expression
Iterable<? extends CharSequence> iterable = () -> Arrays.stream(arr).map(Object::toString).iterator();
^
Iterator<String> cannot be converted to Iterator<CharSequence>
Run Code Online (Sandbox Code Playgroud)
当然添加一些类型提示将使这项工作:
Iterable<? extends CharSequence> iterable2 = (Iterable<String>) () -> Arrays.stream(arr).map(Object::toString).iterator();
Iterable<? extends CharSequence> iterable3 = () -> Arrays.stream(arr).<CharSequence>map(Object::toString).iterator();
Run Code Online (Sandbox Code Playgroud)
以我的理解,Java编译器执行以下操作:
Iterable<? extends CharSequence>。() -> Iterator<? …java ×10
jls ×10
annotations ×1
autoboxing ×1
casting ×1
concurrency ×1
enums ×1
final ×1
hashcode ×1
lambda ×1
operators ×1
recursion ×1
types ×1