About Question enthuware.ocpjp.v8.2.1795 :

Help and support on OCA OCP Java Programmer Certification Questions
1Z0-808, 1Z0-809, 1Z0-815, 1Z0-816, 1Z0-817

Moderator: admin

Post Reply
Tariee
Posts: 5
Joined: Wed Sep 02, 2015 7:21 pm
Contact:

About Question enthuware.ocpjp.v8.2.1795 :

Post by Tariee »

Hello :D

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?

admin
Site Admin
Posts: 10036
Joined: Fri Sep 10, 2010 9:26 pm
Contact:

Re: About Question enthuware.ocpjp.v8.2.1795 :

Post by admin »

No, final is required because otherwise it is possible to modify private fields using reflection.

HTH,
Paul.
If you like our products and services, please help us by posting your review here.

Tariee
Posts: 5
Joined: Wed Sep 02, 2015 7:21 pm
Contact:

Re: About Question enthuware.ocpjp.v8.2.1795 :

Post by Tariee »

Alright, thank you Paul

mrmuiz
Posts: 49
Joined: Mon Jul 27, 2015 4:34 am
Contact:

Re: About Question enthuware.ocpjp.v8.2.1795 :

Post by mrmuiz »

Another possible answer is that you could use another object of the same class to modify private fields:

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);
	}

}
Here a1 is modifying a2's private member x

javabean68
Posts: 31
Joined: Wed Mar 16, 2016 8:38 am
Contact:

Re: About Question enthuware.ocpjp.v8.2.1795 :

Post by javabean68 »

Hi all,

when the Constructor is private the class is 'effectively' final :ugeek: . As a consequence the keyword 'final' isn't really needed...Can it be?

Thank you for your help,

Greetings
Fabio

admin
Site Admin
Posts: 10036
Joined: Fri Sep 10, 2010 9:26 pm
Contact:

Re: About Question enthuware.ocpjp.v8.2.1795 :

Post by admin »

javabean68 wrote:Hi all,

when the Constructor is private the class is 'effectively' final :ugeek: . As a consequence the keyword 'final' isn't really needed...Can it be?

Thank you for your help,

Greetings
Fabio
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."
-Paul.
If you like our products and services, please help us by posting your review here.

javabean68
Posts: 31
Joined: Wed Mar 16, 2016 8:38 am
Contact:

Re: About Question enthuware.ocpjp.v8.2.1795 :

Post by javabean68 »

Thank you Paul

Bye, Fabio

schchen2000
Posts: 106
Joined: Mon Mar 28, 2016 11:36 pm
Contact:

Re: About Question enthuware.ocpjp.v8.2.1795 :

Post by schchen2000 »

Make constructor private.
Isn't this answer option in the quote an equally good answer? Thanks.

Schmichael

admin
Site Admin
Posts: 10036
Joined: Fri Sep 10, 2010 9:26 pm
Contact:

Re: About Question enthuware.ocpjp.v8.2.1795 :

Post by admin »

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.
If you like our products and services, please help us by posting your review here.

schchen2000
Posts: 106
Joined: Mon Mar 28, 2016 11:36 pm
Contact:

Re: About Question enthuware.ocpjp.v8.2.1795 :

Post by schchen2000 »

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.
Argh.... I see. Thank you.

Schmichael

schchen2000
Posts: 106
Joined: Mon Mar 28, 2016 11:36 pm
Contact:

Re: About Question enthuware.ocpjp.v8.2.1795 :

Post by schchen2000 »

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.
Hi,

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.
If the instance fields include references to mutable objects, don't allow those objects to be changed:
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?
Don't provide methods that modify the mutable objects.
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.

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
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.
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.

I understand this is a lot to discuss but please help me understand the concepts. Many thanks.

Schmichael

schchen2000
Posts: 106
Joined: Mon Mar 28, 2016 11:36 pm
Contact:

Re: About Question enthuware.ocpjp.v8.2.1795 :

Post by schchen2000 »

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");

	}

}
Yes, we cannot change the value that is DIRECTLY inside an external mutable object (*) but what's the point all the copied values, which can then still be changed as shown in this code?

(*) 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.

admin
Site Admin
Posts: 10036
Joined: Fri Sep 10, 2010 9:26 pm
Contact:

Re: About Question enthuware.ocpjp.v8.2.1795 :

Post by admin »

schchen2000 wrote:I understand this is a lot to discuss but please help me understand the concepts. Many thanks.

Schmichael
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.
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.
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.

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.

schchen2000
Posts: 106
Joined: Mon Mar 28, 2016 11:36 pm
Contact:

Re: About Question enthuware.ocpjp.v8.2.1795 :

Post by schchen2000 »

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?
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?

Thanks.

Schmichael

admin
Site Admin
Posts: 10036
Joined: Fri Sep 10, 2010 9:26 pm
Contact:

Re: About Question enthuware.ocpjp.v8.2.1795 :

Post by admin »

schchen2000 wrote:
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?
That's right. The object of class immutableClassTest has become mutable in the end. That's what I meant;
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.
It is like saying, "This suitcase is not safe because I can open it as I have the key!"
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
Yes.
If you like our products and services, please help us by posting your review here.

schchen2000
Posts: 106
Joined: Mon Mar 28, 2016 11:36 pm
Contact:

Re: About Question enthuware.ocpjp.v8.2.1795 :

Post by schchen2000 »

Thank you so much for your help. I get it now. Thank you.

Schmichael

ssszzz
Posts: 13
Joined: Wed Jun 14, 2017 1:56 pm
Contact:

Re: About Question enthuware.ocpjp.v8.2.1795 :

Post by ssszzz »

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. - Is it not obvious? otherwise we can not instantiate this object (if not take into account reflection and some other unobvious ways)

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.

__JJ__
Posts: 125
Joined: Thu Jul 05, 2018 6:44 pm
Contact:

Re: About Question enthuware.ocpjp.v8.2.1795 :

Post by __JJ__ »

admin wrote:
Sat Jun 18, 2016 10:56 am
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.
Hi admin,
Sorry to be picky, but you say
Making constructor private is not the only thing required
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.
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.

admin
Site Admin
Posts: 10036
Joined: Fri Sep 10, 2010 9:26 pm
Contact:

Re: About Question enthuware.ocpjp.v8.2.1795 :

Post by admin »

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.

Javatje
Posts: 9
Joined: Wed Jun 30, 2021 6:53 am
Contact:

Re: About Question enthuware.ocpjp.v8.2.1795 :

Post by Javatje »

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?

admin
Site Admin
Posts: 10036
Joined: Fri Sep 10, 2010 9:26 pm
Contact:

Re: About Question enthuware.ocpjp.v8.2.1795 :

Post by admin »

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 like our products and services, please help us by posting your review here.

Post Reply

Who is online

Users browsing this forum: Google [Bot] and 43 guests