This is the modified toString function within the Complex ADT class that i'm trying to implement (My doubt is only regarding this function so I havent included the private variables declared before and the other functions) :
class ComplexCart implements Complex{
public String toString(){
if(image == 0) return (real + "");
}
}
Why can't we write the following?
if(imag == 0) return(real);
Why do we need to add the additional "" ?
since the return type is String, and real is integer type. alternatively you can use real.toString()
Since real is int type where as toString() method expects String to return.So you need add "";
+ is String concatenation operator here.
public String toString(){
if(image == 0) return (real + "");
}
In the above code if real is not of type String it's compile time error.
if it is of type String.No errorrs occures.
To make real as string you are writing real + "".
Then , Immediate question is Then how it's working with + "" ??
Here the Docs of String
The Java language provides special support for the string concatenation operator ( + ), and for conversion of other objects to strings. String concatenation is implemented through the StringBuilder(or StringBuffer) class and its append method. String conversions are implemented through the method toString, defined by Object and inherited by all classes in Java.
As a side note:
concatenating with String is a bad idea.There are some identical and better ways to do it.
1)Integer.toString(intval);
2)String.valueOf(intval);
It's because you have to return a String from toString(), and presumably real is not a String. real + "" performs string concatenation (converting real to a String and concatenating it with the empty string; see JLS ยง15.18.1) and results in a String, which is why you can validly return it.
Note that you should consider using something like Integer.toString(real) over real + "" (see Integer.toString()).
Related
As you may know Object has some function,
For example we have toString() from oracle Documentacion we can know by default it's return HexValue of hashCode()
https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#toString()
We also can use hashCode() for checking of equality object (of course implementation depends on you)
So I made implementation for my Class Projekt :
public class Projekt {
int i;
public Projekt(int i) {
this.i=i;
// TODO Auto-generated constructor stub
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + i;
return result;
}
}
Test Code:
Projekt projekt = new Projekt(1);
System.out.println(projekt.toString());
System.out.println(projekt.toString() == projekt.toString());
Output:
Projekt#20
false
Also i try to inside value from projekt.toString() in StringPool by writing:
String string = projekt.toString();
String stringABC = projekt.toString();
System.out.println(string == stringABC);
According to PoolString i should have the same reference but outPrint is false.
So this method return different reference value but i can't understand why?
From your comment:
I copied this from diffrent comenatry: But to save memory we're using StringPool. If we have the same value, refereance is also the same it's working just for creating String not by constructor. If i had String s = new String("a"); String s2 = new String("a"); I used 2 space in memory, but when i use String s = "a"; String s2 = "a" I use 1 space in memory. So that's mean toString() return "new String()"?
Your source should have said:
...it's working just for creating String using string literals.
That way it might have been clearer, because there are many ways to create new String objects without directly calling the constructor. String literals are those things surrounded by " (including the quotes), such as "a" or "b" or "Welcome to Stack Overflow".
Only string literals1 are pooled automatically. You can manually put a string into the pool by calling intern().
When you concatenate two strings (e.g. stringA + stringB), a new string is generally created, as described here.
Now let's look at what Object.toString does:
The toString method for class Object returns a string consisting of
the name of the class of which the object is an instance, the at-sign
character `#', and the unsigned hexadecimal representation of the hash
code of the object. In other words, this method returns a string equal
to the value of:
getClass().getName() + '#' + Integer.toHexString(hashCode())
Note that strings are being concatenated here, so a new string object is being created here, hence the output.
And to answer the question of:
So that's mean toString() return "new String()"?
Yes, but not directly. The compiler will turn the + operators in Object.toString into some code using StringBuilder (or rather, "the compiler has turned..." since the Object class has already been compiled). At the end, it will call StringBuilder.toString, and that will create a new String object.
1Constant expressions of strings, to be more accurate.
This is because "toString()" method returns a string. So everytime you call toString() it returns a new reference because Strings are immutable (even if they're the same text)
String class is just a pointer to string (char) data somewhere in the memory. It is a class, it is not a primitive type like boolean, byte, char, short, int, long, float and double.
So, comparing two strings you compare pointers.
You generate two strings in:
String string = projekt.toString();
String stringABC = projekt.toString();
So you have 2 different pointers now. They have the same text inside, but they are in different places in memory.
But you can use equals() method of object:
System.out.println(string.equals(stringABC));
So I just perused for a while, all the different questions on here about .valueOf with strings, but they all seem to be about conversions. Comparing .valueOf to just + "".
I want to know if it is worth it or at all necessary to use .valueOf if it is a concatenation.
Example:
LOGGER.info("Final Score: " + String.valueOf(Math.round(finalScore * 100)) + "%");
VS
LOGGER.info("Final Score: " + Math.round(finalScore * 100) + "%");
It seems as though using String.valueOf is unnecessary if you have actual strings to go along with it. I understand it may be better to use .valueOf if you were just converting it and intended to use an empty string.
When we concatenate strings, the compiler actually translates it to StringBuffer.append().
The underlying implementations for StringBuffer.append(int) and String.valueOf(int) both eventually end up calling Integer.getChars(int,int,char[]) except that in case of String.valueOf(), there is a call to Integer.toString(int) first.
To conclude, for the given scenario, directly concatenating would be the way to go. But if you intend to be conscious about memory, then use string-builder to concatenate values first and then log it.
The source code for String#valueOf(Object) looks like this:
public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();
}
So the only difference between valueOf and toString is that valueOf is null-safe. So let's see which one is used if we concatenate a string and an object.
Object foo = null;
System.out.println("foo " + foo); //foo null, no exception thrown
System.out.println("foo " + String.valueOf(foo)); //foo null, no exception thrown
So it looks like there's no difference whatsoever between concatenation and using valueOf in this context.
you are correct. When you are combining strings and other datatypes, the valueOf is not necessary. For only an int, I think the valueOf works, but anecdotally, the 2nd example is a lot more common
#Test
public void testStringValueOF(){
int num = 123;
// this works...
String test = String.valueOf(num);
// but this is more common
String test2 = "" + num;
}
This question already has answers here:
Is a Java string really immutable?
(16 answers)
Closed 7 years ago.
Java string pool coupled with reflection can produce some unimaginable result in Java:
import java.lang.reflect.Field;
class MessingWithString {
public static void main (String[] args) {
String str = "Mario";
toLuigi(str);
System.out.println(str + " " + "Mario");
}
public static void toLuigi(String original) {
try {
Field stringValue = String.class.getDeclaredField("value");
stringValue.setAccessible(true);
stringValue.set(original, "Luigi".toCharArray());
} catch (Exception ex) {
// Ignore exceptions
}
}
}
Above code will print:
"Luigi Luigi"
What happened to Mario?
What happened to Mario ??
You changed it, basically. Yes, with reflection you can violate the immutability of strings... and due to string interning, that means any use of "Mario" (other than in a larger string constant expression, which would have been resolved at compile-time) will end up as "Luigi" in the rest of the program.
This kinds of thing is why reflection requires security permissions...
Note that the expression str + " " + "Mario" does not perform any compile-time concatenation, due to the left-associativity of +. It's effectively (str + " ") + "Mario", which is why you still see Luigi Luigi. If you change the code to:
System.out.println(str + (" " + "Mario"));
... then you'll see Luigi Mario as the compiler will have interned " Mario" to a different string to "Mario".
It was set to Luigi. Strings in Java are immutable; thus, the compiler can interpret all mentions of "Mario" as references to the same String constant pool item (roughly, "memory location"). You used reflection to change that item; so all "Mario" in your code are now as if you wrote "Luigi".
To explain the existing answers a bit more, let's take a look at your generated byte code (Only the main() method here).
Now, any changes to the content's of that location will affect both the references (And any other you give too).
String literals are stored in the string pool and their canonical value is used. Both "Mario" literals aren't just strings with the same value, they are the same object. Manipulating one of them (using reflection) will modify "both" of them, as they are just two references to the same object.
You just changed the String of String constant pool Mario to Luigi which was referenced by multiple Strings, so every referencing literal Mario is now Luigi.
Field stringValue = String.class.getDeclaredField("value");
You have fetched the char[] named value field from class String
stringValue.setAccessible(true);
Make it accessible.
stringValue.set(original, "Luigi".toCharArray());
You changed original String field to Luigi. But original is Mario the String literal and literal belongs to the String pool and all are interned. Which means all the literals which has same content refers to the same memory address.
String a = "Mario";//Created in String pool
String b = "Mario";//Refers to the same Mario of String pool
a == b//TRUE
//You changed 'a' to Luigi and 'b' don't know that
//'a' has been internally changed and
//'b' still refers to the same address.
Basically you have changed the Mario of String pool which got reflected in all the referencing fields. If you create String Object (i.e. new String("Mario")) instead of literal you will not face this behavior because than you will have two different Marios .
The other answers adequately explain what's going on. I just wanted to add the point that this only works if there is no security manager installed. When running code from the command line by default there is not, and you can do things like this. However in an environment where trusted code is mixed with untrusted code, such as an application server in a production environment or an applet sandbox in a browser, there would typically be a security manager present and you would not be allowed these kinds of shenanigans, so this is less of a terrible security hole as it seems.
Another related point: you can make use of the constant pool to improve the performance of string comparisons in some circumstances, by using the String.intern() method.
That method returns the instance of String with the same contents as the String on which it is invoked from the String constants pool, adding it it if is not yet present. In other words, after using intern(), all Strings with the same contents are guaranteed to be the same String instance as each other and as any String constants with those contents, meaning you can then use the equals operator (==) on them.
This is just an example which is not very useful on its own, but it illustrates the point:
class Key {
Key(String keyComponent) {
this.keyComponent = keyComponent.intern();
}
public boolean equals(Object o) {
// String comparison using the equals operator allowed due to the
// intern() in the constructor, which guarantees that all values
// of keyComponent with the same content will refer to the same
// instance of String:
return (o instanceof Key) && (keyComponent == ((Key) o).keyComponent);
}
public int hashCode() {
return keyComponent.hashCode();
}
boolean isSpecialCase() {
// String comparison using equals operator valid due to use of
// intern() in constructor, which guarantees that any keyComponent
// with the same contents as the SPECIAL_CASE constant will
// refer to the same instance of String:
return keyComponent == SPECIAL_CASE;
}
private final String keyComponent;
private static final String SPECIAL_CASE = "SpecialCase";
}
This little trick isn't worth designing your code around, but it is worth keeping in mind for the day when you notice a little more speed could be eked out of some bit of performance sensitive code by using the == operator on a string with judicious use of intern().
I there any utils method in Java that would enable me to surround a string with another string? Something like:
surround("hello","%");
which would return "%hello%"
I need just one method so the code would be nicer then adding prefix and suffix. Also I don't want to have a custom utils class if it's not necessary.
String.format can be used for this purpose:
String s = String.format("%%%s%%", "hello");
No but you can always create a method to do this:
public String surround(String str, String surroundingStr) {
StringBuffer buffer = new StringBuffer();
buffer.append(surroundingStr).append(str).append(surroundingStr);
return buffer.toString();
}
You have another method of doing it but Do not do this if you want better performance:-
public String surround(String str, String surroundingStr){
return surroundingStr + str + surroundingStr;
}
Why not use the second method?
As we all know, Strings in Java are immutable. When you concatinate strings thrice, it creates two new string objects apart from your original strings str and surroundingStr. And so a total of 4 string objects are created:
1. str
2. surroundingStr
3. surroundingStr + str
4. (surroundingStr + str) + surroundingStr
And creating of objects do take time. So for long run, the second method will downgrade your performance in terms of space and time. So it's your choice what method is to be used.
Though this is not the case after java 1.4
as concatinating strings with + operator uses StringBuffer in the background. So using the second method is not a problem if your Java version is 1.4 or above. But still, if you wanna concatinate strings is a loop, be careful.
My suggestion:
Either use StringBuffer of StringBuilder.
Not that i know of, but as already commented, its a single line piece of code that you could write yourself.
private String SurroundWord(String word, String surround){
return surround + word + surround;
}
Do note that this will return a New String object and not edit the original string.
Create a new method:
public String surround(String s, String surr){
return surr+s+surr;
}
Tested the following and returns %hello%
public static void main (String[] args) throws java.lang.Exception
{
System.out.println(surround("hello", "%"));
}
public static String surround(String s, String sign) {
return sign + s + sign;
}
StringUtils.wrap(str,wrapWith) is what you are looking for.
If apache common utils is already a part of dependency, then you can use it. Otherwise as others already mentioned. It's better to add to your base. Not a big deal
https://github.com/apache/commons-lang/blob/master/src/main/java/org/apache/commons/lang3/StringUtils.java
Here's where I wish Java's String class had a replaceLast method, bu it doesn't and I'm getting the wrong results with my code.
I'm writing a program that searches a data structure for any items that match a string prefix. However, since I'm using an Iterator, the last item returned by the iter.next() call doesn't match the pattern, so I want to change the search string so that the last character of the query is increased by one letter. My testing code is returning [C#b82368 with this code and An as titleSearch:
public String changeLastCharacter(String titleSearch) {
char[] temp= titleSearch.toCharArray();
char lastLetter= temp[temp.length-1];
lastLetter++;
temp[temp.length-1]= lastLetter;
String newTitleSearch= temp.toString();
return newTitleSearch;
}
First, what is the cause of the output from this code?
Second, is there a better way to execute my solution?
You want:
newTitleSearch = new String(temp);
The toString method is not overridden for arrays; it's the usual Object.toString, intended for debugging. The above actually creates a string of the characters. An alternative is:
int len = titleSearch.length();
String allButLast = titleSearch.substring(0, len - 1);
newTitleSearch = allButLast + new Character(titleSearch.charAt(len - 1) + 1);
Whenever you see unexpected output like ....#<hex-digits>, the chances are that you are accidentally using toString() on some object whose class inherits the default implementation from Object.
The default toString() method returns a String whose value consists of the type name for the object combined with the object's "identity hash code" as hex digits. In your case the [C part is the type name for a char[] object. The '[' means "array of" and the 'C' means the char primitive type.
The rules for forming the type names used in the default toString() method are fully documented in the javadocs for java.lang.Class.getName().
Your problem is temp.toString(). Try String newTitleSearch = new String(temp); instead.
I figured this out by System.out.println(temp[0]+","+temp[1]); after temp[1] add been assigned to the incremented value. You could do this even easier by using your IDE's debugger.
Since the array was being assigned properly, the problem had to be in the toString().