About Question enthuware.ocajp.i.v7.2.1392 :

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

Moderator: admin

scranen
Posts: 12
Joined: Thu May 07, 2015 8:55 am
Contact:

About Question enthuware.ocajp.i.v7.2.1392 :

Post by scranen »

I'd be very interested to know a bit more about the internals of the += operator here. The following does not compile (as I had expected):

Code: Select all

String s = null + 'g';
I was a bit surprised to find out that the following does compile:

Code: Select all

String s = null;
s += 'g';
Does anyone know what the thought was behind this decision? It seems inconsistent with the fact that the following throws a NullPointerException:

Code: Select all

Integer i = null;
i += 1;
A possible explanation would be that the + on strings add .toString() on both sides if the object passed is not actually a string, but the following also does not work (ClassCastException):

Code: Select all

String s = (String)(Object)new Integer(0);
s += 'g';

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

Re: About Question enthuware.ocajp.i.v7.2.1392 :

Post by admin »

You should check out Section 15.26.2 Compound Assignment Operators of JLS.

Also, + operator is overloaded by Java for the cases when at least one of the operands of + is a String. So null +'g' will not compile because neither of the operands is a String. s += 'g'; works because it translates to s = s + 'g'; which means one operand is a String.
If you like our products and services, please help us by posting your review here.

scranen
Posts: 12
Joined: Thu May 07, 2015 8:55 am
Contact:

Re: About Question enthuware.ocajp.i.v7.2.1392 :

Post by scranen »

Okay, so the result is due to the type checker selecting the string concatenation semantics for the + operator. JLS is (in my opinion) unclear about the behaviour of that operator, though:
If only one operand expression is of type String, then string conversion (§5.1.11) is performed on the other operand to produce a string at run time.
In this case, during type checking the compiler decides that one of the arguments is of type String. Runtime, however, s instanceof String does not hold. JLS does not say what happens in this situation, but apparently it does not only convert the other operand, but all operands not of type String.

rumapathi
Posts: 2
Joined: Tue May 05, 2015 12:30 pm
Contact:

Re: About Question enthuware.ocajp.i.v7.2.1392 :

Post by rumapathi »

Can you please clarify on the below statement?

"Had newStr been defined as String newStr = ""; then the program would have printed false for newStr == myStr because both the references are pointing to two different objects,"

In the question, it's not defined using the 'new' operator so the string reference should be pointing to the 'constant pool' to refer the value "good". In this case, both myStr and newStr are pointing to the same object present in contant pool. Hence, (newStr == myStr) should also be true. Right?

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

Re: About Question enthuware.ocajp.i.v7.2.1392 :

Post by admin »

scranen wrote:Okay, so the result is due to the type checker selecting the string concatenation semantics for the + operator. JLS is (in my opinion) unclear about the behaviour of that operator, though:
If only one operand expression is of type String, then string conversion (§5.1.11) is performed on the other operand to produce a string at run time.
In this case, during type checking the compiler decides that one of the arguments is of type String. Runtime, however, s instanceof String does not hold.
Why do you think so?
If you like our products and services, please help us by posting your review here.

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

Re: About Question enthuware.ocajp.i.v7.2.1392 :

Post by admin »

"new" operator is not the only way to NOT get the string object from the pool. + operator may also return a new string object if one of the operands is not effectively constant. For example,
String a = "g";
String ch = "g";
String b = ""+ch; //ch is not a constant
System.out.println(a == b); //prints false

Would suggest you to check the JLS for precise details. (Not required for the exam though.)
If you like our products and services, please help us by posting your review here.

scranen
Posts: 12
Joined: Thu May 07, 2015 8:55 am
Contact:

Re: About Question enthuware.ocajp.i.v7.2.1392 :

Post by scranen »

Why do you think so?
Take the following code:

Code: Select all

String s = null;
assert(!(s instanceof String));
s = s + 'c';
Here, the + operator is the string concatenation operator, because the type checker resolves the type of s as String (had s been declared as int, for instance, then + would have been interpreted as the numeric addition operator).

According to JLS, during runtime, this operator converts the other argument ('c') to a string, i.e., this code is equivalent to

Code: Select all

String s = null;
assert(!(s instanceof String));
s = s + 'c'.toString();
That however does not change the fact that s is still null. The JLS only says that + returns the concatenation of the two operand strings. In this case, s is not a string, so as far as I can tell, the JLS does not specify what to do in this instance. The implementation of x+y chosen by the compiler is apparently equivalent to add(x,y) in the following code:

Code: Select all

String add(String x, Object y)
{
  StringBuilder sb = new StringBuilder();
  sb.append(x);
  sb.append(y);
  return sb.toString();
}
Personally, I would have also found the following a perfectly acceptable implementation, given the JLS specification:

Code: Select all

String add(String x, Object y)
{
  StringBuilder sb = new StringBuilder(x);
  sb.append(y);
  return sb.toString();
}
This last implementation would throw a NullPointerException when x=null.

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

Re: About Question enthuware.ocajp.i.v7.2.1392 :

Post by admin »

I am sorry but I am really not sure what is your point. If JLS can't satisfy your doubt, I am not sure what will :(
If you like our products and services, please help us by posting your review here.

scranen
Posts: 12
Joined: Thu May 07, 2015 8:55 am
Contact:

Re: About Question enthuware.ocajp.i.v7.2.1392 :

Post by scranen »

I suppose my point is that the result of the expression s+o (for s a String and o an Object) is not properly defined by the JLS if s turns out to be a null reference at runtime. I'm therefore not sure it is reasonable that the question requires you to know what the result of this expression is -- it is not defined in the JLS, so the result of s+o might be compiler-specific.

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

Re: About Question enthuware.ocajp.i.v7.2.1392 :

Post by admin »

The types of the operands are determined at compile itself. Otherwise, the code wouldn't even compile. For example, the following will not compile even though the run time type of the object referred to by a is String:
Object a = "g";
char ch = 'g';
String b = a+ch;//won't compile.
If you like our products and services, please help us by posting your review here.

scranen
Posts: 12
Joined: Thu May 07, 2015 8:55 am
Contact:

Re: About Question enthuware.ocajp.i.v7.2.1392 :

Post by scranen »

Sure, but at runtime, if the left argument s of type String turns out to be null, then s instanceof String does not hold. For all intents and purposes, therefore, s is not a string at that point (regardless of what the type checker decided at compile time). So for the following code snippet,

Code: Select all

String s = null;
s = s + 'c';
the compiler decides at compile time that it is will be concatenating a character 'c' to a string s. Runtime, however, it has to decide how to deal with the fact that s is not a String (it is, in fact, null, which is of the (unnamed) null type). The Oracle Java compiler decides to convert s to the String object with value "null" to overcome this issue. The JLS however does not require that this conversion be done, it only says that 'c' should be converted to a String -- more to the point, it does not prescribe what the semantics of concatenating a null value and a string of characters is.

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

Re: About Question enthuware.ocajp.i.v7.2.1392 :

Post by admin »

OK, it looks like your whole argument is based on the fact that since the instanceof check returns false at runtime, it is not a String and so the operation is not defined by JLS.

My point is the symantics of instanceof clearly require that the left operand must not be null for it to return true. But null can actually be cast to any type. For example, the following runs fine even though a instanceof String (or even Object) is false:
Object a = null;
String s = (String) a;

This means a is-a String.

My question is, why do you insist on the result of instanceof test and not on the cast test?
If you like our products and services, please help us by posting your review here.

scranen
Posts: 12
Joined: Thu May 07, 2015 8:55 am
Contact:

Re: About Question enthuware.ocajp.i.v7.2.1392 :

Post by scranen »

I'm using the instanceof test to illustrate that it is not reasonable to say that null can semantically be seen as a string (note that I am using "string" (with lowercase s) to refer to the semantic notion of a string of characters; I do not argue that null cannot be argued to be of type String). I will rephrase my argument to not use this test.

Maybe my point becomes clearer if I explain how I interpret the JLS on string concatenation. Given that s+o is an expression in which the reference variable s is of type String, and the reference variable o is of type Object, the only thing we know about these variables is that during run time, they will contain a reference to a String and a reference to an Object. I completely agree with you that there is nothing wrong with the typing, even if s turns out to be a null reference, its type is still String.

If I now ask myself what the JLS says about the result of the expression, I have to interpret what "the concatenation of the two operand strings" means (this is what the JLS says is the return value). The only way in which I can interpret this is that it means in the case of s+o is "the concatenation of the two strings referenced by s and o". Two problems can occur:
  1. o references an object that is not a string. In that case, the expression o was not of type String, so this case is covered by the specification: it says to convert the object to a string first.
  2. o or s does not reference any object at all (i.e., is a null reference). In this case, the JLS does not say what happens, because we don't have two strings to concatenate. We have two expressions of type String, but semantically, at least one of them does not actually represent a string. The Java compiler decides in this case to interpret the null references as a reference to the string "null", but this is not prescribed by the JLS.

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

Re: About Question enthuware.ocajp.i.v7.2.1392 :

Post by admin »

OK, I got your point.
thank you for your patience :)
If you like our products and services, please help us by posting your review here.

scranen
Posts: 12
Joined: Thu May 07, 2015 8:55 am
Contact:

Re: About Question enthuware.ocajp.i.v7.2.1392 :

Post by scranen »

Haha np. It gets even more confusing because the conversion for o to "null" in case of a null reference may actually be quite reasonable, as "string conversion is performed" on o anyway. This depends on what "string conversion" means, and whether it is an operation on objects or on object references -- I don't think JLS says anything about this.

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

Re: About Question enthuware.ocajp.i.v7.2.1392 :

Post by admin »

JLS does describe string conversion in Section 5.1.11.
If you like our products and services, please help us by posting your review here.

scranen
Posts: 12
Joined: Thu May 07, 2015 8:55 am
Contact:

Re: About Question enthuware.ocajp.i.v7.2.1392 :

Post by scranen »

Oops :oops: Thanks for the reference.

pbonito
Posts: 13
Joined: Sat May 16, 2015 12:38 pm
Contact:

Re: About Question enthuware.ocajp.i.v7.2.1392 :

Post by pbonito »

I think it is strange that two variables so defined String a = null , String b ="null" can have similar behaviour in operations such concatenation and print, but totally and correctly different in others (trim ,concat ecc. ecc.)

It's just a rule or I can understand it someway.

Thanks

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

Re: About Question enthuware.ocajp.i.v7.2.1392 :

Post by admin »

null and "null" are two entirely different things. The output that you see with null is because it is treated differently by the print (and concatenation) method but nothing surprising about "null".
You just need to remember it.
If you like our products and services, please help us by posting your review here.

Agoosen
Posts: 2
Joined: Fri Jun 26, 2015 4:37 am
Contact:

Re: About Question enthuware.ocajp.i.v7.2.1392 :

Post by Agoosen »

The answer to the question, first line, reads:

Since newStr is null at the beginning, the first iteration of the loop assigns "nullg" to newStr.

In my opinion, the correct explanation is:

"The statement in the loop uses the '+' operator to concatenate two objects. The first object is a String, it therefore (by design) uses the valueOf() method of the String Class. The API for this method says that if it is called with a null reference (*which it is* in our case), the method returns the string "null". "

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

Re: About Question enthuware.ocajp.i.v7.2.1392 :

Post by admin »

Actually, the given explanation is correct but it skipped the details that you've mentioned. These details are covered in other questions.

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

Jokumo♫
Posts: 6
Joined: Wed Apr 20, 2016 9:56 am
Contact:

Re: About Question enthuware.ocajp.i.v7.2.1392 :

Post by Jokumo♫ »

admin wrote:Actually, the given explanation is correct but it skipped the details that you've mentioned. These details are covered in other questions.
The explanation indeed is correct somehow, but without the details of Agoosen it sounds like null == "null". In my opinion it would help a lot to include those details in the explanation.

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

Re: About Question enthuware.ocajp.i.v7.2.1392 :

Post by admin »

The details provided in the previous post by Agoosen are not correct. JLS Section 15.18.1 doesn't say anything about using valueOf. In fact, in section 15.1.11 mentions that toString() is used to convert a non-string operand to a String value.

So, if your String operand is null, the + operator treats it pretty much as "null". Thus, null + 'g' will be evaluated as "nullg" as given in the explanation.

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

Jokumo♫
Posts: 6
Joined: Wed Apr 20, 2016 9:56 am
Contact:

Re: About Question enthuware.ocajp.i.v7.2.1392 :

Post by Jokumo♫ »

damn, you're right (as always)

now I see it in JLS Section 5.1.11 about String converion
If the reference is null, it is converted to the string "null" (four ASCII characters n, u, l, l).
thanks a lot. Much easier to accept it that way

Chanandler
Posts: 1
Joined: Thu Aug 25, 2016 1:33 pm
Contact:

Re: About Question enthuware.ocajp.i.v7.2.1392 :

Post by Chanandler »

Did something go wrong here?

Look for correct/green answer and the explanation:
and true for newStr.equals(myStr)
Attachments
Zrzut ekranu 2016-08-25 o 20.34.12.png
Zrzut ekranu 2016-08-25 o 20.34.12.png (34.13 KiB) Viewed 11018 times

Post Reply

Who is online

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