Lets say I have list of Scenarios in a Game, and lists of Players. Each player plays some scenario from the Scenario list in Game. I don't want to have copy of Scenario in Player, I want to have something like pointer to the list in Game object, so that if any scenario is edited, it is also edited in Player list.
Game
Scenarios : list
Player
Scenarios : list -> each scenario here is a reference to scenario in Game
Now It would be simple in language supporting pointers, but Java is supposedly pass-by-value. At the same time, I know there are hacks using passing values inside tables etc. Is it possible to do this or not?
What have you tried? If you would have tried putting the reference into separate lists you would have known that they are the same reference. The term "pass-by-value" is tricky here because you will get a reference to the same object in your methods for example but java passes around copies of references. So basically java passes around values of references.
If you put the same reference in all your lists the changes to the original will be reflected in them.
SomeObject o = new SomeObject();
list0.add(o);
list1.add(o);
list2.add(o);
o.setSomeValue(true);
// all lists will "see" the changes
list0.get(0).equals(o); // assuming list0 only contains o -> this is true
As a rule of thumb: if you don't mess (swap, assign, etc.) with references and only call methods on the objects the references point to you'll be fine.
In your case, if Player object has a Scenario object, not the whole scenario will be copied (or cloned), only the reference of Scenario will be copied. And you can modify the Scenario either through reference by Player or through the List; as it is one object many references.
1st way
I would use interface in your case. Something like:
public class Scenario implements ScenarioItf{/**/}
And the Player will store only ScenarioItf.
2nd way
To store Scenarios list into Factory class:
public class ScenariosFactory {
private static List<Scenarios> mScenarios = null;
public static void create(List<Scenarios> scenarios) {
mScenarios = scenarios;
}
public static List<Scenarios> getFactory(){
if ( mScenarios == null )
throw new NullPointerException( "...null..." );
return mScenarios;
}
}
So both classes Player and Game can use the same source.
Java is pass-by-reference, so if you have a Scenario object in the list AND in the Player object, they will both be a pointer to the actual Scenario object in memory.
Edit: Apparently, it's sort of by-reference but technically not really. As long as you don't go scenario = new Scenario() at either end, it will be the same object.
Related
Most of the linked list implementations in C++ are like this, a pointer reference will be used as the type for the "next" node
class Node {
public:
int data;
Node* next;
}
But for languages like C#, Java and Python, why pointer is is not directly used? I could see only this kind of implementation:
// C#
class Node {
int data;
Node next;
}
// Java
class Node {
int data;
Node next;
}
What is the underlying difference? Ofcourse Java doesn't support pointers, but what about c#?
CPP"s Node* is equivalent to java's Node, and I'm pretty sure C#'s Node as well. In java, all primitives are the direct value. The primitives are int, long, short, byte, char, double, float, and boolean. These are passed directly, by value: If you call a method passing 5, 5 is pushed onto the stack. If the method you invoke changes their value, the caller can't tell.
But aside from that hardcoded list of primitives, all other types are called references which is just java-ese for pointers - except in java, you can't do pointer arithmatic. at all. You can't ask for 'the memory location 5 higher than where-ever this object lives', like you can do in C.
Here's a trivial example:
class Example {
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("Hello!");
System.out.println(list);
example1(list);
System.out.println(list);
example2(list);
System.out.println(list);
}
static void example1(List<String> in) {
list.add("World!");
}
static void example2(List<String> in) {
in = new ArrayList<String>();
in.add("Bye!");
}
}
This will print:
[Hello!]
[Hello!, World!]
[Hello!, World!]
example1 never changes the variable (The reference), it merely 'dereferences it' (follows the pointer), thus the changes you make are observed in the caller.
But example2 has no effect on main's list variable: It reassigns the variable (makes a new object and then updates its reference to point at this new object). example1's list doesn't change; its pointer doesn't change.
It's like treasure maps: Everybody has a copy of the treasure map, but not of the treasure. in.add is like: "Follow the map, open the treasure chest, put a new item in". in = new ArrayList is: "Make a new treasure chest, bury it in the sand, wipe out this treasure map, and now write the location of this newly buried treasure chest on it". If I have a copy of your map, if you follow your copy and add to the treasure then I'll see that if I later follow my map. But if you make an entirely new map, then whatever you do to the treasure at your new location is never going to be noticed by me.
This matches C++'s behaviour.... at least, for Node*. Not for Node.
What is the underlying difference?
Probably none at all. At the machine-code level, each node contains the address of the next node in the chain.
The question is, rather, about how languages represent objects in source code. Is a variable declaration written as Foo bar (for example) going to be an actual instance of the type Foo or is it going to be a way to get at (handle, pointer, reference) the actual instance. If it's the actual instance, your language probably also needs some syntax to describe not-the-instance but way-to-get-at-the-instance. Perhaps more than one way (Foo*, Foo& in C++).
The possibility of different approaches is one reason why we have different programming languages.
In C++ variables (objects) can be passed by three ways:
by value
by pointer
by reference
(all of them are in reality passed by value, but very specific one)
In e.g. Java, objects are always passed by reference, while primitives by value. There are no pointers or explicit references in Java.
In C++ when you stop needing an object, you need to use delete to remove it. In Java, you just need to replace variable or just don't use it - GB will remove it for you.
After reading the posted answers and other stackoverflow stuffs related to references and pointers like this one C++ references Vs C# references
This is what Makes more sense to me,
C# References are Managed references. But in C++ there is no such
manged environment hence we need to allocate and carefully
de-allocate the memory. In C# this will be manged automatically by
GC. So it is recommended to use references where ever possible rather
than directly using pointers.
Similar to C++ Pointers, C# can also hold nulls. C++ pointers hold
address of a memory location, C# References holds the address of
another object in the memory.
In C# we can use pointers only under unsafe scope, and in java there is no such pointer concepts.
Taking all this into account we can use references rather than pointers for programming languages that execute in a managed environment.
Feel free to edit if this answer can be further improved!
I have seen some people using the topmost parent class as a variable type to hold the child instance and some people use just parent class only. For example:
Collection obj = new ArrayList();
Or
List obj = new ArrayList();
Here, List comes under the Collection only then can’t we use above first line instead of second?
Again, we can't use everywhere in collection framework the reference variable of Collection class only to hold any instance of the class under Collection?
Is this a good practice?
So, I wanted to know which comes under the best practices and why?
If someone could justify technically like performance concerns etc. would be greatly appreciated.
It really really depends on your needs. In your example it doesn't really changes much for basic needs but if you inspect the two interfaces there are some changes. Look :
https://docs.oracle.com/javase/7/docs/api/java/util/Collection.html
and
https://docs.oracle.com/javase/7/docs/api/java/util/List.html
We can notice that the List gives you access to methods Collection doesn't.
set(int index, E element) for instance is defined in the List interface and not in Collection.
This is because every classes inheriting from Collection don't need to implement all the same methods.
Performance wise it have no impact.
Always use the top-most parent class that have all the functionalities you need. For your example there is no need to go higher than List .
There is no so called "best practice" for choosing the class to be used for the reference type. In fact, the class in the highest hierarchy is the Object class. Do you use Object as the reference type for everything you do? No, but generally you may choose the higher class with the all the methods available for your needs.
Instead of following the so called "best practice", apply what suits best for your situation.
These are some pros and cons for using higher hierarchy classes as reference type:
Advantage
Allows grouping of object which shares the same ancestor (super class)
Allows all instances of the given class to be assigned to it
Animal dog = new Dog();
Animal cat = new Cat();
Allows polymorphism
dog.makeNoise();
cat.makeNoise();
It is only an advantage when you are accessing common behaviours or members.
Disadvantage
Requires casting when you are accessing behaviours which exist in one object but not the other.
dog.swim(); //error, class Animal do not have swim()
((Dog)dog).swim();
As you start dumping various objects in the common parent class, you may have a hard time trying to figure out which members belongs to which class.
(Cat(cat)).swim(); //error, class Cat do not have swim()
The general idea is hiding as much as you can so things are easier to change. If you need indexing for instance (List.get(int index) then it MUST be a list because a collection does not support .get(index). If you don't need indexing, then hiding the fact you're using a list, means you can switch to other collections that might not be a list later without any trouble.
For example, maybe one month later I want to use a set instead of list. But Set doesn't support .get(index). So anybody who uses this List might use the indexing features of a list and it would make it difficult to switch to a set because every where someone else used .get(), would break.
On the other hand, excessively hiding your types can cause accidental performance issues because a consumer of your method didn't know the type. Suppose you return a List that's actually a linkedlist (where indexing is O(n)). Suppose the consumer of this list does a lookup for each entry in another list. That can be O(n*m) performance which is really slow. If you advertised that it was a linked list in the first place, the consumer of the linkedlist would realize that it's probably not a good idea to make multiple indexes into this list and the consumer can make a local copy.
Library code (suppose the one you're designing)
public class Util {
public static List<String> makeData() {
return new LinkedList(Arrays.asList("dogs", "cats", "zebras", "deer"));
}
}
Caller's code (suppose the one that's using your library or method)
public static void main(String [] args) {
List<String> data = Util.makeData();
int [] indicesToLookUp = {1,4,2,3,0};
for( int idx : indicesToLookUp ) {
if(idx < data.size()) {
// each index (LinkedList.get()) is slow O(N)
doSomethingWithEntry(idx, list.get(idx));
}
}
}
You could argue it's the caller's fault because he incorrectly assumed the List is an ArrayList<> and should have made a local copy of the list.
I'm having an odd problem that I haven't encountered before with copying objects in Java.
So, I've written a class in my code called "State". This contains a few ints, a 2d array, a string and such...
So, for an instance of State called S, I want to make a copy of it called X (I do this simply by writing State X = S; ). Then I want to make changes to X, do some evaluations based on those changes and then just throw away X and keep using S. However, the problem I'm getting is that S seems to be getting the changes that I make to X.
This seems odd to me, since I feel quite certain that I've done things like this before but never had this problem.
Any thoughts?
(Thanks in advance)
I want to make a copy of it called X (I do this simply by writing State X = S; ).
That does not make a copy of the object.
Variables (of non-primitive types) in Java are references - they are not the objects themselves. By doing
State X = S;
you are not copying an object, you are just copying the reference - the result is that you now have two variables that are referring to the same object. If you modify the object through one reference, you'll see the changes also through the other reference.
One way to copy objects is by using the clone() method. For this to work, the class of the object that you are trying to copy must implement interface Cloneable. Another (and probably better) way is to create a copy constructor, and use it to copy the object:
public class State {
public State(State other) {
// initialize this object by copying content from other
}
}
// Make a copy
State X = new State(S);
Your code is not creating a copy of the object. What you are doing there is creating a new reference and pointing it to the same object.
Search for "how to clone an object in Java". Read up on the Cloneable interface.
class Some{
private int id;
private String name;
//getters and setters
}
class Check{
private Some[] someVals;
//getters and setters
}
Assume I have populated values into the someVals in Check class
void newMethod(){
Check checkPrev = getCheckPopulated();
Some[] someFirst = checkPrev.getSomeVals();
modifySome(someFirst);
Some[] some = ? // at this point need the values of someFirst
}
My question is to get the value of the Some[] array even after the modification(where i have specified), that is the values which were first present when assigned.
fine I will make my question clear.
final Some[] someFirst = checkPrev.getSomeVals(); didnot work
Is there a small tip similar to final by preserving the arrays value without having to reassign all the values to another array all over again?
You can't have your cake and eat it also. You have to make a deep copy of the object, and then modify the original copy. Then, the deep copy will contain the original values.
In your modifySome method, return a new Some[] array.
Some[] modifySome(Some[] passedArray){
Some[] result = new Some[passedArray.length];
System.arraycopy( passedArray, 0, result , 0, a.length );
//Modify result as needed
return result
}
If you cange modifySome to return an array, your code can change to:
Some[] some = modifySome(someFirst);
After that line, someFirst will still be the same as it was before and some will be the modified values.
One option is to use a CopyOnWriteArrayList.
CopyOnWriteArrayList<Some> someFirst = checkPrev.getSomeVals();
Iterator iterator = someFirst.iterator();
modifySome(some);
The iterator will still be referring to the original list, not to the modified list.
Another option is to make a copy of the original array.
Some[] someFirst = checkPrev.getSomeVals();
Some[] someCopy = new Some[someFirst.length];
System.arrayCopy(someFirst, 0, someCopy, 0, someFirst.length);
modifySome(some);
someCopy will still hold a copy of the original array.
Welcome to the mutable world of Java beans.
You cannot do what you want to do... But here is a solution using a couple of interfaces I wrote:
// Both classes in the same package
#Immutable // by contract
class Some implements Frozen<SomeBuilder>
{
// All fields are final, package local
final String name;
// getters only -- NO setters
public Some(final SomeBuilder builder)
{
name = builder.name;
// other
}
// Return a thawed version
#Override
public SomeBuilder thaw()
{
return new SomeBuilder(this);
}
}
#NotThreadSafe // by contract
class SomeBuilder implements Thawed<Some>
{
// Mutable fields here, package local
String name;
// other
// To create a new builder
public SomeBuilder()
{
}
// Package local constructor
SomeBuilder(final Some some)
{
name = some.name;
// etc
}
// Mutations
public SomeBuilder setName(final String name)
{
this.name = name;
return this;
}
// Return a frozen version
#Override
public Some freeze()
{
return new Some(this);
}
}
Now, as to your modify function, make it return a NEW array. And use .freeze()/.thaw() to create new instances of Some from existing ones.
One of the weaknesses with Java is that there is fundamentally only one non-primitive type: the promiscuous heap object reference. There is no way that an instance of class George which holds a reference to a object Foo of class Bar outside its package can share that reference with outside code without giving that outside code the perpetual ability to do anything to Foo that George can do with it. Part of the design goal of Java is to be easy to implement even on simple hardware systems, and having a single non-primitive type helps it achieve that goal. On the other hand, it also means that the programmer is required to keep track of which object references serve to encapsulate:
Immutable aspects of object state other than identity, which cannot be changed even by code which holds a reference.
Object identity (as well as, perhaps, other immutable aspects of state)
Aspects of object state which would be mutable, except that they are expected never to be given to code that would actually mutate them, but not identity.
Mutable aspects of object state which are "owned" by the code which hold the reference, but not identity.
Mutable aspects of object state, as well as identity.
In your code, because arrays are mutable, your array-type field cannot have the first meaning, but it could hold any of the other four. In addition, the elements of the array could hold any of the above kinds of things. If you consider the state of your object to be the combination of id and name pairs held in its array, if the id and/or name of a Some to which the Check holds a reference could change, and if such a change would be considered a change in the state of the Check, then making a copy of the Check's state would require creating a new array, and populating it with new Some instances whose data is copied from the corresponding instances in the original array.
If none of the Check objects which are in the array will ever be exposed to code that might mutate them, then it would not be necessary to construct new instances of the individual Check objects; creating a new array and populating it with references to the objects in the original array would suffice. Likewise if the purpose of the array is to encapsulate the identities of Check objects which are defined elsewhere and thus changes to those objects would not be considered changes to the Check's state. Note that in the former situation (the objects never change), replacing the Some objects with new instances that hold the same data would be inefficient but would not break anything. In the latter situation (the array encapsulates the identities of the objects, rather than their states), replacing the references with references to new instances would break the code.
While many people talk about "deep cloning" or "shallow cloning", such terminology mainly stems from the lack of clarity about what various object references are supposed to encapsulate. If object Fred has a class-type field that encapsulates mutable state which Fred owns (but does not encapsulate identity), a copy of the Fred should hold a reference to a copy of that object. If a field encapsulates immutable state, a copy of Fred could hold a reference to the original object or any immutable copy thereof. If it encapsulates identity, a copy of Fred must hold a reference to the original object--not a copy. If it encapsulates both identity and mutable state, then Fred cannot be copied without also copying the entire forest of inter-connected objects of which it is a part.
I understand that in order to copy an arraylist and have two lists independent of one another you must use a deep copy (copying the objects from one list to another not just the references), however is there a way this can be done cross-class?
For example; I am calling Class2 from Class1. In Class2 objects are added to an ArrayList of custom objects upon an event. I would like to be able to transfer this ArrayList to Class1 but whenever I try I get a NullPointer.
Any clues??
This is highly indicative of a design flaw.
See if you can't accomplish the same goal by wrapping your list in a class, sharing the class and using it to control access to the list.
The only case where this wouldn't just outright work is if your two classes must modify the list independently.
If this is a requirement, then I would probably hand a different instance of the wrapper class to each modifying class (with a reference to the same source list), then have a way for newly added data to be tagged with an ID referring to the original class--that way when you query, the wrapper would only return untagged items (items that were part of the original shared list) and items tagged with it's own ID.
Either that or the wrapper class could contain a second list and when queried, return the combined results of the original and second lists.
I've almost never wanted a deep copy. It happens, but it's quite rare.
If you post more info, maybe we can be more specific in helping with the redesign.
ALSO: (Edit)
Chances are that the copied array list isn't your problem--it's probably that it wasn't TRULY a deep copy. For a deep copy, it means you implement a copy method (I believe they are supposed to be called .clone(), I never use this stuff--as I said, it's bad juju) for each object in the array list, then you call your copy method on each one to get the new copy in your next list.
Furthermore, any objects referenced by your copied object should probably be cloned as well. "Deep" means all the way down the tree.
I'm guessing you're failing somewhere in the process.
I'd really like to hear why you feel you need a copy instead of a reference.
My suggestion is for you to create a getArray() method and call it from the other class. This method should create a copy of the ArrayList because you should not "transfer" variables within classes; always with get() method so OO paradigm stays intact.
Do something like this:
Class 1
public ArrayList<Object> getArray() {
ArrayList<Object> aux = new ArrayList<Object>();
for(Object x : list) //object is the string, int, etc...
aux.add(x.clone()) //assuming the Object has a clone method!
return aux;
}
On Class 2, just call this method. Then just look at the test from the other answer about the null exception, should work.
Hope it helps.