简体   繁体   English

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

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

I would like to call a method which could potentially take on different versions, ie the same method for input parameters that are of type:我想调用一个可能采用不同版本的方法,即相同类型的输入参数的方法:

  • boolean布尔值
  • byte字节
  • short
  • int整数
  • long

The way I would like to do this is by "overloading" the method (I think that is the correct term?):我想这样做的方法是“重载”该方法(我认为这是正确的术语?):

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

... but that would mean that I would have to pass the primitive type in by reference... similar to C++ where the method has external effect, where it can modify the variable outside its scope. ...但这意味着我必须通过引用传递原始类型...类似于 C++,其中方法具有外部效果,它可以在其范围之外修改变量。

Is there a way to do this without creating new classes or using the Object versions of the primitive types?有没有办法在不创建新类或使用原始类型的 Object 版本的情况下做到这一点? If not, any suggestions on alternative strategies?如果没有,关于替代策略的任何建议?

Let me know if I should further explain to clear up any confusion.让我知道我是否应该进一步解释以消除任何混淆。


UPDATE更新

What I'm actually trying to do is construct the primitive type from a set of bits.我实际上想要做的是从一组位构造原始类型。 So if I'm dealing with the byte version of the method, I want to pretty much do my work to get 8 bits and return the byte (since I can't pass by reference).因此,如果我正在处理该方法的字节版本,我几乎想做我的工作来获取 8 位并返回字节(因为我无法通过引用传递)。

The reason I'm asking this question is because the work I do with bits is very repetitive and I don't want to have the same code in different methods.我问这个问题的原因是因为我对位所做的工作非常重复,我不想在不同的方法中使用相同的代码。 So I want to find a way for my ONE method to KNOW how many bits I'm talking about... if I'm working with a byte, then 8 bits, if I'm working with a short, 16 bits, etc...所以我想找到一种方法让我的 ONE 方法知道我在谈论多少位......如果我正在处理一个字节,那么 8 位,如果我正在处理一个短的,16 位等...

Java is always pass-by-value . Java总是按值传递 There is no pass-by-reference in Java. Java 中没有传递引用。 It's written in the specs ! 它写在规范中

While Java supports overloading, all parameters are passed by value, ie assigning a method argument is not visible to the caller.虽然 Java 支持重载,但所有参数都是按值传递的,即分配方法参数对调用者是不可见的。

From your code snippet, you are trying to return a value of different types.从您的代码片段中,您试图返回不同类型的值。 Since return types are not part of a method's signature, you can not overload with different return types.由于返回类型不是方法签名的一部分,因此您不能使用不同的返回类型进行重载。 Therefore, the usual approach is:因此,通常的做法是:

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

If this is actually a conversion, the standard naming is如果这实际上是一个转换,则标准命名为

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

You can't.你不能。 In Java parameters are always passed by value.在 Java 中,参数总是按值传递。 If the parameter is a reference type, the reference is passed by value and you can modify it inside the method while with primitive types this is not possible.如果参数是引用类型,则引用按值传递,您可以在方法内部修改它,而对于原始类型,这是不可能的。

You will need to create a wrapper type.您将需要创建一个包装器类型。

Primitives are not passed by references (or objects for that matter) so no you cannot.原语不是通过引用(或对象)传递的,所以你不能。

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

Prints out 1打印出来 1

The object types of primitive types in Java (Double, Integer, Boolean, etc) are, if I remember correctly, immutable. Java 中原始类型的对象类型(Double、Integer、Boolean 等),如果我没记错的话,是不可变的。 This means that you cannot change the original value inside a method they are passed into.这意味着您不能在传递给它们的方法中更改原始值。

There are two solutions to this.对此有两种解决方案。 One is to make a wrapper type that holds the value.一种是制作一个保存值的包装器类型。 If all you are attempting to do is change the value or get a calculation from the value, you could have the method return the result for you.如果您尝试做的只是更改值或从值中获取计算,则可以让该方法为您返回结果。 To take your examples:举个例子:

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

And you would call them by the following:您可以通过以下方式调用它们:

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

or something similar.或类似的东西。 This allows you to mutate or change the value, and return the mutated value, which would allow something like the following:这允许您更改或更改值,并返回更改后的值,这将允许类似以下内容:

Short s = foo.getValue(10);

Hope that helps.希望有帮助。

I would say the alternative strategy, if you want to work with primitives, is to do what the Java Libraries do.如果您想使用原语,我会说另一种策略是做 Java 库所做的事情。 Just suck it up and have multiple methods.只需吸收它并有多种方法。

For example, ObjectInputStream has readDouble() , readByte() , etc.例如, ObjectInputStream 有readDouble()readByte()等。

You're not gaining anything by sharing an implementation of the function, and the clients of your function aren't gaining anything by the variants of your function all having the same name.您不会通过共享函数的实现获得任何东西,并且您的函数的客户端不会通过您的函数的所有变体都具有相同的名称而获得任何东西。

UPDATE更新

Considering your update, I don't think it's necessary to duplicate too much code.考虑到你的更新,我认为没有必要复制太多代码。 It depends on your encoding strategy but I would imagine you could do something like this:这取决于您的编码策略,但我想您可以执行以下操作:

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

Anything that shares code more than that is probably over-engineering.任何比这更多地共享代码的东西都可能是过度设计的。

An alternative could be另一种可能是

private long getBits(int numBits);

public byte getByte() {
    return (byte)getBits(8);
}

public int getInt() {
    return (int)getBits(32);
}

ie I don't think it makes sense to expose the users of your library to anything other than the primitive types themselves.即我认为将您的库的用户暴露给原始类型本身以外的任何东西是没有意义的。

If you really, really wanted to then you could make a single method for access like this:如果你真的,真的想要,那么你可以创建一个像这样的访问方法:

@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);

But I fail to see how it's any less cumbersome for clients of your library.但我看不出它对你图书馆的客户来说有什么不那么麻烦的。

Sounds like you have a set of bits that you're parsing through.听起来您有一组正在解析的位。 You should have it wrapped in an object, lets call that object a BitSet.您应该将它包装在一个对象中,让该对象称为 BitSet。 You're iterating through the bits, so you'll have something like an Iterator<Bit>, and as you go you want to parse out bytes, ints, longs, etc... Right?您正在遍历各个位,因此您将拥有 Iterator<Bit> 之类的东西,并且在执行过程中您想解析出字节、整数、长整数等……对吗?

Then you'll have your class Parser, and it has methods on it like:然后你会有你的类解析器,它有如下方法:

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
}

etc...等等...

So after you call whichever method you need, you've extracted the value you want in a typesafe way (different return types for different methods), and the Iterator has been moved forward the correct number of positions, based on the type.因此,在调用您需要的任何方法之后,您已经以类型安全的方式提取了您想要的值(不同方法的不同返回类型),并且 Iterator 已根据类型向前移动正确数量的位置。

Is that what you're looking for?这就是你要找的吗?

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

Yes, please be more specific about what you want to achieve.是的,请更具体地说明您想要实现的目标。 From your description I suggest you have a look at Java generics where you could write something like this:根据您的描述,我建议您查看 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