About Question enthuware.ocpjp.v8.2.1795 :
Moderator: admin
-
- Posts: 5
- Joined: Wed Sep 02, 2015 7:21 pm
- Contact:
About Question enthuware.ocpjp.v8.2.1795 :
Hello
I thought all one had to do to make an object immutable is make its fields private, provide public getters and not provide any setters or make the class final. In this question it says make all fields private and final, my question is why make the fields final as well? Isn't it enough that they are private and can only be modified by the owning class?
I thought all one had to do to make an object immutable is make its fields private, provide public getters and not provide any setters or make the class final. In this question it says make all fields private and final, my question is why make the fields final as well? Isn't it enough that they are private and can only be modified by the owning class?
Online
-
- Site Admin
- Posts: 10061
- Joined: Fri Sep 10, 2010 9:26 pm
- Contact:
Re: About Question enthuware.ocpjp.v8.2.1795 :
No, final is required because otherwise it is possible to modify private fields using reflection.
HTH,
Paul.
HTH,
Paul.
If you like our products and services, please help us by posting your review here.
-
- Posts: 5
- Joined: Wed Sep 02, 2015 7:21 pm
- Contact:
Re: About Question enthuware.ocpjp.v8.2.1795 :
Alright, thank you Paul
-
- Posts: 49
- Joined: Mon Jul 27, 2015 4:34 am
- Contact:
Re: About Question enthuware.ocpjp.v8.2.1795 :
Another possible answer is that you could use another object of the same class to modify private fields:
Here a1 is modifying a2's private member x
Code: Select all
public class Main {
public static void main(String[] args) {
class A{
private int x=10;
void foo(A a){a.x++;}
int getX(){return x;}
}
A a1=new A();
A a2=new A();
a1.foo(a2);
}
}
-
- Posts: 31
- Joined: Wed Mar 16, 2016 8:38 am
- Contact:
Re: About Question enthuware.ocpjp.v8.2.1795 :
Hi all,
when the Constructor is private the class is 'effectively' final . As a consequence the keyword 'final' isn't really needed...Can it be?
Thank you for your help,
Greetings
Fabio
when the Constructor is private the class is 'effectively' final . As a consequence the keyword 'final' isn't really needed...Can it be?
Thank you for your help,
Greetings
Fabio
Online
-Paul.
-
- Site Admin
- Posts: 10061
- Joined: Fri Sep 10, 2010 9:26 pm
- Contact:
Re: About Question enthuware.ocpjp.v8.2.1795 :
Yes, the explanation notes this point, "Don't allow subclasses to override methods. The simplest way to do this is to declare the class as final. A more sophisticated approach is to make the constructor private and construct instances in factory methods."javabean68 wrote:Hi all,
when the Constructor is private the class is 'effectively' final . As a consequence the keyword 'final' isn't really needed...Can it be?
Thank you for your help,
Greetings
Fabio
-Paul.
If you like our products and services, please help us by posting your review here.
-
- Posts: 31
- Joined: Wed Mar 16, 2016 8:38 am
- Contact:
Re: About Question enthuware.ocpjp.v8.2.1795 :
Thank you Paul
Bye, Fabio
Bye, Fabio
-
- Posts: 106
- Joined: Mon Mar 28, 2016 11:36 pm
- Contact:
Re: About Question enthuware.ocpjp.v8.2.1795 :
Isn't this answer option in the quote an equally good answer? Thanks.Make constructor private.
Schmichael
Online
-
- Site Admin
- Posts: 10061
- Joined: Fri Sep 10, 2010 9:26 pm
- Contact:
Re: About Question enthuware.ocpjp.v8.2.1795 :
Making constructor private is not the only thing required. As per Oracle's documentation noted in the explanation, "A more sophisticated approach is to make the constructor private and construct instances in factory methods.".
The option doesn't mention the second part.
The option doesn't mention the second part.
If you like our products and services, please help us by posting your review here.
-
- Posts: 106
- Joined: Mon Mar 28, 2016 11:36 pm
- Contact:
Re: About Question enthuware.ocpjp.v8.2.1795 :
Argh.... I see. Thank you.admin wrote:Making constructor private is not the only thing required. As per Oracle's documentation noted in the explanation, "A more sophisticated approach is to make the constructor private and construct instances in factory methods.".
The option doesn't mention the second part.
Schmichael
-
- Posts: 106
- Joined: Mon Mar 28, 2016 11:36 pm
- Contact:
Re: About Question enthuware.ocpjp.v8.2.1795 :
Hi,4. If the instance fields include references to mutable objects, don't allow those objects to be changed:
Don't provide methods that modify the mutable objects.
Don't share references to the mutable objects. Never store references to external, mutable objects passed to the constructor; if necessary, create copies, and store references to the copies. Similarly, create copies of your internal mutable objects when necessary to avoid returning the originals in your methods.
I've questions that are based on the quote above. I'd break the quote to make asking individual questions simpler. My understand is that the entire quote below is a part of the solution on how to make a class immutable while it has some association with (external) mutable objects.
don't allow those objects to be changed?If the instance fields include references to mutable objects, don't allow those objects to be changed:
What if we only have access to those external mutable objects and we lack power to make those objects immutable? Is the following one of the solutions to that situation?
As far as this is concerned, we just need to make OUR class (*) not provide a method that delegates the responsibility of changing the value(s) of a mutable object via the setter method of the class, from which the mutable object is instantiated.Don't provide methods that modify the mutable objects.
Why did I say that?
We are simply using a mutable object and therefore we can't possibly get rid of the potential setter method that may exist in the class, from which the mutable object is instantiated.
(*) OUR class = the class we are tasked to make immutable
With the quote immediately above, I sort of get what you are trying to do but then I suppose, I'm not fully getting what you are suggesting. I hope you could help me understand this. For the ideas you suggested in the quote immediately above, I've written the working code (The code in the following post due to 3000-char limit here) to implement the idea you suggested.Don't share references to the mutable objects. Never store references to external, mutable objects passed to the constructor; if necessary, create copies, and store references to the copies. Similarly, create copies of your internal mutable objects when necessary to avoid returning the originals in your methods.
I understand this is a lot to discuss but please help me understand the concepts. Many thanks.
Schmichael
-
- Posts: 106
- Joined: Mon Mar 28, 2016 11:36 pm
- Contact:
Re: About Question enthuware.ocpjp.v8.2.1795 :
Code: Select all
class MutableClass{
int mtbl_int;
MutableClass(int input){
mtbl_int = input;
}
void setter(int new_value){
mtbl_int = new_value;
}
}
public class ImmutableClassTest{
private final MutableClass ptr;
private ImmutableClassTest(MutableClass mtbl_obj){
ptr = new MutableClass(mtbl_obj.mtbl_int);
System.out.println("Mutable object from the ImmutableClassTest constructor: " + ptr);
}
public MutableClass getter(){
return new MutableClass(ptr.mtbl_int);
}
public static void main(String... args){
MutableClass var = new MutableClass(555);
System.out.println("\nMutableClass object from main: " + var + "\n");
ImmutableClassTest temp = new ImmutableClassTest(var);
System.out.println("\ntemp Before\n***********\n" + temp.ptr.mtbl_int + "\n");
ImmutableClassTest trying_to_change = temp;
trying_to_change.ptr.mtbl_int = 777;
System.out.println("temp After\n**********\n" + temp.ptr.mtbl_int + "\n");
System.out.println("trying_to_change\n****************\n" + trying_to_change.ptr.mtbl_int + "\n");
}
}
(*) We have 2 different mutable objects, one in main and one copied version in the constructor and you can see that they are indeed 2 different objects due to their different hash values shown in the program output.
Online
I looked at your code but I am not sure I understand your question. Are you saying that since you are able to change the value using trying_to_change.ptr.mtbl_int = 777; your object of class ImmutableClassTest is not immutable? If so, then that is ok because that code is part of ImmutableClassTest itself. You can decide whether you want to change the value or not in your class. What is important is whether other classes are able to modify the values inside an immutable class without your permission or knowledge.
-
- Site Admin
- Posts: 10061
- Joined: Fri Sep 10, 2010 9:26 pm
- Contact:
Re: About Question enthuware.ocpjp.v8.2.1795 :
I think you are making it more complicated that it really is. All you want is for the values inside an object to not change. What can you do to prevent anyone from changing the values inside that object? Choke off all ways through which such values can be changed, of course.schchen2000 wrote:I understand this is a lot to discuss but please help me understand the concepts. Many thanks.
Schmichael
If your class has contains reference to another mutable class then, if you follow both the above directions (not just one), you can make your class immutable.4. If the instance fields include references to mutable objects, don't allow those objects to be changed:
Don't provide methods that modify the mutable objects.
Don't share references to the mutable objects. Never store references to external, mutable objects passed to the constructor; if necessary, create copies, and store references to the copies. Similarly, create copies of your internal mutable objects when necessary to avoid returning the originals in your methods.
I looked at your code but I am not sure I understand your question. Are you saying that since you are able to change the value using trying_to_change.ptr.mtbl_int = 777; your object of class ImmutableClassTest is not immutable? If so, then that is ok because that code is part of ImmutableClassTest itself. You can decide whether you want to change the value or not in your class. What is important is whether other classes are able to modify the values inside an immutable class without your permission or knowledge.
If you like our products and services, please help us by posting your review here.
-
- Posts: 106
- Joined: Mon Mar 28, 2016 11:36 pm
- Contact:
Re: About Question enthuware.ocpjp.v8.2.1795 :
That's right. The object of class immutableClassTest has become mutable in the end. That's what I meant; however, the value inside the original mutable object (i.e. the one instantiated inside main in my provided code) did not get changed when the program finally stops. Does that mean I get my mission accomplished, i.e. not allowing to change a value inside a mutable object?Are you saying that since you are able to change the value using trying_to_change.ptr.mtbl_int = 777; your object of class ImmutableClassTest is not immutable?
Thanks.
Schmichael
Online
It is like saying, "This suitcase is not safe because I can open it as I have the key!"
-
- Site Admin
- Posts: 10061
- Joined: Fri Sep 10, 2010 9:26 pm
- Contact:
Re: About Question enthuware.ocpjp.v8.2.1795 :
That is not entirely correct. The concept of mutability applies to mutation by others. The point is that other classes should not be able to change the state of an object of the class that promises that it is immutable. If the class itself changes the value from inside then that is something else entirely.schchen2000 wrote:That's right. The object of class immutableClassTest has become mutable in the end. That's what I meant;Are you saying that since you are able to change the value using trying_to_change.ptr.mtbl_int = 777; your object of class ImmutableClassTest is not immutable?
It is like saying, "This suitcase is not safe because I can open it as I have the key!"
Yes.however, the value inside the original mutable object (i.e. the one instantiated inside main in my provided code) did not get changed when the program finally stops. Does that mean I get my mission accomplished, i.e. not allowing to change a value inside a mutable object?
Thanks.
Schmichael
If you like our products and services, please help us by posting your review here.
-
- Posts: 106
- Joined: Mon Mar 28, 2016 11:36 pm
- Contact:
Re: About Question enthuware.ocpjp.v8.2.1795 :
Thank you so much for your help. I get it now. Thank you.
Schmichael
Schmichael
-
- Posts: 13
- Joined: Wed Jun 14, 2017 1:56 pm
- Contact:
Re: About Question enthuware.ocpjp.v8.2.1795 :
The option doesn't mention the second part. - Is it not obvious? otherwise we can not instantiate this object (if not take into account reflection and some other unobvious ways)Making constructor private is not the only thing required. As per Oracle's documentation noted in the explanation, "A more sophisticated approach is to make the constructor private and construct instances in factory methods.".
The option doesn't mention the second part.
So why option 'Make constructor private' is wrong, but option 'Instead of a default no-args constructor, create a constructor that initializes the members' is correct?
It is not the only thing required as well. Moreover, almost all mutable classes which have constructors initialize their members inside that constructors
But option 'Make the class final' is correct.
Is not this a synonym of private constructors in case there are no any inner classes? In both cases we can't inherit such classes.
-
- Posts: 125
- Joined: Thu Jul 05, 2018 6:44 pm
- Contact:
Re: About Question enthuware.ocpjp.v8.2.1795 :
Hi admin,admin wrote: ↑Sat Jun 18, 2016 10:56 amMaking constructor private is not the only thing required. As per Oracle's documentation noted in the explanation, "A more sophisticated approach is to make the constructor private and construct instances in factory methods.".
The option doesn't mention the second part.
Sorry to be picky, but you say
Well yes this is true but none of the answers is the only thing required. Every answer identified as correct is not a solution in and of itself. It is one thing of many that needs to be done or can be done (which is what the question asks) in order to make a class immutable. So it is inconsistent of you to say that one answer is incorrect because it is not a complete solution in and of itself.Making constructor private is not the only thing required
As has been stated, Oracle themselves say that "A more sophisticated approach is to make the constructor private".
So certainly, you can make a constructor private, that's something you can do. The question isn't asking which of the below, independently, will make a class immutable. Because then, none of the answers would be correct.
Online
-
- Site Admin
- Posts: 10061
- Joined: Fri Sep 10, 2010 9:26 pm
- Contact:
Re: About Question enthuware.ocpjp.v8.2.1795 :
Making a constructor private is not "required" for making a class immutable.
If you like our products and services, please help us by posting your review here.
-
- Posts: 9
- Joined: Wed Jun 30, 2021 6:53 am
- Contact:
Re: About Question enthuware.ocpjp.v8.2.1795 :
Why is the option "Instead of a default no-args constructor, create a constructor that initializes the members." correct?
This way the code that calls the "constructor that initializes the members" might have references to the objects to which the members refer. Therefore, it seems that the members become mutable. What am I missing?
This way the code that calls the "constructor that initializes the members" might have references to the objects to which the members refer. Therefore, it seems that the members become mutable. What am I missing?
Online
-
- Site Admin
- Posts: 10061
- Joined: Fri Sep 10, 2010 9:26 pm
- Contact:
Re: About Question enthuware.ocpjp.v8.2.1795 :
Observe the first point in the explanation, "Don't provide "setter" methods — methods that modify fields or objects referred to by fields.".
If you provide a default no args constructor, you will have to provide setter methods to initialize the instance members. Setter methods will mutate the object after it is constructed. So, that is definitely incorrect.
There is no difference between passing mutable members to a constructor or setter methods. Both have the same issue if you pass them mutable arguments. But it is the constructor's job to accept the arguments, make a copy of them, and assign the copy to the instance members.
If you provide a default no args constructor, you will have to provide setter methods to initialize the instance members. Setter methods will mutate the object after it is constructed. So, that is definitely incorrect.
There is no difference between passing mutable members to a constructor or setter methods. Both have the same issue if you pass them mutable arguments. But it is the constructor's job to accept the arguments, make a copy of them, and assign the copy to the instance members.
If you like our products and services, please help us by posting your review here.