So I am given this piece of code and asked the question: What will be the result of compiling and executing Test class.
package com.foo.bar;
public class Test {
public static void main(String[] args) {
String str = "java";
StringBuilder sb = new StringBuilder("java");
System.out.println(str.equals(sb) + ":" + sb.equals(str));
}
}
The result according to them and the program when run through Eclipse is
false:false
I do not understand why it gives the above output. I thought String class overrides .equals so that it converts the values into strings and compares them. i.e. :
Object b, Object c ->
b.equals(c) ->
b.toString.equals(c.toString()) //b is a String
It is running the String.equals(). If you have str -> "java" and sb -> "java" which both override toString.
str.equals(sb) -> str.toString().equals(b.toString) -> true
No, String.equals does not convert the other argument to a String then compare the characters.
Compares this string to the specified object. The result is true if and only if the argument is not null and is a String object that represents the same sequence of characters as this object.
If the other object is not a String, e.g. a StringBuilder, then it will always return false. It will not convert the object to a String.
Like any well-formed equals method, it will test if the given object is the same class (ensuring it's not null first), and if it is, cast it to a String, but it won't call toString or otherwise convert the given object to a String.
Related
I have the following groovy code:
def script
String credentials_id
String repository_path
String relative_directory
String repository_url
CredentialsWrapper(script, credentials_id, repository_name, repository_group, relative_directory=null) {
this(script, credentials_id, 'git#gitlab.foo.com:' + repository_group +'/' + repository_name + '.git', relative_directory);
}
CredentialsWrapper(script, credentials_id, repository_url, relative_directory=null) {
this.script = script;
this.credentials_id = credentials_id;
this.repository_url = repository_url;
if (null == relative_directory) {
int lastSeparatorIndex = repository_url.lastIndexOf("/");
int indexOfExt = repository_url.indexOf(".git");
this.relative_directory = repository_url.substring(lastSeparatorIndex+1, indexOfExt);
}
}
Jenkins gives me the following:
Unable to compile class com.foo.CredentialsWrapper due to hash collision in constructors # line 30, column 7.
I do not understand why, the constructors are different, they do not have the same number of arguments.
Also, "script" is an instance from "WorkflowScript", but I do not know what I should import to access this class, which would allow me to declare script explicitly instead of using "def"
Any idea ?
When you call the Constructor with four parameters, would you like to call the first or the second one?
If you write an constructor/method with default values, groovy will actually generate two or more versions.
So
Test(String x, String y ="test")
will result in
Test(String x, String y) {...}
and
Test(String x) {new Test(x, "test")}
So your code would like to compile to 4 constructors, but it contains the constructor with the signature
CredentialsWrapper(def, def, def, def)
two times.
If I understand your code correctly, you can omit one or both of the =null. The result will be the same, but you will get only two or three signatures. Then you can choose between both versions by calling calling them with the right parameter count.
I have this code in Spock:
then:
1 * dao.getByValue(Something.ONE, _ as String) >> {Something smth, String value ->
return createSomething(smth).withValue(value).build()
}
It doesn't look exactly like that, but you get the point. I want to return an object based on arguments passed to the method, in the real version this object is loaded from database.
The point is that I have this call in a lot of places and it looks exactly the same everywhere. Could I somehow extract this closure and use it everywhere, like this:
then:
1 * dao.getByValue(Something.ONE, _ as String) >> Closures.makeSomething
I tried using Intellij extract feature, but it kinda went crazy there with types, after I edited the types manually I had weird errors:
public static final Closure<Optional<Something>> makeSomething = { Something smth, String value ->
return createSomething(smth).withValue(value).build()
}
...
1 * dao.getByValue(Something.ONE, _ as String) >> makeSomething
org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object 'mypackage.MySpec$__clinit__closure1#1757cd72' with class 'mypackage.MySpec$__clinit__closure1' to class 'java.util.Optional'
Even that one didn't work, and I thought it would:
public static final Closure<Optional<Something>> makeSomething = { Something smth, String value ->
return createSomething(smth).withValue(value).build()
}
...
1 * dao.getByValue(Something.ONE, _ as String) >> {args -> makeSomething.call(args[0], args[1]) }
groovy.lang.MissingMethodException: No signature of method: mypackage.MySpec$__clinit__closure2.call() is applicable for argument types: (java.util.Arrays$ArrayList) values: [[mypackage.Something$$Lambda$6/1105423942#6f45df59, ...]]
I'm not good at Groovy or Spock in general, I'm just trying this out for now.
Edit:
Working code after #tim_yates suggestion (whole interaction is in the helper method):
then:
interaction {
somethingCall(2, Something.TWO)
somethingCall(3, Something.ONE)
}
}
private void somethingCall(int times, Something something) {
times * dao.getByValue(something, _ as String) >> { Something smth, String value ->
return createSomething(smth).withValue(value).build()
}
}
Not working code that I'd like (only the return value is in the helper method):
then:
2 * dao.getByValue(Something.TWO, _ as String) >> makeSomething
3 * dao.getByValue(Something.ONE, _ as String) >> makeSomething
}
public static final Closure<Optional<Something>> makeSomething = { Something smth, String value ->
return createSomething(smth).withValue(value).build()
}
If I simply inline each >> makeSomething and write there it's body instead, then it works.
You have a conceptual problem here. You cannot just split the closure from the preceding code because if you look at it
dao.getByValue(something, _ as String) >> { Something smth, String value ->
return createSomething(smth).withValue(value).build()
}
you might notice that smth and value inside the closure get their values from getByValue(something, _ as String).
Now if you factor out the in-line closure part into a stand-alone closure instance, you lose that connection. First of all, >> makeSomething has no parameters, secondly you do not evaluate the makeSomething closure, i.e. on the right hand side you do not get your Optional instance but a Closure instance. In order to evaluate the closure you have to call it with parameters, i.e. something like >> makeSomething(something, "dummy") would work. But this way you have to repeat the first getByValue parameter and make up a dummy for the second, unspecified one because you have no easy way to refer to it other than introducing yet another closure like >> { Something smth, String value -> makeSomething(smth, value) }. But then you are not saving a lot of code.
It is your decision if this is nicer than somethingCall(2, Something.TWO) (I like it, actually) or if you go for my contrived construct. What I cannot do for you is change Groovy or Spock DSL syntax just because you prefer it to look different.
Some format issue when I'm trying to quote the code, so here is the picture :(
image description here
import akka.actor.{Actor, ActorSystem, Props}
case class Number(n: Int)
case class String(s: String)
class DoublingActor extends Actor {
def receive: Receive = {
case Number(n) => println(s"Result of doubling $n: ${n*2}")
case String(s) => println(s"Result of doubling $s: ${s}${s}")
}
}
object Double extends App {
val system = ActorSystem("DoublerSystme")
val doubler = system.actorOf(Props[DoublingActor], "doubler")
doubler ! Number(5)
doubler ! String("test")
}
The thing is, the actor works fine with number, but how can I add the matching function that returns the string twice?
You should avoid naming your case class as String, especially in your case, with String parameter type:
case class String(s: String)
It would confuse the compiler to expect a parameter type different from the actual String type you want. Your app will work if you explicitly specify java.lang.String as the parameter type:
case class String(s: java.lang.String)
In any case, I would not recommend naming a case class as String.
What behavior are you seeing? Due to your issue being wrapped in an image, I can't test for sure, but I'd expect that you are getting a compile error with the descriptive message object String is not a case class, nor does it have an unapply/unapplySeq member.
Because it doesn't have the unapply member, you'll need to modify your statement to
case s: String => println(s"Result of doubling $s: ${s}:${s}")
The following Kotlin code:
val x = null + null
results in x being of type String, which is correct as according to the docs for String.plus:
Concatenates this string with the string representation of the given [other] object. If either the receiver or the [other] object are null, they are represented as the string "null".
However, I don't understand why this happens - is it due to some special feature of the language?
Probably because String?.plus(Any?) is the only plus function which accepts a nullable type as a receiver in Kotlin library. Therefore, when you call null + null, the compiler will treat the first null as String?.
If you define an extension function where the receiver type is Int? and the return type is Int, then x will be inferred as Int.
public operator fun Int?.plus(other: Any?): Int = 1
val x = null + null
If you declare another similar function within the same file (nullable type as the receiver type), when you call null + null, it causes the compile time error: Overload resolution ambiguity. All these functions match..
public operator fun Int?.plus(other: Any?): Int = 1
public operator fun Float?.plus(other: Any?): Float = 1F
val x = null + null //compile time error
We need to start with the type of Nothing. This type has exactly zero possible values. It's a bottom type, and is a subtype of every other type (not to be confused with Any, which is a supertype of every other type). Nothing can be coerced to any type, so that you can do stuff like:
fun doStuff(a: Int): String =
TODO("this typechecks")
Moving on to the type of Nothing?, meaning Nothing or null. It has 0 + 1 possible values. So null has a type of Nothing?. Nothing? can be coerced to any nullable type, so that you can do stuff like:
var name: String? = null
Here null : Nothing? is coerced to String?.
For some reason, unfortunately, there's this function defined in stdlib:
operator fun String?.plus(other: Any?): String
that allows null + null leveraging those coercion rules I mentioned above
val x = null + null
Try to rephrase this as below and you will find you answer:
val x = null.plus(null)
The below is what IntelliJ shows as the signature of the plus method:
public operator fun String?.plus(other: Any?): String
So the first null is treated as String? type and then when you try to plus anything else, the above plus method is the only match you have. Printing out x will result in nullnull
I have the following code (note the code below doesnt update the property)
private void queryResultsFilePath_Click(object sender, EventArgs e)
{
Library.SProc.Browse browser = new Browse();
browser.selectFile(QueryResultFilePath);
}
and
public class Browse
{
public void selectFile(string propertyName)
{
...
propertyName = browserWindow.FileName;
}
}
Now i realise that i need to change the second method so that it returns a string and manually assign it to the property in the first example.
What im unsure of is that i thought that when i assigned a ref type as an actual parameter of a method, a copy of its value on the stack (ie its memory address in the heap) was copied to the new location on the stack for the methods formal parameter, so they are both pointing to the same memory address on the heap. So when i changed the value of the formal parameter, it would actually change the value stored on the heap and thus the actual parameters value.
Obviously im missing something since im having to return a string and manually assign it to the property. If someone could point out what ive misunderstood id appreciate it.
Thanks.
I believe the missing piece here is: strings are immutable.
Although you pass it by reference, as soon as anything attempts to mutate the string, a new string is created leaving the old one intact.
I believe it is the only reference type that has enforced immutability.
From MSDN:
Strings are immutable--the contents of a string object cannot be
changed after the object is created, although the syntax makes it
appear as if you can do this. For example, when you write this code,
the compiler actually creates a new string object to hold the new
sequence of characters, and that new object is assigned to b. The
string "h" is then eligible for garbage collection.
Further reading:
http://social.msdn.microsoft.com/Forums/en/netfxbcl/thread/e755cbcd-4b09-4a61-b31f-e46e48d1b2eb
If you wish the method to "change" the caller's string then you can simulate this using the ref keyword:
public void SelectFile(ref string propertyName)
{
propertyName = browserWindow.FileName;
}
In this example, the parameter propertyName will be assigned to in the method, because of ref being used, this also changes the string that the caller is pointing to. Note here that immutability is still enforced. propertyName used to point to string A, but after assignment now points to string B - the old string A is now unreferenced and will be garbage collected (but importantly still exists and wasn't changed - immutable). If the ref keyword wasn't used, the caller would still point at A and the method would point at B. However, because the ref keyword was used the callers variable now points to string B.
This is the same effect as the following example:
static void Main(string[] args)
{
MyClass classRef = new MyClass("A");
PointToANewClass(ref classRef);
// classRef now points to a brand new instance containing "B".
}
public static void PointToANewClass(ref MyClass classRef)
{
classRef = new MyClass("B");
}
If you try the above without the ref keyword, classRef would still point to an object containing "A" even though the class was passed by reference.
Don't get confused between string semantics and ref semantics. And also don't get confused between passing something by reference and assignment. Stuff is technically never passed by reference, the pointer to the object on the heap is passed by value - hence ref on a reference type has the behaviour specified above. Also hence not using ref will not allow a new assignment to be "shared" between caller and method, the method has received its own copy of the pointer to the object on the heap, dereferencing the pointer has the usual effect (looking at the same underlying object), but assigning to the pointer will not affect the callers copy of the pointer.
I'm really grateful to Adam Houldsworth, because I've finally understood how the .NET framework uses reference parameters and what happens with the string.
In .NET there are two kind of data types:
value type: primitive types like int, float, bool, and so on
reference type: all the other objects, including string
In the case of reference type, the object is stored in the heap, and a variable only holds a reference pointing to this object. You can access the object's properties through the reference and modify them. When you pass one of this variables as parameter, a copy of the reference pointing to the same object is passed on to the method body. So, when you access and modify properties, you are modifyin gthe same object stored on the heap. I.e, this class is a reference object:
public class ClassOne
{
public string Desc { get; set; }
}
When you do this
ClassOne one = new { Desc = "I'm a class one!" };
there's an object on the heap pointed to by the reference one. If you do this:
one.Desc = "Changed value!";
the object on the heap has been modified. If you pass this reference as a parameter:
public void ChangeOne(ClassOne one)
{
one.Desc = "Changed value!"
}
The original object on the heap is also changed, because one helds a copy of the original reference that points to the same object on the heap.
But if you do this:
public void ChangeOne(ClassOne one)
{
one = new ClassOne { Desc ="Changed value!" };
}
The original object is unchanged. That's because one was a copy of the reference that it's now pointing to a different object.
If you pass it explicitly by reference:
public void ChangeOne(ref ClassOne one)
{
one = new ClassOne { Desc ="Changed value!" };
}
one inside this method is not a copy of the outer refernce, but the reference itself, so, the original reference now points to this new object.
strings are inmutable. This means that you cannot change a string. if you try to do so, a new string is created. So, if you do this:
string s = "HELL";
s = s + "O";
The second line creates a new instance of string, with the value "HELLO" and "HELL" is abandoned on the heap (left to be garbage collected).
So it's not possible to change it if you pass it as a parameter like this:
public void AppendO(string one)
{
one = one + "O";
}
string original = "HELL";
AppendO(original);
the original string is left as is. The code inside the function creates a new object, and assign it to one, which is a copy of original reference. But original keeps pointing to "HELL".
In the case of value types, when they are passed as parameters to a function, they are passed by value, i.e. the function receives a copy of the original value. So, any modification done to the object inside the function body won't affect the original value outside the function.
The problem is that, although string is a reference type, it looks as if it behaves like a value type (this applies to comparisons, passing parameters, and so on).
However, as explained above, it's possible to make the compiler pass a reference type by reference using the ref keyword. This also also works for strings.
You can check this code, and you'll see that the string is modified (this would also apply to an int, float or any other value type):
public static class StringTest
{
public static void AppednO(ref string toModify)
{
toModify = toModify + "O";
}
}
// test:
string hell = "HELL";
StringTest.AppendO(ref hell);
if (hell == "HELLO")
{
// here, hell is "HELLO"
}
Note that, for avoiding errors, when you define a parameter as ref, you also have to pass the parameter with this modifier.
Anyway, for this case (and similar cases) I'd recommend you to use the more natural functional syntax:
var hell = StringTest.AppendO(hell);
(Of course, in this case, the function will have this signature and corresponding implementation:
public static string AppendO(string value)
{
return value + "O";
}
If you're going to make many changes to a string, you should use the StringBuilder class, which works with "mutable strings".
How a property, of type string, is passed
Strings are immutable and therefore you are passing copies of them to methods. This means that the copy changes but the original parameter stays the same.