代码之家  ›  专栏  ›  技术社区  ›  Hristo

我可以通过Java中的引用传递一个基元类型吗?[复制品]

  •  8
  • Hristo  · 技术社区  · 14 年前

    这个问题已经有了答案:

    我想调用一个可能具有不同版本的方法,即对于类型为的输入参数使用相同的方法:

    • 布尔
    • 字节
    • 短的
    • int
    • 长的

    我想这样做的方式是通过“重载”方法(我认为这是正确的术语?):

    public void getValue(byte theByte) {...}
    public void getValue(short theShort) {...}
    ... etc ...
    

    …但这意味着我必须通过引用传入原始类型…与C++类似,该方法具有外部效应,可以在其范围之外修改变量。

    有没有一种方法可以在不创建新类或使用基元类型的对象版本的情况下做到这一点?如果没有,对替代策略有什么建议吗?

    如果我需要进一步解释以消除任何困惑,请告诉我。


    更新

    我实际上要做的是从一组位构造基元类型。因此,如果我处理的是方法的字节版本,我几乎要做我的工作来获取8位并返回字节(因为我不能通过引用传递)。

    我之所以问这个问题是因为我对比特的工作是非常重复的,我不想在不同的方法中使用相同的代码。所以我想找到一种方法让我的一种方法知道我在说多少比特…如果我使用的是一个字节,那么8位,如果我使用的是一个短字节,16位,等等…

    9 回复  |  直到 12 年前
        1
  •  8
  •   meriton    14 年前

    虽然Java支持重载,但所有参数都是按值传递的,即分配方法参数对调用方不可见。

    从代码片段中,您试图返回不同类型的值。由于返回类型不是方法签名的一部分,因此不能使用不同的返回类型进行重载。因此,通常的方法是:

    int getIntValue() { ... }
    byte getByteValue() { ... }
    

    如果这实际上是一个转换,标准命名是

    int toInt() { ...}
    byte toByte() { ... }
    
        2
  •  9
  •   Community nesinervink    7 年前
        3
  •  5
  •   Darin Dimitrov    14 年前

    在Java中,参数总是通过值传递。如果参数是引用类型,则通过值传递引用,您可以在方法内部对其进行修改,而对于基元类型,这是不可能的。

    您将需要创建包装类型。

        4
  •  1
  •   willcodejavaforfood    14 年前

    基元不由引用(或对象)传递,因此不能。

    int i = 1;
    moo(i);
    public void moo(int bah)
    {
       bah = 3;
    }
    System.out.println(i);
    

    打印出1

        5
  •  1
  •   aperkins    14 年前

    Java中的基元类型的对象类型(double、整数、布尔等),如果我没记错的话,是不可变的。这意味着您不能更改传递给它们的方法中的原始值。

    有两种解决办法。一种方法是创建一个保存值的包装器类型。如果您所要做的就是更改该值或从该值中获取计算结果,那么您可以让该方法为您返回结果。举个例子:

    public byte getValue(byte theByte) {...}
    public short getValue(short theShort) {...}
    

    你可以通过以下方式给他们打电话:

    Short s = 0;
    s = foo.getValue(s);
    

    或者类似的东西。这允许您对值进行变异或更改,并返回变异的值,这将允许如下操作:

    Short s = foo.getValue(10);
    

    希望有帮助。

        6
  •  1
  •   Mark Peters    14 年前

    我想说,如果你想使用原语,另一种策略就是做Java库所做的事情。把它吸干,有多种方法。

    例如,objectinputstream具有 readDouble() , readByte() 等。

    通过共享函数的实现,您没有获得任何东西,并且您的函数的客户机也没有获得任何东西,因为您的函数的变体都具有相同的名称。

    更新

    考虑到您的更新,我认为没有必要复制太多的代码。这取决于您的编码策略,但我想您可以这样做:

    private byte get8Bits();
    public byte getByte() {
        return get8Bits();
    }
    public int getInt() {
        return (get8Bits() << 24) | (get8Bits() << 16) | (get8Bits() << 8) | get8Bits();
    }
    

    任何与代码共享更多的东西都可能是过度工程化的。

    另一种选择可能是

    private long getBits(int numBits);
    
    public byte getByte() {
        return (byte)getBits(8);
    }
    
    public int getInt() {
        return (int)getBits(32);
    }
    

    也就是说,我认为让您的库的用户接触到原始类型本身以外的任何东西都没有意义。

    如果你真的,真的很想这样做,那么你可以做一个单一的访问方法:

    @SuppressWarnings("unchecked")
    public static <T> T getValue(Class<T> clazz) {
        if ( clazz == byte.class ) {
            return (T)Byte.valueOf((byte)getBits(8));
        } else if ( clazz == int.class ) {
            return (T)Integer.valueOf((int)getBits(32));
        }
        throw new UnsupportedOperationException(clazz.toString());
    }
    
    //...
    byte b = getValue(byte.class);
    int i = getValue(int.class);
    

    但我看不出这对你们图书馆的客户来说有多麻烦。

        7
  •  1
  •   romacafe    14 年前

    听起来您有一组要解析的位。您应该将它包装在一个对象中,让我们称该对象为位集。您正在对位进行迭代,因此您将拥有类似于迭代器的东西<bit>,并且在您进行时,您希望解析字节、整数、长等…对吗?

    然后您将拥有类解析器,它上面有如下方法:

    public byte readByte(Iterator<Bit> bitit) {
      //reads 8 bits, which moves the iterator forward 8 places, creates the byte, and returns it
    }
    public int readInt(Iterator<Bit> bitit) {
      //reads 32 bits, which moves the iterator forward 32 places, creates the int, and returns it
    }
    

    等。。。

    因此,在调用了所需的任何方法之后,您已经以类型安全的方式提取了所需的值(不同方法的返回类型不同),并且迭代器已经根据类型向前移动了正确的位置数。

    这就是你要找的吗?

        8
  •  0
  •   Darron    14 年前

    只有通过创建自己的价值持有类型。

        9
  •  0
  •   einarmagnus    14 年前

    是的,请更具体地说明你想要达到的目标。 从你的描述中,我建议你看看Java泛型,在那里你可以写出这样的东西:

    class SomeClass <GenericType> {
      GenericType val;  
    
      void setValue(GenericType val) {
         this.val = val;
      }
    
      GenericType getValue() {
         return val;
      }
    
      public static void main(String[] args) {
        SomeClass<Integer> myObj = new SomeClass<Integer>();
        myObj.setValue(5);
        System.out.println(myObj.getValue());
    
        SomeClass<String> myObj2 = new SomeClass<String>();
        myObj2.setValue("hello?!");
        System.out.println(myObj2.getValue());
    
      }
    
    }