public static void main(String[] args) {
int a = 1;
int b = a;
b = b - 1;
System.out.println(a);
System.out.println(b);
}
The current output is "1,0." However, I wanted "a" and "b" to point to the same object, and if "b" changes, "a" changes, as well. I am not sure how to make this happens.
CodePudding user response:
Java has no pointer data types. You cannot make a pointer in java for int.
See section: 2.2.9 No More Pointers of The Java Language Environment
CodePudding user response:
As @Jeffrey Ram said, Java has no pointer data types, specifically in primitive types: int, byte, short, long, float, double, boolean, and char. But don't worries, still have some trick to do it, that is use object
types.
Not like primitive
type, object
type in java will point t the same address if you assign one object to other. So see my ex here:
class HelloWorld {
public static void main(String[] args) {
Pointer g = new Pointer();
g.i = 6;
System.out.println(g.i); // 6
Pointer b = g; // assign object g to b, this will make b point to g's address
b.i = 9;
System.out.println(b.i); // 9
System.out.println(g.i); // guess what value is this :) it's 9
}
}
class Pointer {
int i;
}
But remember, make sure you not declare b
like this:
Pointer b = new Pointer();
b.i = g.i;
this will not pass g
's address to b
, so now if b
is 9, g
still is 6.
Hope this will help your problem. Happy coding! ;)
CodePudding user response:
The usual way to create a pointer is one of 4 options:
- Use a 1-size array
This is a bad idea, but you see it a lot. Looks like this:
int[] a = new int[1];
a[0] = 5;
int[] b = a;
b[0] ;
System.out.println(a[0]); // prints 6, as you wanted.
It's a bad idea because arrays have bad toString, equals, and hashCode impls.
- AtomicX
There's AtomicInteger, AtomicLong, AtomicDouble, and AtomicReference for everything else, pretty much. Oh, and AtomicBoolean. These are thread safe (generally useful - 'I want to have mutable references' often goes hand in hand with '... and that means they may end up in the hands of another thread'), and have better equals/hashCode/toString impls. They are baked into java, in the java.util.concurrent package
- Write your own type
Can be as simple as class Wrapper { public int value; }
. Generally, if the one and only purpose is to wrap, just use an AtomicX
. But if you want to 'pointerize' a whole swath of values, this starts becoming a good idea.
- Use a type specifically designed for it
This is rare, but occasionally an immutable type ships with a mutable variant on the side. For example, String is not mutable (you can hand a string ref to another method; they can't change that string, only make new strings, so, they can't modify the string in a way that the caller can see it) – but StringBuilder
is, so you could use StringBuilder as a standin for this.
But beware!
Whilst you can write perfectly fine java code that conveys its results by way of modifying the inputs using one of the above 4 tricks, this is not what your average java coder does. Given that a programming language is almost entirely useless for a hermit living on the top of a mountain (given that you tend to work in teams, read tutorials, interact with java programmers on Stack Overflow, use libraries written by others, and so on), going against the grain is not something you should do lightly. So, in general, you should do none of the above 4 things and instead do this the way your average java coder would do this, which usually involves immutables, and the novel idea of returning the results of your method via... the return value. Hence why that's named "the return value".
If you want a method to change multiple things, then there are really only 2 obvious choices: Either that method does multiple unrelated things and therefore instead of a method, this should really be a class, or just multiple separate unrelated methods. (Which may internally use the same helper method to do their thing if their implementation shares a lot of similarities, but that should not be exposed to other code that calls it). Or, the values themselves should be gathered together in a single class, that is, if for example you have a method that looks up the name and birth date of a student by ID, you do NOT want:
public void lookupStudent(int studentId, AtomicReference<String> studentName, AtomicReference<LocalDate> birthDate) {
// do the lookup
studentName.set(name);
birthDate.set(birthDate);
}
instead you would want to create a Person class:
record Student(String name, LocalDate birthDate) {}
Person lookupStudent(int id) {
...
}
If record is too new for you, Project Lombok's @Value
can also do it, or write out the boilerplate by hand.