在Java语言规范的第15.12.2.5节中,它讨论了如何在具有固定arity的方法和可变arity方法(即varargs)中选择最具体的方法.
我在JLS中找不到的是关于两个方法之间的决定,其中一个是固定的arity,另一个是变量arity.例如:
public interface SomeApi {
public String getSomething(String arg); // method 1
public String getSomething(String ... args); // method 2
}
Run Code Online (Sandbox Code Playgroud)
按照人们的预期编译就好(由Yoni概述的原因如下).这个调用代码也编译:
SomeApi api = ...
Object o = api.getSomething("Hello");
Run Code Online (Sandbox Code Playgroud)
如果你运行它,method #1(即非varargs方法)被调用.为什么这个调用代码没有含糊不清?为什么固定arity方法比变量arity方法更具体?有人能指出我对规范的相关部分吗?
有人可以帮助我理解JLS的第15.12.2.5节:最具体的方法吗?
(来自JLS的强行剪切和粘贴如下)
另外,一个名为m的变量arity成员方法比另一个具有相同名称的变量arity成员方法更具体:
- 一个成员方法有n个参数,另一个成员方法有k个参数,其中n> = k.第一个成员方法的参数类型是T1 ,. ..,Tn-1,Tn [],其他方法的参数类型是U1 ,. ..,Uk-1,英国[].如果第二种方法是通用的,那么让R1 ... Rp p1成为它的形式类型参数,让Bl成为Rl的声明边界,1lp,让A1 ... Ap成为推断的实际类型参数(§15.12.2.7)对于这种在初始约束下的调用Ti << Ui,1ik-1,Ti << Uk,kin和let Si = Ui [R1 = A1,...,Rp = Ap] 1ik; 否则让Si = Ui,1ik.然后:对于从1到k-1的所有j,Tj <:Sj,并且对于从k到n的所有j,Tj <:Sk,并且,如果第二种方法是如上所述的通用方法,那么Al <:Bl [R1 = A1,...,Rp = Ap],1lp.
- 一个成员方法具有k个参数,另一个具有n个参数,其中n> = k.第一种方法的参数类型是U1 ,. ..,Uk-1,Uk [],其他方法的参数类型是T1 ,. ..,Tn-1,Tn [].如果第二种方法是通用的,那么让R1 ... Rp p1成为它的形式类型参数,让Bl成为Rl的声明边界,1lp,让A1 ... Ap成为推断的实际类型参数(§15.12.2.7)对于这种在初始约束条件下的调用,Ui << Ti,1ik-1,Uk << Ti,kin和令Si = Ti [R1 = A1,...,Rp = Ap] 1in; 否则让Si = Ti,1in.然后:对于从1到k-1的所有j,Uj <:Sj,并且对于从k到n的所有j,Uk <:Sj,并且,如果第二种方法是如上所述的通用方法,则Al <:Bl [R1 = A1,...,Rp = Ap],1lp.
忽略问题泛型,这是否意味着varargs比子类型更重要,或者在确定一种方法是否比另一种更具体时,子类型比varargs更重要?我无法弄清楚. …
在Java中给出以下内容:
String a = "str";
CharSequence b = "charseq";
Run Code Online (Sandbox Code Playgroud)
你可以写
b = b + a;
Run Code Online (Sandbox Code Playgroud)
但无法编写(产生编译器错误)
b += a;
Run Code Online (Sandbox Code Playgroud)
错误是
incompatible types
found : java.lang.CharSequence
required: java.lang.String
Run Code Online (Sandbox Code Playgroud)
现在在JLS第二版中,这可以通过15.26.2复合赋值运算符的这一行来解释:
All compound assignment operators require both operands to be of primitive type, except for +=, which allows the right-hand operand to be of any type if the left-hand operand is of type String.
但是在JLS第三版中,该注释消失了,关于复合运算符的唯一说明是在15.26.2复合赋值运算符:
A compound assignment expression of the form E1 op= E2 is equivalent to E1 …
在针对双重检查锁定方案的无序写入中提到的示例中(参考: IBM文章和维基百科文章)
在构造函数完全初始化之前,我无法理解为什么Thread1会在同步块中出现的简单原因.根据我的理解,创建"new"和调用构造函数应该按顺序执行,同步锁不应该释放,直到所有工作都没有完成.
请让我知道我在这里缺少什么.
java multithreading synchronization jls double-checked-locking
JLS 3.10.1. Integer Literals http://docs.oracle.com/javase/specs/jls/se7/html/jls-3.html#jls-3.10.1陈述
The largest decimal literal of type int is 2147483648.
Run Code Online (Sandbox Code Playgroud)
同时这一行
int x = 2147483648;
Run Code Online (Sandbox Code Playgroud)
产生编译错误
The literal 2147483648 of type int is out of range
Run Code Online (Sandbox Code Playgroud)
JLS错了吗?
好的,这里是JLS专家的一个非常好奇的Java 7语言谜题.以下代码不能用javac和Eclipse编译:
package com.example;
public class X {
public static X com = new X();
public void x() {
System.out.println(com.example.X.com);
// cannot find symbol ^^^^^^^
}
}
Run Code Online (Sandbox Code Playgroud)
似乎成员com完全阻止com.*从内部访问包X.然而,这并未得到彻底应用.以下工作,例如:
public void x() {
System.out.println(com.example.X.class);
}
Run Code Online (Sandbox Code Playgroud)
我的问题:
注意,这只是对生成代码中的实际问题的简化,其中com.example.X需要完全限定并且com不能重命名成员.
更新:我认为它实际上可能是类似这样的问题:为什么我不能在Java中"静态导入"一个"等于"方法?
无障碍
缺少访问修饰符的接口的所有成员都是隐式公开的
接口的所有成员都是隐式公共的.
当我尝试以下代码时:
public interface Test {
protected int i = 10;
}
Run Code Online (Sandbox Code Playgroud)
编译,我得到了
Test.java:3: error: modifier protected not allowed here
protected int i = 10;
^
Java版本: Java(TM) SE Runtime Environment (build 1.8.0-b129)
但在上面的Interface成员声明我不缺乏访问修饰符,那么为什么我收到此错误.
为什么以下代码不会产生编译时未经检查的警告:
class Parent {
public List method(){
return null;
}
}
class Child extends Parent {
public List<String> method() {
return null;
}
}
Run Code Online (Sandbox Code Playgroud)
而以下实际上是:
class Parent {
public List<String> method(){
return null;
}
}
class Child extends Parent {
public List method() {
return null;
}
}
Run Code Online (Sandbox Code Playgroud)
我实际上是在寻找 JLS 中这种行为的参考。
我对以下情况感到困惑。
考虑两个包a并b具有以下类:
1)MethodInvoker仅call()在给定对象上调用:
package b;
import java.util.concurrent.Callable;
public class MethodInvoker {
public static void invoke(Callable r) throws Exception {
r.call();
}
}
Run Code Online (Sandbox Code Playgroud)
2)
package a;
import b.MethodInvoker;
import java.lang.reflect.Method;
import java.util.concurrent.Callable;
public class Test {
private static Void method() {
System.out.println("OK");
return null;
}
public static void main(String[] args) throws Exception {
Method method = Test.class.getDeclaredMethod("method");
method.invoke(null); // ok
// TEST 1
MethodInvoker.invoke(() -> {
return method.invoke(null); // ok (hmm....
});
// …Run Code Online (Sandbox Code Playgroud) 我查看了java.lang.Double该类的实现。的值NaN是的指定值0x7ff8000000000000L。将该public static final double NaN字段设置为该0.0d / 0.0值,以0x7ff8000000000000L判断JVM是否确实以这种方式实现了该字段。
为什么0x7ff8000000000000L选择此值()?这个值有什么特别的地方(例如它的位掩码)吗?
为什么将字段隐式设置为该值并取决于该0.0d / 0.0操作的基础实现,而静态方法public static long doubleToLongBits(double value)将该值显式设置0x7ff8000000000000L为NaN参数的值?由于0.0d / 0.0高度依赖JVM的实现并在理论上可以更改(很可能永远不会更改),因此隐式设置它是否更安全?
这同样适用于POSITIVE_INFINITY和NEGATIVE_INFINITY。字段被隐式设置为它们的值,但是某些方法使用显式指定的值。这背后有原因吗?
感谢您每天帮助我学习新知识:-)。