Remove all pointers to an object in java [closed] - java

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
OK, here is the thing. I have multiple pointers to an object and I want to remove both of them. I have simplified it, below, so don't bother asking why on earth I would try the thing below :)
String first = "ASSIGNED";
String second = test;
second = null;
System.out.println(first);
In the example above, the output still results in "ASSIGNED". However, I want first to be no longer assigned. In the example above, it is easy, by setting it to null, but in my real example, this is not possible (first being passed into a method, where I want to remove the assingment).
EDIT:
So, I guess the question is, if it is possible to remove all pointers to a given object.
Apparently it was a bit vague what I was asking, so let's try to give a better example:
String first = "Assigned";
doSomethingAndRemove(first);
public void Remove(String string) {
//Do something
//...and remove
string = null;
}
The thing is that first still is referencing to "Assigned"... But from what I read in the answers so far, there is no way around this?

No, it is not possible to remove all "pointers" to a given object, for one because Java doesn't have pointers, they are called references.
Neither Java nor the JVM knows all references to a given object. This is why the garbage collector has to scan everything to find unused objects.
You have to clear references, and you cannot clear a reference variable that was used to pass a parameter from within the called method, because Java is pass-by-value, meaning the reference (not the object) is copied.
Example:
public static void main(String[] args) {
String var1 = "Hello";
doSomething(var1); // The value of var1 is copied to param1
}
private static void doSomething(String param1) {
param1 = null; // Only clears the param1 reference
var1 = null; // Cannot do this, because doSomething() does not have access to var1
}
Only code in method main can change the reference value of var1.
Update
If you want method doSomething to be able to update var1 to a different value, incl. null, then a common practice is to simply return the updated value.
public static void main(String[] args) {
String var1 = "Hello";
var1 = doSomething(var1);
}
private static void doSomething(String param1) {
// do something with param1
return "Goodbye";
}
This of course only works if you didn't already have a different kind of return value, and only works for a single value.
Output (and In/Out) parameters can be simulated in Java using the holder pattern, e.g. see Output Parameters in Java

C# can do it using ref, but Java cannot. The following is the last resort in Java if you must do it.
public class Nullify
{
public static void main(String[] args) {
String[] first = { "ASSIGNED" };
System.out.println("first[0] = " + first[0]);
nullify(first);
System.out.println("first[0] = " + first[0]);
}
private static void nullify(String[] array) {
array[0] = null;
}
}

String s=ASSIGNED;
String s2=s;
String s2=null; // means just remove the link s2 is pointing to
System.out.println(s); // print ASSIGNED
seen the picture.
if you want to remove you have to assign null to all individual objects.

Related

String in Java is object, so it should be reference? [duplicate]

This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 8 years ago.
I am a beginner in Java, recently faced such an interview question on Java String concept:
public class Test1 {
public static void changeStr(String str){
str="welcome";
}
public static void main(String[] args) {
String str="1234";
changeStr(str);
System.out.println(str);
}
}
I think the output should be "welcome", however, I tested it in Eclipse, it showed "1234", isn't Java string is a reference, so the Java string "str" references gets changed to "welcome" in method changeStr?
Pardon me for the beginner question!
The object's reference is passed to the method and assigned to the parameter, which is a kind of local variable.
Assigning a different object reference to the parameter does nothing to the variable outside the method that held a reference to the original object.
Also String is immutable, so there's no way to change its value (for example a setValue() method).
The line str = "welcome"; doesn't change the value of any String - Strings can never change their values. What it does is it makes one reference point to a different String. But the reference that it reassigns is the one that's local to changeStr, not the one that is declared in main.
String is a reference, but the key is that String str inside changeStr is a different reference than str in main. Add that to the fact that strings are immutable in Java (meaning that when you change a String, the reference points to a different location in memory) and that explains why main will print 1234
Consider the following example:
public static void main(final String[] args) throws Exception {
final StringHolder holder = new StringHolder("old value");
System.out.println(holder);
reassignHolder(holder);
System.out.println(holder);
changeVal(holder);
System.out.println(holder);
}
static void reassignHolder(StringHolder holder) {
holder = new StringHolder("new value");
}
static void changeVal(StringHolder holder) {
holder.setVal("new value");
}
static class StringHolder {
private String val;
public StringHolder(String val) {
this.val = val;
}
public String getVal() {
return val;
}
public void setVal(String val) {
this.val = val;
}
#Override
public String toString() {
return "StringHolder{" + "val=" + val + '}';
}
}
In Java references are passed by value and (almost) everything is an object reference.
Here we have a mutable object that holds a String - a StringHolder.
When we call reassignHolder what we actually do is copy our object reference and pass it to the method. When the method reassigns the reference nothing happens to our original reference as we are passing a copy.
When we call reassignHolder we also pass a copy of our reference, but the method uses this reference to call a method on our object to change its val variable. This will have an effect.
So the output is:
StringHolder{val=old value}
StringHolder{val=old value}
StringHolder{val=new value}
As String is immutable, you can only carry out the first example rather than the second.
The logic here is that the str value that is passed is passed as a copy of reference of str. This implies that any change in str will not be reflected in the original str.
This situation is similar to pass by value (but of references!)
However in your code if you change the code to str = new String("welcome"); It will change the original str string by making it reference a new copy that was created.
Hope this clears things for you.

How parameter.method() method works? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
Well, i was thinking about that kind of methods.
They dont recive parameters, but they work with them.
An example: .replace(Char, Char) of String API, it works with a String followed by a dot.
Like:
String test = "= Text = without = equals";
String output = test.replace("=","");
How it works without receive the parameter test?
I'm just being curious, want to do a method like these.
Sorry for my bad english!
Thanks.
Let's say you build a new type of String, that only does replace stuff (why not?!):
public class MyString {
private final String s;
public MyString(String s) {
this.s = s;
}
public String replace(String search, String replace) {
return s.replace(search, replace);
}
}
Now you can call it like this:
MyString myString = new MyString("= Text = without = equals");
String output = myString.replace("=", "");
Et voila, you have done the same "trick"! And you can see how it works: your MyString object keeps some data internally (the s variable) and can access that data from its methods.
These are instance methods, which means that they require an instantiated class object to operate. So, the string class knows the value of test in your example, because it has access to the instantiated data.
To create these types of methods, simply define them within your class and do not mark them as static.
String is an object. The class definition is part of the Java standard library. That definition includes the replace method.
Since String is a final class you can not subclass it to add additional methods. So you can not do what you are trying to do.

Java - Object state does not change after method call [duplicate]

This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 6 years ago.
Beginner java question, but I cannot understand how call-by-Value ( or Reference ) is working in the example below -
How come the String value is not modified after it exits the method while my custom String Object is. ? Same with other classes like Date..
public class StringMadness {
public static void main(String[] args) {
String s = "Native String";
CustomStringObject cs = new CustomStringObject();
System.out.println("Custom String Before: " + cs.str);
hello(cs);
System.out.println("Custom String After: " + cs.str);
System.out.println("Native String Before: " + s);
hello(s);
System.out.println("Native String After: " + s);
}
private static void hello(String t) {
t = "hello " + t;
}
private static void hello(CustomStringObject o) {
o.str = "hello " + o.str;
}
}
class CustomStringObject {
String str = "Custom String";
}
Compare these two methods:
private static void hello(String t) {
t = "hello " + t;
}
private static void hello(CustomStringObject o) {
o.str = "hello " + o.str;
}
In the first case, you're assigning a new value to t. That will have no effect on the calling code - you're just changing the value of a parameter, and all arguments are passed by value in Java.
In the second case, you're assigning a new value to o.str. That's changing the value of a field within the object that the value of o refers to. The caller will see that change, because the caller still has a reference to that object.
In short: Java always uses pass by value, but you need to remember that for classes, the value of a variable (or indeed any other expression) is a reference, not an object. You don't need to use parameter passing to see this:
Foo foo1 = new Foo();
Foo foo2 = foo1;
foo1.someField = "changed";
System.out.println(foo2.someField) // "changed"
The second line here copies the value of foo1 into foo2 - the two variables refer to the same object, so it doesn't matter which variable you use to access it.
There's an important difference between the two methods: using hello(String) you're trying to change the reference to the String, and with hello(CustomObject), given a reference, you're using the reference to change a member of the object.
hello(String) takes a reference to a String. In the function you're trying to change which object that reference points to, but you're only changing the pass-by-value copy of the reference. So your changes aren't reflected outside the method.
hello(CustomObject) is given a copy of a reference to an object, which you can then use to change the actual object. Think of this as changing the contents of the object. So your changes are reflected in the caller.
Given a reference to an object, you can change the object using it's exposed methods/fields
Because for the String you are just changing the local parameter reference.
t will point to new object and scoped to method only, so changes not visible outside.
Second case, the value you are changing will be updated to object,so those changes are visible after method call.
Doesn't work because String is an immutable object

Why references to Strings don't behave like other Objects references?

In the following code
public class Test {
public static void main(String[] args){
int [] arr = new int[]{1,2};
String b=new String("abc");
f(b,arr);
System.out.println(b);
System.out.println(arr[0]);
}
public static void f(String b, int[] arr){
b+="de";
b=null;
arr[0] = 5;
}
}
Why the reference variable of the string doesn't behave like the reference variable of the array?.
I know string are immutable so operations on them creates new string but how about references to strings and how the reference b still refer to the old value although it was changed to refer to something else in f() method.
Object references in Java are passed by value. Assigning just changes the value, it does not alter the original object reference.
In your example arr[0] is changed, but try arr=null and you will see it has no effect after the method has returned.
Method call is called by value in Java, well there is long debate about this , But I think that we should consider in terms of implementation language of Java which is C/C++. Object references just pointers to objects, and primitives are the values.. Whenever a method is called, actual arguments are copied to formal parameters. Therefore, if you change pointer to reference another object , original pointer is not affected by this change, but if you change object itself, calling party can also see the changes, because both party are referring the same object..
Well, in your example, you are changing string reference to null in called method, but you are changing object referred by array reference.. These two operations are not the same, therefore they do have different consequences.. for example, if you change the code as below, they would be semantically same operation..
arr = null;
You cnanot change the argument for any method, however you can do the following.
public static void main(String... args) throws IOException {
String[] strings = {"Hello "};
addWorld(strings);
System.out.println("Using an array "+Arrays.toString(strings));
StringBuilder text = new StringBuilder("Hello ");
addWorld(text);
System.out.println("Using a StringBuilder '" + text+"'");
}
private static void addWorld(String[] strings) {
for(int i=0;i<strings.length;i++)
strings[i] += "World!";
strings = null; // doesn't do anything.
}
private static void addWorld(StringBuilder text) {
text.append("World !!");
text = null; // doesn't do anything.
}
prints
Using an array [Hello World!]
Using a StringBuilder 'Hello World !!'

Output Parameters in Java

With a third party API I observed the following.
Instead of using,
public static string getString(){
return "Hello World";
}
it uses something like
public static void getString(String output){
}
and I am getting the "output" string assigned.
I am curious about the reason of implementing such functionality. What are the advantages of using such output parameters?
Something isn't right in your example.
class Foo {
public static void main(String[] args) {
String x = "foo";
getString(x);
System.out.println(x);
}
public static void getString(String output){
output = "Hello World"
}
}
In the above program, the string "foo" will be output, not "Hello World".
Some types are mutable, in which case you can modify an object passed into a function. For immutable types (such as String), you would have to build some sort of wrapper class that you can pass around instead:
class Holder<T> {
public Holder(T value) {
this.value = value;
}
public T value;
}
Then you can instead pass around the holder:
public static void main(String[] args) {
String x = "foo";
Holder<String> h = new Holder(x);
getString(h);
System.out.println(h.value);
}
public static void getString(Holder<String> output){
output.value = "Hello World"
}
That example is wrong, Java does not have output parameters.
One thing you could do to emulate this behaviour is:
public void doSomething(String[] output) {
output[0] = "Hello World!";
}
But IMHO this sucks on multiple levels. :)
If you want a method to return something, make it return it. If you need to return multiple objects, create a container class to put these objects into and return that.
I disagree with Jasper: "In my opinion, this is a really ugly and bad way to return more than one result".
In .NET there is a interesting construct that utilize the output parameters:
bool IDictionary.TryGet(key, out value);
I find it very usefull and elegant. And it is the most convenient way to aks if an item is in collection and return it at the same time. With it you may write:
object obj;
if (myList.TryGet(theKey, out obj))
{
... work with the obj;
}
I constantly scold my developers if I see old-style code like:
if (myList.Contains(theKey))
{
obj = myList.Get(theKey);
}
You see, it cuts the performance in half. In Java there is no way to differentiate null value of an existing item from non-existance of an item in a Map in one call. Sometimes this is necessary.
This functionality has one big disadvantage - it doesn't work. Function parameters are local to function and assigning to them doesn't have any impact outside the function.
On the other hand
void getString(StringBuilder builder) {
builder.delete(0, builder.length());
builder.append("hello world");
}
will work, but I see no advantages of doing this (except when you need to return more than one value).
Sometimes this mechanism can avoid creation of a new object.
Example:
If an appropriate object exists anyhow, it is faster to pass it to the method and get some field changed.
This is more efficient than creating a new object inside the called method, and returning and assigning its reference (producing garbage that needs to be collected sometime).
String are immutable, you cannot use Java's pseudo output parameters with immutable objects.
Also, the scope of output is limited to the getString method. If you change the output variable, the caller won't see a thing.
What you can do, however, is change the state of the parameter. Consider the following example:
void handle(Request r) {
doStuff(r.getContent());
r.changeState("foobar");
r.setHandled();
}
If you have a manager calling multiple handles with a single Request, you can change the state of the Request to allow further processing (by other handlers) on a modified content. The manager could also decide to stop processing.
Advantages:
You don't need to return a special object containing the new content and whether the processing should stop. That object would only be used once and creating the object waste memory and processing power.
You don't have to create another Request object and let the garbage collector get rid of the now obsolete old reference.
In some cases, you can't create a new object. For example, because that object was created using a factory, and you don't have access to it, or because the object had listeners and you don't know how to tell the objects that were listening to the old Request that they should instead listen to the new Request.
Actually, it is impossible to have out parameters in java but you can make a work around making the method take on a de-reference for the immutable String and primitives by either writing a generic class where the immutable is the generic with the value and setter and getter or by using an array where element 0 (1 in length) is the value provided it is instantiate first because there are situations where you need to return more than one value where having to write a class just to return them where the class is only used there is just a waste of text and not really re-usable.
Now being a C/C++ and also .Net (mono or MS), it urges me that java does not support at least a de-reference for primitives; so, I resort to the array instead.
Here is an example. Let's say you need to create a function (method) to check whether the index is valid in the array but you also want to return the remainding length after the index is validated. Let's call it in c as 'bool validate_index(int index, int arr_len, int&rem)'. A way to do this in java would be 'Boolean validate_index(int index, int arr_len, int[] rem1)'. rem1 just means the array hold 1 element.
public static Boolean validate_index(int index, int arr_len, int[] rem1)
{
if (index < 0 || arr_len <= 0) return false;
Boolean retVal = (index >= 0 && index < arr_len);
if (retVal && rem1 != null) rem1[0] = (arr_len - (index + 1));
return retVal;
}
Now if we use this we can get both the Boolean return and the remainder.
public static void main(String[] args)
{
int[] ints = int[]{1, 2, 3, 4, 5, 6};
int[] aRem = int[]{-1};
//because we can only scapegoat the de-ref we need to instantiate it first.
Boolean result = validate_index(3, ints.length, aRem);
System.out.println("Validation = " + result.toString());
System.out.println("Remainding elements equals " + aRem[0].toString());
}
puts: Validation = True
puts: Remainding elements equals 2
Array elements always either point to the object on the stack or the address of the object on the heap. So using it as a de-references is absolutely possible even for arrays by making it a double array instantiating it as myArrayPointer = new Class[1][] then passing it in because sometimes you don't know what the length of the array will until the call going through an algorithm like 'Boolean tryToGetArray(SomeObject o, T[][] ppArray)' which would be the same as in c/c++ as 'template bool tryToGetArray (SomeObject* p, T** ppArray)' or C# 'bool tryToGetArray(SomeObject o, ref T[] array)'.
It works and it works well as long as the [][] or [] is instantiate in memory first with at least one element.
in my opinion, this is useful when you have more than one result in a function.

Categories

Resources