How is this legal
System.out.println("".valueOf(1121997));
And this is illegal
System.out.println(1.valueOf("1121997"));
"" is a string literal, and the java compiler makes sure that a String object will be automatically created for each string literal that you use in your program. So, since "" is an object, it has methods like valueOf().
On the other hand, 1 is an int literal, so there is no object created for it; it is just a primitive. Primitives do not have methods in java.
Because "" is a String. String Class has a valueOf method, so you can call it.
For your old question,
System.out.println( 1.valueOf("1121997"));
Here 1 is primitive integer value and not Integer Wrapper class. You can not call method on primitive data types.
For your updated Question,
System.out.println((Integer) 1.valueOf("1121997"));
Here you need to wrap (Integer)1 with additional ().
System.out.println(((Integer) 1).valueOf("1121997"));
Also valueOf() is a static method. It is not a good practice to call it with instance. You should call it directly with class name like
Integer.valueOf("1121997");
"" is a reference to a String Object, therefore has methods like length, valueOf, etc.
1 is an integer literal. It is a primitive data type, therefore you can't call methods on it.
Related
According to Oracle Documentation, the String::compareToIgnoreCase is also a valid method reference, my question is that compareToIgnoreCase is not a static method, in other words, compareToIgnoreCase must be attached to a specific String instance. So how does JDK know which instance of String I refer when I use String::compareToIgnoreCase ?
Consider the following example using toUpperCase which is also an instance method.
It works in this case because the Stream item that is being handled is of the same type as the class of the method being invoked. So the item actually invokes the method directly.
So for
Stream.of("abcde").map(String::toUpperCase).forEach(System.out::println);
the String::toUpperCase call will be the same as "abcde".toUpperCase()
If you did something like this:
Stream.of("abcde").map(OtherClass::toUpperCase).forEach(System.out::println);
"abcde" is not a type of OtherClass so the OtherClass would need to look like the following for the stream to work.
class OtherClass {
public static String toUpperCase(String s) {
return s.toUpperCase();
}
}
String::compareToIgnoreCase is not used such as str1.compareToIgnoreCase(str2) would be.
It actually is used as a comparator.
E.g. you could compare it to
Arrays.sort(someIntegerArray, Collections.reverseOrder())
but in this case it would be
Arrays.sort(someStringArray, String::compareToIgnoreCase)
It is like there is an additional parameter, the actual instance, involved.
Example for String::compareToIgnoreCase:
ToIntBiFunction<String, String> func = String::compareToIgnoreCase;
int result = func.applyAsInt("ab", "cd"); // some negative number expected
We get a ToIntBiFunction - a two parameter function returning int - since the result is an int, the first parameter correspond to this of compareToIgnoreCase and the second function parameter is the parameter passed to compareToIgnoreCase.
maybe a bit easier:
ToIntFunction<String> f = String::length; // function accepting String, returning int
int length = f.applyAsInt("abc"); // 3
length does not accept any parameter, but the first argument of the function is used as the instance length is called on
The examples above are very abstract, just to show the types involved. The functions are mostly used directly in some method call, no need to use an intermediate variable
for example in Scanner we have
obj.next()
but we can call another method after next()
obj.next().charAt(0)
how can I make similar thing for example
obj.getName().toLowerCase()
What you have observed – with examples like obj.getName().toLowerCase() – is that when the return type of a method call is itself some other object, then you can immediately call a new method on that newly returned object.
Here's another example: String s = String.class.getName().toLowerCase();. This example could be rewritten like so:
Class<String> stringClass = String.class;
String name = stringClass.getName();
String s = name.toLowerCase();
Both of the one-line and multi-line version of this code result in a String object, referenced by s, which contains the value "java.lang.string".
Note that chaining method calls together is not possible if the return type isn't an object, such as an integer value. For example, here's a method call that results in a primitive long value, which isn't an object, so you can't call any methods on that result – that is, something like millis.hashCode() isn't possible.
long millis = System.currentTimeMillis();
To address your primary question finally: you can create this same behavior by creating methods that return objects instead of primitives (int, long, byte, etc.).
I know java is pass by value, period. However, I still can't figure out this.
public static void changeTheName(String obj){
obj.toUpperCase();
}
This method will not affect the original string object, Fairly understandable. Because strings are immutable and changing in string literals means that the reference variable will now refer to the new object and the old one will be left for the garbage collector. But when I pass a string array I'm able to change the string literals that means I'm able to change the references. Why is this happening with the array because if we do obj[]= new String[]{} it will not affect to the original array and the original still refers to the old array and that is similar to directly changing the string literals
public static void ChangeTheName(String obj[]){
for(int i=0;i<obj.length();i++) obj[i]=obj[i].toUpperCase;
}
Edit:
The answer I was looking for is that reference of obj and obj[0] are unique and that's why the second method is able to change the entire content of my array. As I'm from C background and I thought obj and obj[0] has same refernces but that is not the case in java for sure.
toUpperCase does not change the String, it returns a new String which is uppercase.
#karthikdivi said - toUpperCase() does not change the String. it returns a new String which is uppercase.
But as i understand that you want to know why object value is changed in method but not premitive data type value?
Although Java is strictly pass by value, the precise effect differs between whether a primitive type or a reference type is passed.
.
When we pass a primitive type to a method, it is passed by value. But when we pass an object to a method, the situation changes dramatically, because objects are passed by what is effectively call-by-reference. Java does this interesting thing that’s sort of a hybrid between pass-by-value and pass-by-reference. Basically, a parameter cannot be changed by the function, but the function can ask the parameter to change itself via calling some method within it.
While creating a variable of a class type, we only create a reference to an object. Thus, when we pass this reference to a method, the parameter that receives it will refer to the same object as that referred to by the argument.
This effectively means that objects act as if they are passed to methods by use of call-by-reference.
Changes to the object inside the method do reflect in the object used as an argument.
if you are doing like below will only change the value.
public static void(String obj[]){
for(String s:obj) {
s=s.toUpperCase();
}
}
I think thus make changes.
I wonder that how it would help us in practice while writing code. In Java numeric wrapper class has overloaded static toString() method and return String representation of the parameter.
Is it common approach to use this methods?
Yes. You could use it whenever you want the String value of a number. Alternatively, you can use String.valueOf(int) note that the Javadoc refers to Integer.toString(int, int) where the second int is the radix.
No, this isn't common. It's simply a convenience method to use instead of having to box the argument into a wrapper object and then call toString on it. Since you can't define any more primitives, only objects, overriding the non-static toString is the way to go in your own code.
It is useful when you need to convert a variable of a primitive type to a String without creating a wrapper object.
Like this:
int a = 5;
String str = Integer.toString(a);
In preparation for the SCJP (or OCPJP as it's now known) exam, I'm being caught out by some mock questions regarding pass-by-(reference)value and immutability.
My understanding, is that when you pass a variable into a method, you pass a copy of the bits that represent how to get to that variable, not the actual object itself.
The copy that you send in, points to the same object, so you can modify that object if its mutable, such as appending to a StringBuilder. However, if you do something to an immutable object, such as incrementing an Integer, the local reference variable now points to a new object, and the original reference variable remains oblivious to this.
Consider my example here :
public class PassByValueExperiment
{
public static void main(String[] args)
{
StringBuilder sb = new StringBuilder();
sb.append("hello");
doSomething(sb);
System.out.println(sb);
Integer i = 0;
System.out.println("i before method call : " + i);
doSomethingAgain(i);
System.out.println("i after method call: " + i);
}
private static void doSomethingAgain(Integer localI)
{
// Integer is immutable, so by incrementing it, localI refers to newly created object, not the existing one
localI++;
}
private static void doSomething(StringBuilder localSb)
{
// localSb is a different reference variable, but points to the same object on heap
localSb.append(" world");
}
}
Question : Is it only immutable objects that behave in such a manner, and mutable objects can be modified by pass-by-value references? Is my understanding correct or are there other perks in this behaviour?
There is no difference between mutable and immautable objects on the language level - immutability is purely a property of a class's API.
This fact is only muddled by autoboxing which allows ++ to be used on wrapper types, making it look like an operation on the object - but it's not really, as you've noticed yourself. Instead, it's syntactic sugar for converting the value to a primitive, incrementing that, converting the result back to the wrapper type and assigning a reference to that to the variable.
So the distinction is really between what the ++ operator does when it's used on a primitive vs. a wrapper, which doesn't have anything to do with parameter passing.
Java itself has no idea of whether an object is immutable or not. In every case, you pass the value of the argument, which is either a reference or a primitive value. Changing the value of the parameter never has any effect.
Now, to clarify, this code does not change the value of the parameter:
localSb.append(" world");
That changes the data within the object that the value of the parameter refers to, which is very different. Note that you're not assigning a new value to localSb.
Fundamentally, you need to understand that:
The value of an expression (variable, argument, parameter etc) is always either a reference or a primitive value. It's never an object.
Java always uses pass-by-value semantics. The value of the argument becomes the initial value of the parameter.
Once you think about those things carefully, and separate in your mind the concepts of "variable", "value" and "object", things should become clearer.