Accessing private variable of Model class without getters - java

I have a Model class defined in my project. and as usual it has some private variables and public getters and setters
public class Person{
private ArrayList<String> mark;
public void setMark(ArrayList<String> mark){
this.mark = mark;
}
public void getMark(){
return this.mark;
}
}
Suppose in some other class I am using this Model like
Person person = new Person();
ArrayList<String> mark = new ArrayList();
mark.add("10");
mark.add("15");
mark.add("18");
person.setMark();
then the private variable of person holds the value "my name", the I am accessing the variable using public getter of the class like
ArrayList<String> localMark = person.getMark()
so as per my knowledge person.getMark() returns the reference of private variable name, so if I modify the local variable 'localMark', then it will effect the private variable of Person class, so there it breaks the private property of the variable
ex:
ArrayList<String> localMark = person.getMark();
System.out.println(localMark.get(0)); // will be "10"
localMark.set(0,"25") // person.mark will be changed
System.out.println(person.getMark().get(0)); //will be printing "25"
most of the developers following the same design pattern I guess, but what is the correct way to create Models
EDIT
As per the comment of vinod I checked, and Strings it passes value but not reference but for ArrayList... it returns reference.

You have a reference (name) to an object instance (the value of name). As the reference is private, you're in full control of it.
When you return a reference, you in fact return it 'by value', meaning that a copy of the reference is returned. Both references point to the same value (the String instance)).
An outside caller obtaining the reference can assign a new value, but your model's own reference is unaffected by that and still points to the value.
It's like a dog (object) on a leash (reference).
When you return a reference you're returning a new leash onto the same dog.
The owner of the new reference can modify your dog (pet it, shave it, whatever) when the dog is mutable (which Strings are not, so it cannot be modified)
...or he can attach a new dog to his leash
...but he can never (reflection aside) attach YOUR leach to another dog.

If the instance being exposed by call to get() is mutable, then whatever changes you make in some other place will be reflected in the instance everywhere it is used.
Example :
methodX classA -
List<String> locaNamesList = person.getNamesList();
locaNamesList.clear();
Somewhere else
methodY classB -
List<String> locaNamesList = person.getNamesList(); // note the same person instance should be used.
//locaNamesList will be empty here
Just re-assigning the reference won' change anything.
List<String> locaNamesList = person.getNamesList();
locaNamesList = null; // won't change the actual list. You are setting local field locaNamesList to null and not the actual instance.
You have to use defensive-copies of mutable instances and pass them around if you don't want the original instance to be changed by external players (provided you can't make the instance itself immutable)

Related

Stack variables in Java (newbie)

I am staring to study java and currently I am learning about the classes setters.
I see that the most common way to make a setter is something like this.
class Apple{
private String _name;
//Setters
public void setName(String name){
_name = name;
}
}
I am used to C so this code raises me a question. If I am setting _name = name in a function, after this function is completed and his stack is discarded why does the variable _name still stores the right value? This is confusing because in C if I assig a pointer to another pointer inside a function like this it would probably cause a segmentation fault (since name is a temporary variable).
In Java, you as an user don't have control over the stack as in C/C++ languages.
In addition, all non-primitive data types (int, double, etc.) are stored in the heap. The user is only able to use references or pointers and is not required to perform any kind of memory management, since a mechanism known as garbage collector already frees those instances which haven't any reference to them. Therefore, there are no such thing as pointers in Java, although you can assign a null value to a non-primitive variable: Foo f = null;
Therefore, in Java you could literally behave what this C++ code does:
class Foo {
Foo( int a ) {}
};
void bar( int a ) {
Foo f(a); // f is placed in the stack
}
The only way you can create an instance of Foo in java would be like this:
void bar( int a ) {
Foo f = new Foo(a); /* f is a reference to the new instance
* (placed in heap) */
}
Actually, name is an instance variable and setName() is an instance method. This means that there is a separate copy of name for every object of the class Apple. The setName() method sets the value for the global variable of the object it is called with to that of its argument. So, even after the stack of the method is discarded, the object exists and so does the value of this object's copy of name. See this example below:
class Apple {
private String name; //instance variable
public void setName(String name) {
this.name = name; //same as what you have written
}
//main method
public static void main(String[] args) {
Apple obj = new Apple(); //object created
Apple obj2=new Apple();
obj.setName("Yolo");
obj2.setName("Yay!");
System.out.println(obj.name); //displays obj's copy of name that holds the value "Yolo"
System.out.println(obj2.name); //displays obj2's name
}
}
This displays
Yolo
Yay!
I hope this makes it clear to you.
You are setting the reference of name to the reference of _name so they look in the same spot in memory. Therefore when the instance of setName disappears and the variable name with it the reference stored in _name remains.
Since you set _name to private it can only be accessed inside the class Apple. You cant change it within your main method and that's why you create the set method so it can be changed by outside classes (I.e. Your main method)

Cloning objects in Java

An abstract taken from Herbert Schildt book on Java
Cloning is a potentially dangerous action, because it can
cause unintended side effects. For example, if the object
being cloned contains a reference variable called obRef,
then when the clone is made, obRef in the clone will refer
to the same object as does obRef in the original.
If the clone makes a change to the contents of the object
referred to by obRef, then it will be changed for the original object, too.
So when the object is being cloned, do the references pointing to that
original object also gets cloned and as such these points to to the cloned object?
I am confused at this line "...obRef in the clone will refer
to the same object as does obRef in the original...".
Consider the difference between references to the original object, and references within the original object.
Suppose you have an object myObj of type MyClass which contains a field of type ArrayList named myList.
When you constructed this object, myList was initialized with new ArrayList() and is now pointing to an object in the VM's heap.
Now suppose you clone myObj
MyClass myClone = myObj.clone();
The variable myClone is pointing to a different object than myObj. They are two distinct objects. However, the myList field inside of myObj is pointing to the same object in the heap as myList in myClone. This is because when you clone, the references are copied as-is, there is no new ArrayList() that assigns a separate object to myList in the new object.
No references are ever changed automatically, so any references to your old myObj still point to it. The only reference you have to the new object is myClone until you assign it to additional variables. But the same is true for myList. So the two objects point to the same ArrayList. So if one of them adds to it, the other one sees the added values.
Normally, that's not what you need.
Lets say, I have a class called Another as shown :
public class Another {
int number;
String message;
// And so on.
}
And another class called CloneMe overriding clone() method ,as shown :
public class CloneMe {
int version;
Another another;
public CloneMe(int newVersion, Another obj) {
this.version = newVersion;
this.another = obj;
}
// and so on
#Override
protected Object clone() throws CloneNotSupportedException {
return super.clone(); // You can also provide your own implementation here
}
}
Now, when you create an object of class CloneMe :
CloneMe actualObject = new CloneMe(10, new Another());
Then an instance of class Another is created and is assigned to reference another in your CloneMe class.
Now, when you call :
CloneMe clonedObject = actualObject.clone();
Then only a new instance of CloneMe is created with existing state of the actualObject. However, no new instance of any other class (for example, Another in our case) is created but the same object reference is assigned to the reference variable in the clonedObject. This is called shallow cloning.

NullPointerException in while loop when trying to add new Class instances to ArrayList

The more I google this the more confused I'm getting.
I'm bringing in a list of names of unknown length with some other details in from a CSV which I then need to turn into Person objects and store in a list called people which is the instance variable for the class Club, a list of its members basically.
This is a very simplified version of something more complex I need to do in which I need to while loop through a file creating objects for each line which I then need to add to a list collection.
I keep getting a nullPointerException error when I run my code though and I'm stumped how to avoid it. I'm guessing that my variable p when I create the new object would need to change on each loop but I don't think it's possible to change variables dynamically is it?
Can't think how I can commit the object to the collection with a valid non null reference each time. Would be very grateful for any help. I've tried to cut out all the unnecessary stuff in the code below.
Thank you
//class arraylist instance variable of class "Club"
private ArrayList<Person> people;
//class constructor for Club
public Club()
{List<Person> people = new ArrayList<>();}
public void readInClubMembers()
{
//some variables concerning the file input
String currentLine;
String name;
String ageGroup;
while (bufferedScanner.hasNextLine())
{
//some lines bringing in the scanner input from the file
name = lineScanner.next();
ageGroup = "young";
Person p = new Person(); // i guess things are going wrong around here
people.add(p);
p.setName(name);
p.setAgeGroup(ageGroup);
}
}
Remove the List<Person> before people = … inside the constructor, otherwise you are declaring a new local variable people inside the constructor shadowing the field people (which is then never used). This leaves the class field uninitialized (null) and then causes the NPE.
What you want instead is initializing the field people:
public Club() {
// you can also use "this.people = …" to be explicit
people = new ArrayList<>();
}
To show the difference:
class Example {
private int myNumber;
public Example() {
myNumber = 42; // sets the field of the class
int myNumber = 1337; // declares a new local variable shadowing the class field
myNumber = -13; // accesses the object in the closest scope which is the local variable
this.myNumber = 0; // explicitly accesses the class field
}
}

How does Object Oriented Programming work?

I am not sure about some things in OOP.
If I have Class1, which has some private field, for example private Field field1, and make
getField1 () {
return field1;
}
then I have some class with constructor
public Class2 (Field field) {
someMethod(field);
}
And then I call constructor of Class2 in Class3 like:
Class2 cl = new Class2(instanceOfClass1.getField1());
And now the question: Am I working with field1 of instanceOfClass1 in someMethod(field)?
This depends on whether field is a value or a reference.
Value types are copied when passed as parameters. Reference types are not; the function is simply handed a "reference" that points back to the original value, and any changes that it makes are reflected in the original value.
Whether a given type is value or reference depends on your particular programming language. Generally speaking, basic integer and boolean types are usually value types, and everything else is up in the air -- some languages make strings values, and others treat them as references, etc.
Edit: Since you mentioned you're using Java, here's a short program that demonstrates value and reference types:
class ClassOne {
public int myInt;
}
class ClassTwo {
public int myInt;
public ClassTwo(ClassOne c)
{
myInt = c.myInt;
c.myInt = 3;
}
}
public class main
{
public static void main(String[] args)
{
ClassOne c = new ClassOne();
c.myInt = 1;
System.out.println("C1: " + c.myInt);
ClassTwo c2 = new ClassTwo(c);
System.out.println("C2: " + c2.myInt);
System.out.println("C1: " + c.myInt);
}
}
Running this program will give the output:
C1: 1
C2: 1
C1: 3
In this program, both ClassOne and ClassTwo contain an integer field -- a value type. ClassTwo takes a ClassOne parameter -- a reference type -- in its constructor, and sets its own integer field based on the value of the ClassOne object it is given, and then changes the ClassOne object's value.
Because classes are reference types, changing the ClassOne object in the ClassTwo constructor causes the original object to be changed. (In the main function here, that's c.) But because integers are value types, even though c2 changes the value of c.myInt in its constructor, because it sets its own value beforehand, c2.myInt isn't affected: it retains the original number, because it was copied rather than referenced.
Hopefully this helps clear things up a bit.
You're working with the value contained in it. If it is a mutable object then yes, it is possible to change the state of the instance of Class1 from outside, which violates data protection principles. This is why you should copy mutable types before returning them.
I had to reread your question two or three times to make sure I understood what you're asking.
To recap:
There is Class1 which contains an field attribute (of type Field?) which is sent back by it's getField1() method.
There is then Class2 which is apparently has a constructor that accepts an object parameter of Field type and contains a method that uses an instance of Field to trigger a local method in this class.
You then use a third class to instantiate Class2 and initialize it using an instance of Field using the getField1() method from an instance of Class1.
In the case of Java, providing you've done the necessary instantiation this would mean that the Field instance in Class1 is being used throughout the process. You can verify this using a System.out.println() (this will give you an # symbol with a series of weird numbers) or using the a.equals(b) method common to all objects.
Here is an interesting link about passing objects by value:
http://www.javaranch.com/campfire/StoryPassBy.jsp

Java object reference/scope question

If I have a member variable such as this (declared in the body of a class)
private Dot[] dots=new Dot[numDots];
I loop through all members of this array, and:
1) Pass every Dot object to a function of another class, which:
2) Passes it to yet another function of a 3rd class, if some conditions are met
3) And the 3rd class changes some properties of the Dot object
then when this object is returned to the original/parent class, would those changes to its properties have retained? Or would it be treated like a local variable by the 2nd/3rd functions?
Yes, the changes to the properties are retained. Java is 100% pass-by-value, however, when you pass an object, the "value" passed is truly a pointer to the object. Thus, when you change an object in a method, you're changing the actual object passed in.
That is, if you have the following method, then the calling method will see the changes:
private void updateMyDot(final Dot aDot) {
aDot.dotColor = new Color(255,255,255);
}
but if you do the following, then the calling method will not see the changes.
private void updateMyDot(/* not final */ Dot aDot) {
aDot = new Dot();
aDot.dotColor = new Color(255,255,255);
}
In the second example, the caller will not see any changes and will not see the newly created Dot object.
Objects are passed by [reference value where the value is the reference] (things that inherit from Object), primitive values (int, long, double, etc.) are passed by value.
This means that when a primitive is passed from a caller to method it is copied, whereas with an object a [value of the] reference is passed.
Which in turn means that when an object is mutated by a method the caller sees those changes because it has a reference to the same object.
Conversely when a method mutates a primitive the caller does not see the changes as the method is working on a copy.
[reason for the edits]
If Java had pass by reference then you could do this:
Object x;
x = new Integer(42);
foo(x);
System.out.println(x.getClass()); // pass by reference would have it print out java.lang.Float
where foo is defined as:
void foo(Object o)
{
o = new Float(43);
}
Since Java passes the reference by value o = new Float(43); is allowed - but the value in the caller will remain as the new Integer(42);

Categories