简体   繁体   English

分配问题OCJP; 为什么不能将int传递给short?

[英]Assignment issue OCJP; why can't I pass an int to a short?

I have two pieces of code. 我有两段代码。 One works, another doesn't, but both seem to do identical things. 一种有效,另一种无效,但是两者似乎都做相同的事情。 This works: 这有效:

short s=7;

but the below code doesn't. 但是下面的代码没有。 Instead, it gives error: 相反,它给出了错误:

can't assign int to short 不能将int赋给short

I know an integer number literal by default is int , but if it can be assigned directly above, then why not when passing to a method? 我知道默认情况下,整数是int ,但是如果可以直接在上面分配,那么在传递给方法时为什么不呢?

class Demo1{
    public static void main(String[] args){
        new Demo1().go(7);
    }
    void go(short s){System.out.println("short");}
}

The rules are different for assignment and for method overload resolution : 分配和方法重载解析的规则不同:

For assignment the JLS says : 对于分配,JLS说:

In addition, if the expression is a constant expression (§15.28) of type byte, short, char, or int: 此外,如果该表达式是类型为byte,short,char或int的常量表达式(第15.28节):

A narrowing primitive conversion may be used if the type of the variable is byte, short, or char, and the value of the constant expression is representable in the type of the variable. 如果变量的类型为byte,short或char,并且常量表达式的值可表示为变量的类型,则可以使用缩窄的原始转换。

For overload resolution, JLS 15.12.2.2. 对于过载解析,请参见JLS 15.12.2.2。 says: 说:

The method m is applicable by subtyping if and only if both of the following conditions hold: 当且仅当同时满足以下两个条件时,方法m才可以通过子类型化来应用:

For 1 ≤ i ≤ n, either: 对于1≤i≤n,则:
* Ai <: Si (§4.10), or * Ai <:Si(第4.10节),或
* Ai is convertible to some type Ci by unchecked conversion (§5.1.9), and Ci <: Si. * Ai可通过未经检查的转换(第5.1.9节)和Ci <:Si转换为某种Ci类型。

Here Ai is the type of the parameter passed to the method ( int in your case, since 7 is an int literal). 这里艾是传递给方法的参数的类型( int在你的情况下,由于7是一个int文字)。 Si is the type of the method's formal parameters ( short in your case). Si是方法的形式参数的类型(在您的情况下short )。 Ai <: Si means that Ai is a sub-type of Si. Ai <: Si表示Ai是Ai <: Si的子类型。 int is not a sub-type of short (the opposite is true), which is why the compiler doesn't accept new Demo1().go(7); int 不是 short的子类型(相反是正确的),这就是为什么编译器不接受new Demo1().go(7); .

You must cast the integer to short as follows: 您必须将整数强制转换为short,如下所示:

short s = (short) 7;

This should work. 这应该工作。

Your code should look like this: 您的代码应如下所示:

class Demo1{
    public static void main(String[] args){
        new Demo1().go((short) 7);// change here.
    }
    void go(short s){System.out.println("short");}
}

The reason for implicit casting during a direct assignment and it not being present when passing a value during a method call is due to the difference between the assignment context and the invocation context which are self explained by the situation you are in. It is just how the java programming language works. 在直接分配过程中进行隐式强制转换,而在方法调用期间传递值时不进行隐式转换的原因是由于赋值上下文和调用上下文之间的差异,这由您所处的情况自行解释。这就是如何Java编程语言有效。

I see it as a positive factor as it helps the compiler decide which method your are calling if some of your methods have the same name but have the different data types in the paramaters. 我认为这是一个积极因素,因为如果某些方法名称相同但参数中的数据类型不同,它可以帮助编译器确定正在调用的方法。 With you casting the given value to the data type in the paramater, the compiler will be able to distinguish which method you are calling, if implicit casting were to occur in the parameter how would the compiler know which data type to cast it to, if you had two methods with the same name but different parameters, say int and short. 如果将给定值转换为参数中的数据类型,则编译器将能够区分您正在调用的方法,如果在参数中进行隐式转换,则编译器将如何知道将其转换为哪种数据类型,如果您有两个名称相同但参数不同的方法,例如int和short。

The language allows the narrowing conversion of constant int expression to short type, in Assignment Context . 该语言允许在Assignment Context中将常量int表达式缩小为short类型。 The same is not true for method invocation context . 对于方法调用上下文,情况并非如此。 Relevant JLS section is JLS §5.2 and JLS § 5.3 . 相关的JLS部分是JLS§5.2JLS§5.3

For assignment context, I'll list down the exact statement: 对于分配上下文,我将列出确切的语句:

In addition, if the expression is a constant expression (§15.28) of type byte , short , char , or int : 此外,如果该表达式是类型为byteshortcharint的常量表达式(第15.28节):

A narrowing primitive conversion may be used if the type of the variable is byte , short , or char , and the value of the constant expression is representable in the type of the variable. 如果变量的类型为byteshortchar ,并且常量表达式的值可以表示为变量的类型,则可以使用缩窄的原始转换。

While there is no such rule for invocation context conversion. 虽然没有用于调用上下文转换的规则。 That is why, you've to tell the compiler explicitly to do the conversion, by type-casting: new Demo1().go((short)7); 因此,您必须通过类型转换明确地告诉编译器进行转换: new Demo1().go((short)7);

Now, as for why such a behaviour, the reason we come up with would just be a guess (real answer, language designer only knows). 现在,至于为什么这样的行为,我们提出的原因只是一个猜测(真正的答案,语言设计师只知道)。

First one Variable initialization. 第一个变量初始化。 Second one is passing parameter to method. 第二个是将参数传递给方法。 In Method you must pass exact data type of variable. 在Method中,您必须传递变量的确切数据类型。

In an assignment it is clear for the compiler to which argument to cast: 在分配中,对于编译器来说,将哪个参数强制转换为显然是:

short s=7; //here is no doubt that it must be cast to short

In a method call, which could be possibly virtual, it is not decidable. 在可能是虚拟的方法调用中,它是不确定的。

go(7); //here it could be anything

The compiler tries to find a signature which is type compatible, ie 编译器尝试查找类型兼容的签名,即

void go(Integer i); // via auto boxing
void go(Number i); // autoboxing and supertype

It does not try casting, ie following would not work: 它不会尝试强制转换,即以下操作无效:

void go(short s); // short is neither a super type nor a subtype of int
void go(byte b); // byte is neither a super type nor a subtype of int

I rather do not expect go(new Integer(7)) to call void go(Short s) and that is the same with every types that are in no type hierarchy relation. 我宁愿不要go(new Integer(7))调用void go(Short s) ,并且对于没有类型层次关系的每个类型都是一样的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM