I using type object and I fill it with data inside loop and at the end I want to clear the data inside ,I don't see any option to clear it (with .+CTRL SPACE) and I don't want to create new instance for it because I want to create object type just once ,is there a workaround to clear it?
I want to do the following just once for specObject, i.e. create instance type list or object and than I have loop that I fill the data inside this object ,when i finish and want to create new instance in specObject I want to clear it before ,how should I do that?
List<Object> itemObject = null;
Object specObject = null;
// Check instance type whether is list or specific object instance
if (multiplicity.equals(MULTI_N)) {
itemObject = new ArrayList<Object>();
return itemObject;
} else if (multiplicity.equals(MULTI_1)) {
return specObject;
} else {
return specObject;
}
You can call the clear method on the List object. That will remove all elements without the need to create a new instance. The documentation is here.
Just to note on object references
when i finish and want to create new instance in specObject I want to clear it before ,how should I do that?
Let's say you have a list:
ArrayList<String> strings = new ArrayList<String>();
If you add some string objects to this list:
strings.add("Hello");
strings.add("There");
strings.add("StackOverflow");
Then you nullify the strings object.
strings = null;
You have effectively removed all of the elements inside the list? Why? Well when you declare ArrayList<String> strings;, you're not creating a new object. You're creating a new reference (pointer) to an object. To illustrate this:
String s = "Hello";
String s2 = s; // s2 points to the same object that s points to.
String s3 = "Another String"; // S3 points to a different object.
The one exception to this rule is if you declare:
String s = "Hello";
String s2 = "Hello"; // s2 will point to the same object as s.
When an object isn't pointed to by anything, it is removed by the Garbage Collector. So effectively, if you declare:
strings = null;
You're removing all of the String child objects that you added to.
Related
Too many times I have to use a List of an Object instead of the object, If I use
MyObj a = null;
a.setParameter = 0;
It works.
But If I use
List<MyObj> a = null;
MyObj b = getObjectFromSomewhere();
a.add(b);
It fails with error : java.lang.NullPointerException?
And How I can see If my new List<MyObj> a is "null" or without any element inside?
A list is a container that you have to put elements into. The list has to exist prior to putting anything in it (so you can have an empty list, note).
So this:
List<MyObj> a = null;
declares a variable pointing to a null - not an actual container. Try:
List<MyObj> a = new ArrayList<>();
(note that lists come in different varieties, with different performance characteristics, and the above is just a commonly used variety chosen for illustration)
(to address your first point re a.setParameter, I guess that is a static method - defined for the class, not the instance of a class - and confusingly Java will let you reference that via an instance)
Eclipse allows you to initiate it to a null because Eclipse thinks that you will be pointing an object to this reference somewhere later in your code.
so its your responsibility to have it refer to an object before using any of the List methods.
doing this List<MyObj> a = null makes no initialization in memory so a point to nothing
what you should do is
List<MyObj> a = new ArrayList<>();
a.add(getObjectFromSomewhere());
How I can see If my new List a is "null" or without any element
inside?
if(a == null){...} // to check if array not initialized
if(a.size() == 0){...} // to check if array have no element
keep in mind calling a.size() when a is null will throw NullPointerException
variable1 = value_of_A;
for loop {
//some calculations over value_of_A,
//so it is not anymore the same as in variable1
}
variable2 = value_of_A;
When I compare variable1 and variable2 they are the same ALL THE TIME. I have tried new class so a setter can store the value, methods, all type of variable definitions etc.
Possible solution so far: to write variable1 to a file, and then read it after the for loop. This should work, but any other solution?
I guess your problem is that you are working with objects, and in Java objects are passed by reference. It means, that you may have one object and two variables referencing it, and when you change the object via the first reference variable (variable1), the second reference variable (variable2) now gives you access to the same object, that has changed. Your solution is to create a new object inside your loop and assign a reference to this new object to your variable2, so that you will have to distinct objects with a single reference to each one of them.
// suppose this is the class you are working with
public class SomeObject {
private String nya;
public SomeObject(String value) {
nya = value;
}
public String getValue() {
return nya;
}
public void changeByValue(int value) {
nya += "Adding value: " + value;
}
}
// and here comes the code that changes the object
// we assign the first variable the original object
SomeObject variable1 = someObject;
// but we do not assign the same object to the second one,
// instead we create the identical, but new object
SomeObject variable2 = new SomeObject(someObject.getValue());
for (int i = 0; i < 10; i++) {
// here we change the second (new) object, so the original stays the same
variable2.changeValueBy(i);
}
System.out.println(variable1 == variable2); // false
System.out.println(variable1.equals(variable2)); // depends on implementation
In Java, when working with objects, you're actually just having a reference to that object. That means, if you have something like this
SomeObject o1 = new SomeObject();
SomeObject o2 = o1;
then o1 and o2 point to the same object, thus changes made in o1 are also affecting o2. This is called Aliasing.
In order to compare two different objects you could for example use a copy of your object before changing it in your for loop.
// This is the object we want to work on.
SomeObject changing = new SomeObject();
// Copy-Constructor, where you assign the fields of 'changing' to a new object.
// This new object will have the same values as 'changing', but is actually a new reference.
SomeObject o1 = new SomeObject(changing);
for loop {
// This operation alters 'changing'.
someOperationOn(changing);
}
// Again, a copy constructor, if you want to have another, different reference.
SomeObject o2 = new SomeObject(changing);
Now you have two objects o1 and o2 which doesn't affect each other anymore.
What is the type of your variables? It seems to me that it is a "by value" vs "by reference" issue. Look at this question here.
Essentially, depending on the type of your variable, the "=" followed by calculations does not create a new object. You just have one more reference to the same object in memory.
This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 6 years ago.
I have below two situations related to ArrayList get method, one with custom class and one with String class:
1. Below is the example of modifying Custom class ArrayList element:
ArrayList<MyClass> mTmpArray1 = new ArrayList<MyClass>();
MyClass myObj1 = new MyClass(10);
mTmpArray1.add(myObj1);
MyClass myObj2 = mTmpArray1.get(0);
myObj2.myInt = 20;
MyClass myObj3 = mTmpArray1.get(0);
Log.d(TAG, "Int Value:"+myObj3.myInt); // Prints "20"
2. And below is the example of modifying String ArrayList element:
ArrayList<String> mTmpArray2 = new ArrayList<String>();
mTmpArray2.add("Test_10");
String myStr1 = mTmpArray2.get(0);
myStr1 = "Test_20";
String myStr2 = mTmpArray2.get(0);
Log.d(TAG, "Str Value:"+myStr2); // Prints "Test_10"
So in case of MyClass ArrayList, when I call get and modify the value, then I see change is reflecting when I do get again.
But same way when I modify String ArrayList, then changes are not reflecting.
What is the different in of the get method in both the scenarios?
Is it that in case of String, String class creating deep copy and returns new object, and in case of Custom class shallow copy is created?
In the first scenario applicable to "LinkedHashMap", "HashMap" and "List"?
Your are not doing the same thing in the two cases.
Here you update the state of an object, so the change affects the object stored in the list :
myObj2.myInt = 20;
Here you are assigning a new object to a local variable, so the list is not affected :
myStr1 = "Test_20";
If String was mutable, you could have modified the String by calling some method, and the change would have been reflected in the object stored in the list :
myStr1.setSomething(...);
On the other hand, if in the first case you would have changed the value of the local variable, the object stored in the list wouldn't have been affected :
myObj2 = new MyClass (...);
Strings are immutable. You're not inserting the new string into the array list.
When you do String myStr2 = mTmpArray2.get(0);, even tho you are pointing to a reference in the ArrayList, any attempt to change the value, will (because of String immutability) create a new String (myStr2) that will not reference the ArrayList anymore.
When you do myStr1 = "xxx", you're not actually changing the ArrayList reference, you're changing a new (copy) (now called myStr1) that was grabbed from the ArrayList and it has a local scope.
Read some more about Strings: Immutability of Strings in Java
Now in the first example, you are pointing to a mutable object (your custom class) so you're literally changing the direct value, through the reference. Welcome to Java. ;)
Unrelated: This code: MyClass myObj1 = new MyClass(10); is (arguably) considered bad. It's better to use a factory pattern that is a lot easier to read. In other words, public constructors with parameters are hard to read (for example, I have no idea what I am constructing when I read your code).
A (perhaps) better approach would be: MyClass myObj = MyClass.createInstanceWithCapacity(10); // i've invented the name because I don't know what your 10 is, but look at both, which one do you think is easier to understand upon first glance?
Disclaimer: The above unrelated comment is my personal opinion and not all developers will agree. ;)
Strings have very nice property called "Immutablity"
This means that String cannot be mutable (changed), when we create/
try to refer to old string, a new instance string is created. And any
changes we do are saved in new instance and it do not affect the old
string
For example,
String s = "Old String";
System.out.println("Old String : "+s); // output : Old String
String s2 = s;
s2 = s2.concat(" made New");
System.out.println("New String : "+s2); // output : Old String made New
System.out.println("Old String is not changed : "+s); // output : Old String
These is no difference between the two "get" calls. The difference is between the types that the ArrayList is holding, and what you're doing the references the "get" method returns.
In your first example, you do this:
MyClass myObj2 = mTmpArray1.get(0);
myObj2.myInt = 20;
Here, you're getting a reference to the MyClass instance in the ArrayList in position 0, and you are modifying a field within this instance.
In your second example, you do this:
String myStr1 = mTmpArray2.get(0);
myStr1 = "Test_20";
Here, you're getting a reference to the String instance in the array list, and then you're giving myStr1 a reference to a different string which you create ("Test_20"). It's as if you did wrote myObj2 = new MyClass(20); in the 2nd line in the 1st example.
So, in short, in the 1st example, you access a field within the object by altering it from the reference you grabbed. In the 2nd example, you simply altered your reference to point at a different String.
I should also mention that in Java, Strings are immutable, meaning once they have been created, they cannot be changed.
String is an immutable class. A line like
myStr1 = "Test_20";
does not change the value of the String object myStr1 is pointing to. Instead a new String is created and myStr1 is modified to point to the new String. The original String is unchanged and can be retrieved from the ArrayList.
Your MyClass object is clearly mutable. Only one instance is created and its state is changed by the assignment
myObj2.myInt = 20;
Hence when this object is retrieved from the ArrayList, its new state is seen.
You simply do NOT change the list in your 2nd example.
In the first example, you are doing this:
Get the first object from the list and store it in the variable called 'myObj2'
Modify the object stored in variable 'myObj2' by setting the int value of this object
But your second example is completely different:
String myStr1 = mTmpArray2.get(0);
myStr1 = "Test_20";
Let me translate that:
Get the first element from the list and store it in the variable called 'myStr1'.
Set the value of the variable 'myStr1' to "Test_20"
So, in case one you are modifying a variable of the object stored in the list. In case two you are retrieving the object stored in the list - and then re-use the variable you stored that retrieved object in and use it for something new - but that does not change the original list, of course.
To modify your list for a type like string, you would need to use set(x, "Test_20").
I am working over Java collections.
I found something strange and not getting why is this happening.
So here is the scenario.
ArrayList al = new ArrayList();
al.add("Hello World");
//The below line is creating some confusion
System.out.print(al.get(0));
Now the last line is printing "Hello World" as it is.
But as i am not using any type parameter it should give an object type in return.So it should call the Object's toString() instead of String's toString().
Does it depend on the object type which is getting saved (like String here ) of the return type (like Object).
Please help.
Actually all the trick is not related to generics even you snippet showcase it.
It related to overriden methods, toString() is defined in the super super class Object and overriden in the String class, that are evalutated at runtime using the actual object type and not its reference, i.e when calling:
Object o = new String("hello");
o.toString(); // Here at runtime, the JVM will call the "hello" toString method and not the Object one.
In you code, you have called:
al.add("Hello World");
The above line do the following:
Creates a new String object with Hello World as a literal and add it to the string pool.
Makes the first element in the list (element at index 0) reference that object (that is a String one).
Now when calling System.out.print(al.get(0));:
The first element of the list, which is an Object reference to a String object, got his toString() method called and which as already said will evalute to the object real type and not the refence type, i.e. you will have String#toString method called.
If you want to return Strings from a collection you'll have to initialise it like this, using a String type parameter:
ArrayList<String> al = new ArrayList<String>();
// ^^^^^^^^ ^^^^^^^^
al.add("Hello World");
String value = al.get(0); //<-- now you can get Strings
Now, however you will only be able to get objects, and you will have to cast before getting back to your original type:
ArrayList al = new ArrayList();
al.add("Hello World");
Object object = al.get(0); //<-- ok
String value = (String)al.get(0); // <-- ok
value = al.get(0); //<-- wont compile
Edit
ArrayList al = new ArrayList();
al.add("Hello World");
Object object = al.get(0); //<-- ok
String value = object.toString();
In this case, calling object.toString(), will just return the object as a String. It will call the toString method on the String class, which just returns itself.
When calling a method of an object, the actual method that is called is of the actual type of the object. This is why the toString that is actually called is the String class method.
BTW: generic types are for compile-time, and not for runtime. For example you can't have in the same class 2 methods like:
void foo(List l) and
void foo(List l) since after compiling both have the same signature.
I am receiving input from my Ext JS application on the front end and I want to compare two records on the java side, the record prior to a form update on the UI side and the record after setting all the new values. I have made two references to the same type of object, one before setting new values (oldRecord) and one after (newRecord) and compare these but when I try to use oldRecord.getClass() on the old record it will show the new field values. Is there any way to have access to the old values? I also tried making two field arrays and passing those into my method.
private static Map<String, List<String>> changes;
public static <T> Map<String, List<String>> getChanges (T oldRecord, T newRecord) {
changes = new HashMap<String, List<String>>();
try {
if(oldRecord instanceof UserInfo && oldRecord.getClass().equals(newRecord.getClass())) {
Field field = oldRecord.getClass().getDeclaredField("name");
field.setAccessible(true);
System.out.println(field.get(oldRecord));
field = newRecord.getClass().getDeclaredField("name");
field.setAccessible(true);
System.out.println(field.get(newRecord));
// will loop through all fields in both records and compare
}
} catch (Exception e) {
System.err.println("Exception");
}
return changes;
}
I think you are using the same object. This is the case if you have done something like this:
Object oldRecord = new Object();
Object newRecord = oldRecord;
newRecord.doSomethingThatModifyIt();
getChanges(oldRecord, newRecord);
If you have done something like this, then keep in mind that Object newRecord = oldRecord; does not create any new object, but just sets the 2 variables to point to the same object.
You should instead create a new object based on the old one, with some method like clone() that you would have to implement. Or just by manually setting the fields of the newly created object.
Note: I have used Object but it could be any type of course.
If oldRecord and newRecord reference the same object like
T oldRecord = new T();
T newRecord = oldRecord;
they will "hold" the same instance variable values as well.
To save in oldRecord the old values you must do a deep copy of the object, that means create a new object and copy the instance variable values.
SEarch for deep copy or cloning, maybe start here: How do you make a deep copy of an object in Java?