有人可以解释为什么String和Class注释参数的预期不同吗?为什么编译器需要Classes的文字,wherby也接受字符串的常量?
使用Spring的@RequestMapping的工作示例:
public class MyController {
public static final String REQUEST_MAPPING = "/index.html";
@RequestMapping(MyController.REQUEST_MAPPING) // ALL OK!
...
}
Run Code Online (Sandbox Code Playgroud)
使用TestNG的@Test的WTF示例:
public class MyControllerTest {
public static final Class TEST_EXCEPTION = RuntimeException.class;
@Test(expectedExceptions = MyControllerTest.TEST_EXCEPTION) // compilation error, WTF:
// The value for annotation attribute Test.expectedExceptions must be a class literal
...
}
Run Code Online (Sandbox Code Playgroud)
什么工作当然是@Test(expectedExceptions = RuntimeException.class).但为什么?我看到的注释参数的唯一区别是它的类型:String vs Class.为什么Java编译器也接受String常量,但只接受类文字?
给定一个f1() + f2()*f3()带有3个方法调用的表达式,java首先计算加法运算(的操作数):
int result = f1() + f2()*f3();
f1 working
f2 working
f3 working
Run Code Online (Sandbox Code Playgroud)
我(错误地)期望f2()首先被呼叫,然后被呼叫f3(),最后被呼叫f1()。因为乘法应在加法之前求值。
所以,我在这里不了解JLS-我想念什么?
15.7.3。评估尊重括号和优先权
Java编程语言遵守 由括号显式表示和由运算符优先级隐式表示的评估顺序。
在此示例中,如何精确地遵守运算符优先级?
JLS在15.7.5中提到了一些例外。其他表达式(方法调用表达式(§15.12.4),方法引用表达式(§15.13.3))的评估顺序,但是我不能将这些异常中的任何一个应用于我的示例。
我知道JLS保证二进制运算的操作数从左到右求值。但是在我的示例中,为了了解方法调用顺序,有必要了解首先考虑哪个操作(及其两个操作数!)。我在这里错了-为什么?
更多示例:
int result = f1() + f2()*f3() + f4() + f5()*f6() + (f7()+f8());
Run Code Online (Sandbox Code Playgroud)
自豪地生产:
f1 working
f2 working
f3 working
f4 working …Run Code Online (Sandbox Code Playgroud) java evaluation expression-evaluation operator-precedence jls
免责声明:我意识到我可以在运行时用Java生成这个,这是一个非常特殊的情况下需要的,同时性能测试一些代码.我发现了一种不同的方法,所以现在这只是一种好奇心而不是任何实际的东西.
我已经尝试了以下作为静态字段,作为实例字段,并直接在构造函数中初始化.每次eclipse通知我"构造函数TestData()的代码超过65535字节限制"或"静态初始化程序的代码超过65535字节限制".
有10,000个整数.如果每个int是4个字节(32位),那么那不是40,000个字节吗?除了仅构建数组的数据之外,还有更多的25,0000字节的开销吗?
使用这一小段python生成数据:
#!/usr/bin/python
import random;
print "public final int[] RANDOM_INTEGERS = new int[] {";
for i in range(1,10000):
print str(int(random.uniform(0,0x7fffffff))) + ",";
print "};";
Run Code Online (Sandbox Code Playgroud)
这是一个小样本:
public final int[] RANDOM_INTEGERS = new int[] {
963056418, 460816633, 1426956928, 1836901854, 334443802, 721185237, 488810483,
1734703787, 1858674527, 112552804, 1467830977, 1533524842, 1140643114, 1452361499,
716999590, 652029167, 1448309605, 1111915190, 1032718128, 1194366355, 112834025,
419247979, 944166634, 205228045, 1920916263, 1102820742, 1504720637, 757008315,
67604636, 1686232265, 597601176, 1090143513, 205960256, 1611222388, 1997832237,
1429883982, 1693885243, 1987916675, 159802771, 1092244159, 1224816153, 1675311441,
1873372604, 1787757434, 1347615328, …Run Code Online (Sandbox Code Playgroud) Java允许某些关键字后跟语句或语句块.例如:
if (true)
System.out.println("true");
do
System.out.println("true");
while (true);
Run Code Online (Sandbox Code Playgroud)
编译以及
if(true) {
System.out.println("true");
}
do {
System.out.println("true");
} while (true);
Run Code Online (Sandbox Code Playgroud)
这也适用于像关键字for,while等等.
但是,有些关键字不允许这样做.synchronized需要一个块语句.相同try ... catch ... finally,这需要在关键字后面至少有两个块语句.例如:
try {
System.out.println("try");
} finally {
System.out.println("finally");
}
synchronized(this) {
System.out.println("synchronized");
}
Run Code Online (Sandbox Code Playgroud)
有效,但以下内容无法编译:
try
System.out.println("try");
finally
System.out.println("finally");
synchronized (this)
System.out.println("synchronized");
Run Code Online (Sandbox Code Playgroud)
那么为什么Java中的某些关键字需要块语句,而其他关键字允许块语句以及单个语句?这是语言设计的不一致,还是有某种原因?
有了'assert'关键字引入的可能广为人知的例外,Java语言规范是否曾发生变化,导致旧代码不再与JDK的新源代码兼容?
总结到目前为止(非常感谢评论):
如果代码使用在Java语言规范(JLS)的更高版本中引入的关键字之一的声明,则"旧"Java代码在升级到更高版本时可能会导致编译错误:
请参考以下代码.当我运行代码时,我能够更改最终的非静态变量的值.但是,如果我尝试更改最终静态变量的值,那么它会抛出java.lang.IllegalAccessException.
我的问题是为什么它不会在非静态最终变量的情况下抛出异常,反之亦然.为什么不同?
import java.lang.reflect.Field;
import java.util.Random;
public class FinalReflection {
final static int stmark = computeRandom();
final int inmark = computeRandom();
public static void main(String[] args) throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
FinalReflection obj = new FinalReflection();
System.out.println(FinalReflection.stmark);
System.out.println(obj.inmark);
Field staticFinalField = FinalReflection.class.getDeclaredField("stmark");
Field instanceFinalField = FinalReflection.class.getDeclaredField("inmark");
staticFinalField.setAccessible(true);
instanceFinalField.setAccessible(true);
instanceFinalField.set(obj, 100);
System.out.println(obj.inmark);
staticFinalField.set(FinalReflection.class, 101);
System.out.println(FinalReflection.stmark);
}
private static int computeRandom() {
return new Random().nextInt(5);
}
}
Run Code Online (Sandbox Code Playgroud) Java-8允许在接口内部定义静态方法,但仅通过接口名称限制它的调用:
9.4:接口可以声明静态方法,这些方法在不引用特定对象的情况下被调用.
例如:
interface X {
static void y() {
}
}
...
X x = new X() {};
x.y();
Run Code Online (Sandbox Code Playgroud)
导致错误:
error: illegal static interface method call
x.y();
^
the receiver expression should be replaced with the type qualifier 'X'
Run Code Online (Sandbox Code Playgroud)
通常在JLS中,这种禁令有一个解释.在这种情况下,我没有发现任何详细的信息.所以我正在寻找对此规则的全面或权威解释:为什么禁止通过特定对象引用调用静态方法?它打破了什么?
Java规范是否定义了常量的原理,还是留给了推荐角色?
如果在规范中定义,它的定义是什么?
具体而言,以下任何或所有例子都被视为常数吗?如果确实存在部分或全部,是否按照规范或任何其他官方建议进行了考虑?
public static final int ONE = 1;
public static final double TWO = 2.0d;
public static final String THREE = "three";
public static final ImmutableList<Integer> ONE_TWO_THREE = ImmutableList.of(1, 2, 3);
public static final Logger logger = LogManager.getLogManager().getLogger(ThisClass.class);
Run Code Online (Sandbox Code Playgroud) 使用例如AtomicIntegergetVolatile时与getAcquire有什么区别?
PS:这些都与
\n\n\n\n\na\xc2\xa0synchronizes-with\xc2\xa0edge 的源称为\xc2\xa0release,目标称为\xc2\xa0acquire。
\n
来自https://docs.oracle.com/javase/specs/jls/se8/html/jls-17.html#jls-17.3
\n