我的代码很简单:
class A {
public static void main(String[] args){
char c = 65; // ok
new A().m(65); // compile error
}
void m(char c){}
}
我想知道原因
char c = 65;
是可能的,但是
new A().m(65); // compile error
不可能!
谁能解释?
谁可以为类似问题指定通用规则?
答案 0 :(得分:11)
您正在研究的是方法调用转换和分配转换之间的区别。
用简单的语言来说,在两种情况下,转换规则是不同的。
案例#1:作业转换
char c = 5;
如您所知,这是一份作业陈述。当被分配的对象不是预期的类型时,可能会发生一些转换,无论如何都要进行分配。
案例#2:方法调用转换
def foo(char c){}
[...]
foo(5);
这(最后一行)是一个方法调用。这是类型文字可能与声明不匹配的另一个地方,因此转换规则可能适用。
那么,为什么它们不同?
Java的设计者已经为这两种情况实现了不同的转换规则。在案例#1中,规则是(来自JLS):
...缩小的原始转换可能 如果满足以下所有条件,则使用:
- 表达式是byte,short,char或int类型的常量表达式。
- 变量的类型是byte,short或char。
- 表达式的值(在编译时已知,因为它是一个常量表达式)可以在类型中表示 变量。
所以int
- >案例#1中的char
转换正在由Java编译器进行专门检查并自动解决。
然而,案例#2中的规则是不同的。在这里,Java的设计者不希望实现他们用于赋值语句的自动转换。从“程序员指南到Java认证:综合入门”:
请注意,方法调用和赋值转换的区别在于一个 方面:方法调用转换不包含隐式 缩小对整数常量表达式执行的转换。
那么,为什么两种情况有不同的规则?基本上,Java的设计者认为自动转换是有用且方便的,但是由于具有太多的键入灵活性,它可能会使事情过于复杂。他们认为案例#1是一个足够简单的情况,我们可以进行转换而不会失去清晰度,但案例#2则不然。以下是JLS的理由:
方法调用转换特别不包含隐式 缩小整数常量,这是赋值转换的一部分。 Java编程语言的设计者认为包括 这些隐含的缩小转换会增加额外的复杂性 到重载方法匹配解决过程。
具体而言,这是JLS 5.1, 5.2 and 5.3。
修改强>
关于“重载方法匹配解决过程的额外复杂性”,我的假设是他们试图避免这种情况:
def foo(int i){}
def foo(char c){}
foo(5); // OH NO which of the above gets called??@!?!?!
答案 1 :(得分:-3)
阅读规范是正确的,但对我来说很难。
我提供的权利较少但答案更简单:
我写的时候:
new A().m(65); // compile error
完全模拟:
int n =65;
char c = n;
显然(显然对我来说)编译错误
我希望有人希望。