Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/336.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
“处理问题的想法”;“未签名”;Java8中的整数_Java_Annotations_Java 8_Unsigned - Fatal编程技术网

“处理问题的想法”;“未签名”;Java8中的整数

“处理问题的想法”;“未签名”;Java8中的整数,java,annotations,java-8,unsigned,Java,Annotations,Java 8,Unsigned,我正在编写与硬件和数学相关的代码,并广泛使用32位和64位无符号整数值。没有任何javac支持,bug一直很稳定,很难解决。Java8在装箱的Long类上添加了一些用于除法、mod和比较的函数,但尽管这些函数提供了运行时支持,但由于缺少编译时警告,无法将这两个函数意外地混合在一起,这让我非常恼火 有人知道有什么方法可以帮助解决这些问题吗?Java团队成员之一提到了类型检查 到目前为止,我在所有无符号变量的前面加上u_,甚至在每次出现应无符号的int或long之前添加/*unsigned*/注释。

我正在编写与硬件和数学相关的代码,并广泛使用32位和64位无符号整数值。没有任何javac支持,bug一直很稳定,很难解决。Java8在装箱的Long类上添加了一些用于除法、mod和比较的函数,但尽管这些函数提供了运行时支持,但由于缺少编译时警告,无法将这两个函数意外地混合在一起,这让我非常恼火

有人知道有什么方法可以帮助解决这些问题吗?Java团队成员之一提到了类型检查

到目前为止,我在所有无符号变量的前面加上u_,甚至在每次出现应无符号的
int
long
之前添加
/*unsigned*/
注释。虽然这些是有用的,但它们也非常杂乱。这还不够。犯错误的机会太多了

两个较大的问题是不需要的符号扩展和混合操作

/*unsigned*/long u_lowmask=0xffffffff
这样无害的东西并没有得到想要的结果,或者甚至只是
/*unsigned*/long u_wide64=small32
破坏了无提示扩展的功能。在其他语言中,我可以从编译器或类似Lint的静态检查器获得警告。函数式语言通常将其构建到类型检查机制中,但Java已经避开了这些机制,转而采用其他解决方案。有太多机会进行混合比较或操作

希望任何想法都不会对运行时产生影响,所以我负担不起在类或bignums中包装unsigned。好吧,如果我不需要任何分配或线程局部变量的开销,我可能能够将它们封装在一个类中,但这可能会使代码不可重入。Hotspot还必须能够为接近简单本机的包装无符号整数发出代码。(事实上,我认为Hotspot可能足够聪明,可以靠近——可能需要额外的内存读写。)


其他人是如何围绕这个问题编写代码的?

在检测方面,我没有对这些进行过太多的研究,但我会从中查看Java lint或其他Java lint工具

理想情况下,对于
long
变量到
int
值的每次赋值,该工具都会给您一个警告,然后您可以使用如下解决方案将每个此类赋值包装在一个静态(可内联)方法调用中(从而删除警告)

对于赋值静态包装器方法,像这样的实用程序类在过去对我来说非常有效:

public class Convert {
    private Convert() {} // static utility methods only

    public long uintToUlong(int uint) {
        long ulong = 0;
        if (uint < 0) {
            uint &= Integer.MAX_VALUE;
            ulong = Integer.MAX_VALUE;
            ulong++;
        }
        return ulong + uint;
    }

    public long uintToLong(int uint) {
        return uintToUlong(uint)
    }

    public long intToUlong(int signedInt) {
        return signedInt; //TODO would this be correct?
    }

    public long intToLong(int signedInt) {
        return signedInt;
    }
}
一些JUnit测试:

import static org.junit.Assert.assertEquals;

import org.junit.Test;

public class UintTest {
    @Test
    public void testToUlong() {
        long expected = Double.valueOf(Math.pow(2, 32) - 1).longValue();
        assertEquals("maxUint", expected, Uint.toUlong(-1));
        expected = Double.valueOf(Math.pow(2, 31)).longValue();
        assertEquals("minInt", expected, Uint.toUlong(Integer.MIN_VALUE));
        expected--;
        assertEquals("maxInt", expected, Uint.toUlong(Integer.MAX_VALUE));
        expected = 10000;
        assertEquals("10000", 10000l, Uint.toUlong(10000));
        expected = 3000000000l;
        assertEquals("3B", expected, Uint.toUlong(1500000000 + 1500000000));
    }
}

编辑:截至2016年7月,Checker框架附带了您要求的大部分或全部内容:验证有符号值与无符号值的一致使用。从:

有符号性检查器保证有符号值和无符号值在计算中不会混合在一起。此外,它还禁止无意义的操作,例如对无符号值进行除法

(向@MAGx2致敬,因为他注意到这个答案已经过时了。)


旧的答案如下:

我建议你调查一下这件事。它使您能够定义自己的类型限定符批注,例如
@Unsigned
,然后在编译时检查代码对于这些批注的类型是否正确。如果它没有发出警告,那么您可以保证代码不会混合使用有符号和无符号值

Checker框架附带了,但没有一个用于无符号算术。你需要这样做。这应该是相对简单的,因为类型检查器需要很少的特殊规则:您只是不想混合使用有符号值和无符号值

有关需要库注释的JDK方法的列表,请参阅

重写以删除对库或工具的任何引用。我认为,基于注释的解决方案将是最干净的,但目前还没有合适的检查工具。对于转换,我只使用
long ulong=0xFFFFFFFFL&(long)uint
。糟糕的是,我第一次写这篇文章时,不小心把
L
关掉了。我立即将其放入一个静态函数中,以防止再次出现这种情况。@JasonN:that
static
函数这可能是我将要得到的最接近的函数了。我会调查的。这也可能是一个很好的例子,说明为什么这里的一些规则写得很差,遵守得很差。我花了四次重写这个问题——所有之前的问题都被关闭,要求提供一个库或工具的建议——最终得到一个答案,这是一个库或工具。在一个开发人员的语言中有另一个开发人员的库。我发现在Checker框架中有对已签名/未签名的检查
import static org.junit.Assert.assertEquals;

import org.junit.Test;

public class UintTest {
    @Test
    public void testToUlong() {
        long expected = Double.valueOf(Math.pow(2, 32) - 1).longValue();
        assertEquals("maxUint", expected, Uint.toUlong(-1));
        expected = Double.valueOf(Math.pow(2, 31)).longValue();
        assertEquals("minInt", expected, Uint.toUlong(Integer.MIN_VALUE));
        expected--;
        assertEquals("maxInt", expected, Uint.toUlong(Integer.MAX_VALUE));
        expected = 10000;
        assertEquals("10000", 10000l, Uint.toUlong(10000));
        expected = 3000000000l;
        assertEquals("3B", expected, Uint.toUlong(1500000000 + 1500000000));
    }
}