当前位置: 首页 > 面试题库 >

如果Java是从数组中复制的,为什么Java要求对最终变量进行显式转换?

裴翰学
2023-03-14
问题内容

从以下代码开始…

byte foo = 1;
byte fooFoo = foo + foo;

当我尝试编译此代码时,将出现以下错误…

错误:(5,27)Java:不兼容的类型:从整数到字节的可能有损转换

…但是如果foo是最终的…

final byte foo = 1;
final byte fooFoo = foo + foo;

该文件将成功编译

继续下面的代码…

final byte[] fooArray = new byte[1];
fooArray[0] = 1;

final byte foo = fooArray[0];
fooArray[0] = 127;

System.out.println("foo is: " + foo);

…将打印

foo is: 1

…很好。该值将被复制到最终变量,并且无法再更改。播放数组中的值不会更改foo(预期的)值。

为什么以下内容需要强制转换?

final byte[] fooArray = new byte[1];
fooArray[0] = 1;
final byte foo = fooArray[0];
final byte fooFoo = foo + foo;

这个问题与第二个示例有何不同?为什么编译器给我以下错误?

错误:(5,27)Java:不兼容的类型:从整数到字节的可能有损转换

怎么会这样


问题答案:

JLS(第5.2节)具有使用
常量表达式 进行赋值转换的特殊规则:

此外,如果表达式是一个常量表达式(§15.28类型的)byteshortchar,或int

  • 如果变量的类型是byteshortchar,并且常量表达式的值在变量的类型中可表示,则可以使用变窄的原始转换。

如果我们点击上面的链接,我们将在 常量表达式 的定义中看到这些:

  • 基本类型的文字和类型的文字 String
  • 加法运算符+-
    * 引用常量变量(第4.2.4节)的简单名称(第6.5.6.1
    节)。

如果我们点击上面的第二个链接,我们会看到

原始类型或类型的变量String,即final,用一个编译时间常量表达式(初始化§15.28),被称为
恒定变量

因此,foo + foo只能将其赋给fooFooif foo是一个 常量变量 。要将其应用于您的案例:

  • byte foo = 1; 没有 定义 常量变量, 因为不是final

  • final byte foo = 1; 确实 定义了一个 常量变量 ,因为它是final常量表达式 (原始文字)初始化的。

  • final byte foo = fooArray[0]; 没有 定义 常量变量, 因为它没有使用 常量表达式 初始化。

请注意,是否fooFoo本身final并不重要。



 类似资料:
  • 问题内容: 我有一个程序,其中有一个用户可以编辑的文本框。当用户按下按钮时,将创建一个对话框,显示用户的文本和确认“是/否”选项。 这段代码可以正常工作,但是我的第一个版本无法编译。我的IDE抱怨我不应该创建字符串 ,而应该这样做。 这让我开始思考。在这种情况下会增加什么?例如,如果我选择保留对Dialog的引用,并通过另一种方法显示它,该怎么办?这意味着上面的方法将返回。那么变量如何持续存在呢?

  • 问题内容: 这个问题已经在这里有了答案 : 为什么在匿名类中只能访问最终变量? (15个答案) 为什么实例变量“忽略Lambda表达式中使用的变量必须是最终变量或实际上是最终变量”警告[重复] (2个答案) Lambdas:局部变量不需要最终变量,实例变量不需要 (10个答案) 2年前关闭。 当我编写此代码时,我收到一个编译时错误,该错误是: “ lambda中的变量必须是final或有效的fin

  • 问题内容: 我读了这个问题不可变对象,并留下了关于不可变对象,并最终场一个问题: 为什么我们需要不可变类中的实例变量为最终变量? 例如,考虑以下不可变的类: 如果在上面的代码中没有set方法,而实例变量仅在构造函数中设置,为什么要求将实例变量声明为final? 问题答案: 有没有 要求 这样做的变量。但是,当您确实明确打算永远不更改变量时,通常这样做是一种好习惯,因为这不仅可以使变量避免错别字或其

  • 我读到了这个关于不可变对象的问题,留下了一个关于不可变对象和final字段的问题: 为什么我们需要不可变类中的实例变量成为最终变量? 例如,考虑这个不可变类: 如果在上面的代码中没有设置方法,并且实例变量只在构造函数中设置,那么为什么需要将实例变量声明为final?

  • 问题内容: 我正在使用Java 1.6.0_25。 我定义了一个注释: 后来当我使用getAnnotation时: 编译器和IDE同意我必须强制转换结果,但是getAnnotation在Java 1.5文档中声明为: 由于Resource.class是Class类型,在我看来,这意味着cls.getAnnotation(Resource.class)应该返回Resource类型,并且我需要进行强制

  • 问题内容: 如果省略,则会看到错误“ 无法在用其他方法定义的内部类中引用非最终变量jtfContent ”。 为什么匿名内部类必须要求外部类实例变量为final才能访问它? 问题答案: 首先,让我们放松一下,请放下那把枪。 好。现在,语言坚持的原因是它作弊是为了让你的内部类函数可以访问他们渴望的局部变量。运行时复制本地执行上下文(以及其他适当的内容),因此它坚持要求你进行所有操作,final以使事