对Java中原语隐式缩小的想法感到困惑

Moh*_*gar 5 java primitive byte casting

以下看似微不足道的问题已经动摇了我对基元如何在Java中工作的理解的核心.

我所遇到的术语"implicit narrowing",由此更小的范围类型的变量被允许保持较大范围类型的一个文字值,如果该值落入该较小的范围内.
据我所知,Java只允许在byte,char,short和int之间.

例如,如果该值足够小以适合字节类型的范围,则字节变量CAN采用int.

byte b1 = 3; // allowed even though 3 is an int literal
byte b2 = 350; // compilation error because a byte cannot go beyond positive 127
Run Code Online (Sandbox Code Playgroud)

所以,这很好用:

byte k = 3;
Run Code Online (Sandbox Code Playgroud)

但我不知道为什么下面这行不起作用!!

Byte k = new Byte(3);
Run Code Online (Sandbox Code Playgroud)

除非我将后者更改为Byte k = new Byte((byte)3),否则我会收到此编译错误:

error: no suitable constructor found for Byte(int)
        Byte k = new Byte(3);                                        
                 ^             
constructor Byte.Byte(byte) is not applicable                    
(actual argument int cannot be converted to byte by method invocation conversion)
Run Code Online (Sandbox Code Playgroud)

最后一部分error message似乎有一个线索,其中说:

"... actual argument int cannot be converted to 
 byte by method invocation conversion"
Run Code Online (Sandbox Code Playgroud)

然后关于线索的问题变成:
为什么?!我的意思是,将一个小的int文字分配给一个字节并将一个小的int文字传递给一个方法参数类型为byte的方法有什么区别?

我知道如果我传递一个int变量,就必须使用强制转换.但是,我没有传递变量.相反,我正在传递一个小文字,编译器应该意识到它对于一个字节足够小!

Pow*_*ord 10

The rules are different for assignment and method calls (including constructors) for literals.

According to the Java Language Specification (JLS) 8 §3.10, Java only has 6 literal types: IntegerLiteral, FloatingPointLiteral, BooleanLiteral, CharacterLiteral, StringLiteral, and NullLiteral.

3.10.1 further specifies:

An integer literal is of type long if it is suffixed with an ASCII letter L or l (ell); otherwise it is of type int (§4.2.1).

(§4.2.1 is just a specification of the ranges of types)

There are nearly 7 pages about IntegerLiteral, so I'm not going to go through the whole thing. Suffice it to say that int literals are downcast to byte and short as appropriate during assignment.

However, its usage in a constructor is entirely different. Since a constructor is a method, the normal rules for its arguments apply.

I tried quickly sorting through the rules for matching in the JLS, but its a very long and complicated section. Needless to say, only widening conversions will happen automatically when choosing a method to run. i.e. you can pass an int to a method expecting a long without an explicit cast, but you can't pass an int to a method expecting a byte unless you explicitly cast it.