简体   繁体   中英

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.

Is there a way to do this without creating new classes or using the Object versions of the primitive types? 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).

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...

Java is always pass-by-value . There is no pass-by-reference in 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.

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. 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

The object types of primitive types in Java (Double, Integer, Boolean, etc) are, if I remember correctly, immutable. 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. Just suck it up and have multiple methods.

For example, ObjectInputStream has readDouble() , readByte() , etc.

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. 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?

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.

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:

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

  }

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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