referring to this only (not attributes), possible? [duplicate] - java

This question already has answers here:
Why is assignment to 'this' not allowed in java?
(7 answers)
Closed 1 year ago.
Context (not strictly necessary to understand the question):
I have to implement a collection of elements. The class is called DocumentCollection. It is essentially an array of lists (a rudimentary form of a hash array), better formulated: an array of references to the first element of each respective list.
I already implemented a basic constructor, which takes an int as size of the array, and puts null initialized lists in each bucket.
One method to implement is removeAll. My first idea was to generate a new collection of the same size as the original one, and assign this to this newly created collection.
Below the code of the method.
public boolean removeAll(){
if(isEmpty()){
return false;
}
int size = buckets.length;
this = new DocumentCollection(size);
return true;
}
where buckets is the array.
As this is part of an assignment, I don't want to include the code of the whole class. This is enough for my question.
Intellij gives me the following error message (w.r.t. the line with this): variable expected.
Unfortunately this message is not eloquent enough for me to understand it.
Aside Note: yes, I could iterate over the array and assign null lists to them. That's not the point I am trying to make here
Question:
Am I doing something fundamentally wrong? In other words, is trying to give a new reference to the current object (i.e. this) illegal? Or can it be done, and I am simply using some wrong syntax?

You can't assign a new value to this since it is just a keyword to represent the current object along the class code, it is not a variable.
Beside's that, think of the semantics: you are inside the object asking it to become another object, that would be very tricky!
The closest you can get to that is to wrap some object as a field of your class, then you can assign a new instance to this field. Like this:
class MyObjectWrapper{
private MyObject myObject = new MyObject();
...
public void removeAll() {
this.myObject = new MyObject();
}
}
Check this related question: Why is assignment to 'this' not allowed in java?

Related

An Array of ArrayLists (Null Pointer Exception)

i'm currently trying to add items to an generic "array" of arraylists but for some reason i keep getting a null pointer exception. The Structure is initialised and both my array index reference and the reference to the object i'm passing in are both visible within the body of code right before the exception occurs. I'm almost sure its down to the way i either declared the data structure or my way im trying to add it in. Any advice would be appreciated. Thanks in advance
ArrayList<Site>[] group = (ArrayList<Site>[])new ArrayList[entranceSites.size()];
group[i].add(sIndex(path));
sIndex is a function I'm using to convert integers to graph sites and the object is not null when I'm passing it in so i'm sure its not the problem. I is initialised and also visible to the program.
new ArrayList[entranceSites.size()];
does not actually initialize the array elements with any constructor. The array will be filled with enteranceSites.size() null elements.
You will need to iterate through the array and actually construct ArrayList objects.
Here's how you can set each element of the array to a new ArrayList using Java 8:
Arrays.setAll(group, n -> new ArrayList<Site>());
(The second argument is a function of n, the array index, but n isn't actually used. You still need to include it.)
You have allocated an array of ArrayLists, but you have not allocated any actual ArrayLists inside that array. The array initially contains all null references. So your invocation to add is on a null reference and thus causes the exception. If you say:
group[i] = new ArrayList<Site>();
Before you call add it will work.
Note that it is generally a bad idea to mix primitive arrays and Java collections, and if you are new to Java, then you should probably stick to collections since they are going to be easier to work with.
You should also be aware that the cast you are making (ArrayList<Site>[]) is unchecked and will almost certainly generate a warning assuming you have warnings enabled, which you should be enabling warnings as a beginner. This is another reason why it is not a good idea to mix generics with primitive arrays.
By the looks of your code fragment, my guess is that you failed to initialize the ArrayList<Site> element being added to the array; thus, failing when calling the List.add() method. The array itself is properly initialized, but you are trying to add a Site to an ArrayList that has not been initialized properly.
For this to work, you must create your ArrayList<Site> object. Once your lists are properly instantiated, you can add them to the array. You can add Site objects when creating the list or after you add them to the array. It does not matter when because the space in memory will be already allocated. Suppose a company has sites in many states, for argument sake, New York. All of the sites in that geographical location will be added to the NY list of sites:
ArrayList<Site> nySites = new ArrayList<Site>();
Site site1 = new Site();
group[0] = nySites;
group[0].add(site1); // Now you can call the add() method

Is it possible to rename an ArrayList? [closed]

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 9 years ago.
Improve this question
I was just wondering if there is a way to rename the variable assigned to an ArrayList... Or if I just need to create another one, just making it exactly the same.
Just create a new reference with the name you want and assign it from the old reference:
ArrayList original = ...;
ArrayList newList = original;
I should point out that since ArrayList is a reference type, original and newList are both pointing to the same data in memory. If you add an item to original or to newList, it is going to affect both. It is not creating a second copy of the ArrayList. It is a little difficult to understand what you are asking for, though.
If you are talking about refactoring your code to rename the variable across the entire application, then it sort of depends on what IDE you are using, but any good IDE will have this capability.
First, I would just like to point out that 'renaming' a variable is not really a concept that bares any resemblance to the way that changing a 'reference' or 'identifier' works. You can't change a variables identifier (kind of like a variable's name), but you can pass the variable's value to another variable with a different identifier.
When a variable refers to an Object or child of the Object class (such as ArrayList), your reference type variable holds data indicating the position of that object in memory. So passing that reference's data to another reference just means there are now two Object references that 'refer' to the same object in memory.
Technically speaking, if you wanted to give that object a name that you could use to identify it later with, this is possible by creating a custom class that extends ArrayList (or whatever object). For example;
public class NamedArrayList extends ArrayList{
private String listName = "default_name";
public String getListName(){
return listName;
}
public void setListName(String listName){
this.listName = listName;
}
}
Alternatively, you could create a Wrapper class which holds an ArrayList as well as a name for identifying it. Apologies if the last part is a little off subject, but I hope it helps.
You can try this
List<Double> original =new ArrayList<Double>();
List<Double> copy = new ArrayList<Double>(original);
You can't rename any variable while the programm is running.
But you could rename it while developing. Then compile and run.
If you mean by renaming using a different reference than you can simply do
ArrayList newListRef = oldListInstance;
//use newListRef thereafter
If you mean to change some of the elements retaining the order then -
ArrayList is dynamic in size. You can add and remove elements to and from specific index and ordering in retained. So no need to create separate List. If you want to change a specific element simply remove it and add new element at that index.
APIs
public E remove(int index)
public void add(int index, E element)

Is it possible to change a variables value from an array

This is a little confusing question for me to express, but I'll do my best.
So:
ArrayList<Object> fieldList = new ArrayList<Object>();
I then dump a lot of different variables to this array:
fieldList.add(objectsURL); //string
fieldList.add(X); //int
fieldList.add(Y); //int
...
If I change the variable, the values in the array change
too-confirming the array stores a reference to the memory, rather
then value itself.
However, if I then retrieve data from the array then set that...
Object object = ((String)this.fieldList.get(0));
Then set object
object = "meeep!"
objectsURL is not set to "meep!" but rather it retains its original
value.
I assume this is because the "object" is not referencing the original
variable anymore, that instead its pointing to a new immutable string
in the memory.
All expected Java behavior I think....but then, how would I go about
setting the actual original variable? is this possible in java?.
So, in other words. Given only access to "fieldList" is it possible to change the value of
"objectsURL"?
So, if:
String objectsURL = "www.google.com"
fieldList.add(objectsURL);
Is there a way to set objectsURL to "www.stackoverflow.com" using only a reference from fieldList?
I dont want to change the fact that fieldList contains "objectsURL", I want to change what string the variable "objectsURL" actualy contains.
If not, is there an alternative method to achieve the same thing?
I hope my question explains the problem well enough.
My use-case is trying to make a serialization/
deserialization system for a bunch of my objects. I was hoping to put
all the fields into a arraylist I could retrieve for both reading and
writing....thus avoiding having to hard-code long lists of
field[0]=blah and blah=field[0] and then going though constant pains
of needing to renumber them each time I add a new field before
another.
(I cant use Javas inbuilt serialization, as I am using GWT and this is client side only.)
Thanks,
I assume this is because the "object" is not referencing the original variable anymore, that instead its pointing to a new immutable string in the memory.
Correct, each time you use the assignment operator = on an object you change the object it refers to, not the object itself.
To change the values in the List, you use the .set method of an ArrayList
this.fieldList.set(0, newValue);
Since your variable is a String, there is no way you can change the String-variable through the list
Your alternatives:
using a char-array
List myList = new ArrayList();
char[] charArray = "My String".toCharArray();
myList.add(charArray);
charArray[0] = 'A';
String theString = new String(myList.get(0)); // "Ay String"
If you use a char-array, make sure that the length of the array is enough to contain the number of characters you want to have in the future, because to change the length of the array you will need to create a new array (array lists can be expanded dynamically, arrays can not)
Embed the String inside your own class (I have ignored getters and setters here)
class MyString {
public String value;
public MyString(String value) {
this.value = value;
}
}
MyString myStr = new MyString("some value");
list.add(myStr);
((MyString) list.get(0)).value = "a new value";
System.out.println(myStr.value); // will print "a new value"
Strings are immutable, so it is impossible to change the contents of a String object. Also, you cannot use the list to change what object the reference variable objectsURL points to. To achieve what you want, you will need to create a custom class that has a String member. You can then store instances of this class in a List and change the String references to via the references in the list. The changes will then be reflected in any other reference variables which refer to the objects in the list.
First, you declare a variable 'object' and assign some Object out of the ArrayList. Later you assign some other object "meeep!" to this variable. There is no reason that your 'object' variable is related to the ArrayList.

Java get an element from an array, edit it, then store it in another array, without altering the first array

I have encountered a problem in one of my Java projects, which causes bugs.
The problem sounds as following:
I have two arrays. Let's name them firstArray and secondArray. Object in this case is a seperate class created by me. It works, the array can be filled with objects of that type.
Object[] firstArray= new Object[];
Object[] secondArray = new Object[];
Now, when I get an element out of the first array, edit it and then copy it in the second array, the object from the first array gets altered too.
tempObj = firstArray[3];
tempObj.modifySomething();
secondArray[3] = tempObj;
Whenever I do this, the (in this case) 3rd element(actually 4th) of the first array gets the modifications. I don't want this. I want the first Array to remain intact, unmodified, and the objects I have extracted from the first array and then modified should be stored in the second so that the second array is actually the first array after some code has been run.
P.S. Even if I get the element from the first array with Array.get(Array, index) and then modify it, the element still gets modified in the first array.
Hopefully you understood what I wanted to say, and if so, please lend me a hand :)
Thank you!
You're going to have to create a new object.
The problem is the modifySomething call. When you do that, it alters the object on which it's called. So if you've only got one object (even by two names), you can't call modifySomething or they will both change.
When you say secondArray[3] = firstArray[3], you aren't creating a new object: you're just assigning a reference. Going through an intermediate temporary reference doesn't change that.
You'll need code that looks like this:
Object tempObj = firstArray[3].clone();
tempObj.modifySomething();
secondArray[3] = tempObj;
The clone() method must return a new object divorced from the original but having identical properties.
When you retrieve an element from your array, you have a reference to it. So if you modify it, the modification are shered through all the object's references.
In order to leave it intact, you should use some method like Object.clone() or create a new Object and use its constructor to initialize its fields.
The object extracted from the first array needs to be cloned to create a new instance that is seperate. Otherwise the modification will affect the object in the first array as it is the same object.
When you retrieve an element from your array, you get a reference to it. So if you modify it, the modification are shared through all the object's references.
In order to leave it intact, you should use some method like Object.clone() or create a new method which take in input your retrieved object and return a new one alike.
In Java, when you do this secondArray[3] = tempObj;, you actually put the reference to the array, not the real object
So firstArray[3] and secondArray[3] point to the same real object
What you need to do is to create a new object that is identical to your original object, and put the reference of the new object to your secondArray
It might worth to point out that default clone() function only does a shallow copy, so if you have mutable objects in your object's fields, it might cause some problems. Take a look at this article about how to do a deep copy

How to make a separated copy of an ArrayList? [duplicate]

This question already has answers here:
Closed 13 years ago.
Possible Duplicate:
Java: how to clone ArrayList but also clone its items?
I have a sample program like the following:
ArrayList<Invoice> orginalInvoice = new ArrayList<Invoice>();
//add some items into it here
ArrayList<Invoice> copiedInvoice = new ArrayList<Invoice>();
copiedInvoice.addAll(orginalInvoice);
I thought I can modify items inside the copiedInvoice and it will not affect these items inside originalInoice. But I was wrong.
How can I make a separated copy / clone of an ArrayList?
Thanks
Yes that's correct - You need to implement clone() (or another suitable mechanism for copying your object, as clone() is considered "broken" by many programmers). Your clone() method should perform a deep copy of all mutable fields within your object. That way, modifications to the cloned object will not affect the original.
In your example code you're creating a second ArrayList and populating it with references to the same objects, which is why changes to the object are visible from both Lists. With the clone approach your code would look like:
List<Foo> originalList = ...;
// Create new List with same capacity as original (for efficiency).
List<Foo> copy = new ArrayList<Foo>(originalList.size());
for (Foo foo: originalList) {
copy.add((Foo)foo.clone());
}
EDIT: To clarify, the above code is performing a deep copy of the original List whereby the new List contains references to copies of the original objects. This contrasts to calling ArrayList.clone(), which performs a shallow copy of the List. In this context a shallow copy creates a new List instance but containing references to the original objects.
If you are storing mutable objects into the ArrayList, you will need to copy each object when you copy the ArrayList. Otherwise, the new ArrayList will still hold the original references.
However if you're storing immutable objects, it's fine to use:
ArrayList copiedInvoice = new ArrayList(originalInvoice);
I thought I can modify items inside the copiedInvoice and it will not affect these itmes inside originalInoice.
This happens because what gets copied is the reference variable and not the object it self.
Hence you end up with two "references" pointing to the same object.
If you need to copy the whole object you may need to clone it.
But you might have problems if you don't clone the object internal attributes if they happen to be other objects.
For instance the following class definition won't give you any problem.
public class Something {
private int x;
private int y;
private String stringObject;
}
If you create a copy of that, you would copy the current values of its attributes and that's it.
But if your class do have another object inside you might consider to clone it too.
class OtherSomething {
Something something;
private int x;
}
If you do the following:
Something shared = new Something();
OtherSomething one = new OtherSomething();
OtherSomething two = new OtherSomething();
one.something = shared;
two.something = shared;
In this case, both one and two have the same reference variable to the same shared "something" and changing the value in one would affect the other.
That's why it is much simpler/better/easier to use immutable objects.
If you need to change the value of an immutable object you just create a new one with the correct value.
Take a look at ByteArrayOutputStream and ByteArrayInputStream. If all of your classes implement Serializable, then you can make a copy using the above mentioned classes.

Categories