繁体   English   中英

我可以在 Java 中通过引用传递原始类型吗?

[英]Can I pass a primitive type by reference in Java?

我想调用一个可能采用不同版本的方法,即相同类型的输入参数的方法:

  • 布尔值
  • 字节
  • 整数

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

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

...但这意味着我必须通过引用传递原始类型...类似于 C++,其中方法具有外部效果,它可以在其范围之外修改变量。

有没有办法在不创建新类或使用原始类型的 Object 版本的情况下做到这一点? 如果没有,关于替代策略的任何建议?

让我知道我是否应该进一步解释以消除任何混淆。


更新

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

我问这个问题的原因是因为我对位所做的工作非常重复,我不想在不同的方法中使用相同的代码。 所以我想找到一种方法让我的 ONE 方法知道我在谈论多少位......如果我正在处理一个字节,那么 8 位,如果我正在处理一个短的,16 位等...

Java总是按值传递 Java 中没有传递引用。 它写在规范中

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

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

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

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

int toInt() { ...}
byte toByte() { ... }

你不能。 在 Java 中,参数总是按值传递。 如果参数是引用类型,则引用按值传递,您可以在方法内部修改它,而对于原始类型,这是不可能的。

您将需要创建一个包装器类型。

原语不是通过引用(或对象)传递的,所以你不能。

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

打印出来 1

Java 中原始类型的对象类型(Double、Integer、Boolean 等),如果我没记错的话,是不可变的。 这意味着您不能在传递给它们的方法中更改原始值。

对此有两种解决方案。 一种是制作一个保存值的包装器类型。 如果您尝试做的只是更改值或从值中获取计算,则可以让该方法为您返回结果。 举个例子:

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

您可以通过以下方式调用它们:

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

或类似的东西。 这允许您更改或更改值,并返回更改后的值,这将允许类似以下内容:

Short s = foo.getValue(10);

希望有帮助。

如果您想使用原语,我会说另一种策略是做 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);

但我看不出它对你图书馆的客户来说有什么不那么麻烦的。

听起来您有一组正在解析的位。 您应该将它包装在一个对象中,让该对象称为 BitSet。 您正在遍历各个位,因此您将拥有 Iterator<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
}

等等...

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

这就是你要找的吗?

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

是的,请更具体地说明您想要实现的目标。 根据您的描述,我建议您查看 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());

  }

}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM