java - Java Color constructor casts long to float
问题描述
I was trying to draw gradients with Java (doesn't really matter what I was doing).
I have this line where it throws IllegalStatementException: Color parameter outside of expected range: Red
:
Color c = new Color(Math.round(col1r), Math.round(col1g), Math.round(col1b));
col1r
, col1g
and 'col1b' are all double
s and are in range 0-255. Math.round()
function returns long
. While I expected it cast to int
and use Color(int r, int g, int b)
as constructor, it is cast to float
and uses Color(float r, float g, float b)
as constructor.
What is the reason for that?
P.S. I don't want a solution to get my program running, I can do that myself.
解决方案
Because the specs say so: JLS §5.1.2.
Going from long
to int
is considered a narrowing primitive conversion. As in, it is considered that as a general principle (even if it doesn't apply in some specific case), long -> int is 'lossy'. Therefore, java will not do so unless you explicitly ask for it. Even in this trivial example where we don't have multiple overloads:
public void foo(int x) {}
long y = 5;
foo(y); // this will not compile
To ask for it, you either [A] cast: foo((int) y);
would have worked, or [B] use an operation+assignment operator: int x = 0; x += someLong;
actually works, this is a bit weird but, hey, the spec says so.
However, going from long
to double
or float
is a so-called Widening primitive conversion: It is considered lossless (eventhough that is not technically true; if your long is larger than 2^52
or smaller than -2^52
you may lose precision when converting a long to a double, for example) - and java will do that silently, there is no need to ask for it:
public void foo(double x) {}
long y = 5;
foo(y); // compiles just fine
Given the above, of all the various constructors that Color
has, only Color(double, double, double)
unambiguously and without needing to apply narrowing primitive conversion (which java won't do without you asking for it explicitly) fits given 3 longs for an argument.
推荐阅读
- java - 如何使用 C# 在 Unity 中设置/调用 Android 方法
- javascript - 如何将文本重新格式化为不同的模式?
- docker - 如何在 docker compose 文件上设置 MySQL 和 phpmyadmin
- javascript - JS 不会将导入和声明的变量读入 console.log
- javascript - 尝试读取从反应 js 中的 API 返回的响应时获取未定义
- google-compute-engine - 谷歌云控制台 - 找不到 phpmyadmin 404
- selection - bootstrap-vue 选择带有过滤器选项的组件?
- android - 为什么 API Level 29 WiFi 连接需要密码?
- php - PHP Traits 通用和单个(单独)属性范围
- c# - 如何将滚动条与 RichTextBox 中的行匹配