This question already has answers here:
What does this block of code do?
(6 answers)
Closed 8 years ago.
When I do this:
baseApp = (MyApp)this.getContext();
What am I actually doing?
as opposed to doing:
baseApp = myApp.doSomething();
I'm not concern with the methods but understanding the construction.
How are those 2 above different and why?
Whats the meaning of doing (MyApp)?
Whats the meaning of doing (MyApp)?
It is a reference type cast.
It checks that the reference produced by evaluating the RHS (i.e. this.getContext() ) is compatible with MyApp and then uses it that as the result of the expression (with that type). If the reference given by the RHS expression is not for a compatible type, a runtime exception will be thrown.
By contrast ...
baseApp = myApp.doSomething();
is just calling the doSomething() method and assigning it ... WITHOUT doing a typecast. If the doSomething() method does not deliver a value of the correct type, you will get a compilation error.
For the record, there is no "instantiation" going on here. Instantiation is done using the new operator1.
1 - ... or by calling specific reflective methods.
Firstly where are you calling this from? An Activity?
The first line is casting the current objects context to a MyApp object then assigning it to an object named baseApp. And I also assume baseApp is of type MyApp.
The second line is assigning the value returned from the method named doSomething() to baseApp
but more information is needed to compare further.
Related
This question already has answers here:
How does auto boxing/unboxing work in Java?
(4 answers)
Closed 2 years ago.
So I came across a bug caused by following example:
I have static method
private static Foo findFoo(int id) {
//we use id here not important
}
Then I used it inside another method like
private static updateFoo(final Integer id, final String newData) {
final Foo existingData = findFoo(id);
// use existing data and update or make new
}
The problem is when updateFoo is called with null in id argument, the intValue() is implicitly called (I think) when calling findFoo(id) and causes NPE.
I thought Java enforces strong typing that prevents cases where Objects are passed to arguments when primitives are expected. Is there a general rule here when implitic calls are made? And could this be picked up by compiler/IDE and possibly enforce or warn?
This always happens if you use a wrapper class as its primitive counter-part. int cannot be null, so you must call intValue() onto the wrapper class.
You can either do a null check before calling findFoo() or just use the primitive int for updateFoo() or the wrapper class in findFoo().
I thought Java enforces strong typing that prevents cases where Objects are passed to arguments when primitives are expected.
The type of Integer fits, so its type is covered. It is just an implicite casting (unboxing) in this case which is totally fine.
This question already has answers here:
Is there a way to compare lambdas?
(3 answers)
How do I remove lambda expressions/method handles that are used as listeners?
(2 answers)
Does a lambda expression create an object on the heap every time it's executed?
(3 answers)
When does JVM decide to reuse old lambda?
(5 answers)
How will Java lambda functions be compiled?
(2 answers)
Closed 4 years ago.
If I obtain a method reference using the new syntax:
anObject::aMethod
Do I always get the same object? That is, can I trust that two references to the same method will be equal?
This is good to know if, for example, I plan to use them as Runnable callbacks that I can add and remove:
someLibrary.addCallback(anObject::aMethod)
// later
someLibrary.removeCallback(sameObject::sameMethod)
Would this require saving the reference in a Runnable variable to keep it stable?
JLS makes no promises about identity or equality of what you get out of method reference expressions.
You can run a quick test:
Object obj = new Object();
IntSupplier foo = obj::hashCode;
IntSupplier bar = obj::hashCode;
System.out.println(foo == bar); // false
System.out.println(foo.equals(bar)); // false
But this is, of course, implementation dependent.
You could make your lambda Serializable and key your callback map with the serlialized representation. See How to serialize a lambda?. While this will work, it's not exactly required to work by the specs.
Just try this out to get the answer:
Object object = ...;
Supplier<String> s1 = object::toString;
Supplier<String> s2 = object::toString;
System.out.println(s1.equals(s2));
And the answer is... unfortunately not.
OF course if you keep the same reference (i.e. the same object), it will work; but if, as the example above, you request two lambdas, although they seem to be identical, they will never be equal.
Therefore reference = object::methodand then later remove(reference) will obviously work, but remove(sameObject::sameMethod) from a collection will never work if it is written literaly as such.
The answer is also no for constructor (e.g. ArrayList::new) and unbound methods (e.g. Object::toString). It seems that a new lambda is constructed each time you use a lambda expression.
As #Hitobat points it out, this unequality makes sense if you think about what exactly are lambdas and where do they come from. Basicly, Supplier<String> x = myObject::toString is a syntactic suggar for Supplier<String> x = new Supplier<String>( ... ). Without a proper Object.equals overloading, two instances of an anonymous class are obviously different. As many people probably, I though that there was a kind of cache of frequently used lambdas somewhere to make it more efficient; well, not at all.
This question already has answers here:
When is generic return value of function casted after type erasure?
(3 answers)
Closed 5 years ago.
Consider below code and the output in Eclipse 4.5.0 & javac(1.8) .
I know it is due to the type erasure in runtime, but why the second one still output data even it is declared as List of Integer, I also checked with javap, checkcast bytecode is only inserted in the third output .
My questions are :
is it a bug ?
How the javac determine where to insert the "cast" ?
public static void main(String[] args){
List<String> a = Arrays.asList("abc","def");
List<Integer> b = (List<Integer>)(List<?>)a;
System.out.println(b.size()); --output 2
System.out.println(b.get(1)); ---output "def"
System.out.println(b.get(1).getClass()); --error in type cast
EDIT
Checked the answer below and the When is generic return value of function casted after type erasure? , quite similar with my case.
If we add the answer from this What is meant by "the erasure of the static type of the expression on which it is called" in the getClass() docs?, then it will be much clear about the "cast" rule.
The compiler can determine where to insert the cast and ensure type safety.
My first case is fine since it will return int anyway.
Second case is fine since the println expect Object. so no cast is needed to ensure type safety.
Thrid case is not since the getClass() is expected to return the Class which is the static type of b.get(1) according to JLS. So the cast is inserted and get type cast error.
As #newacct said , "you should not rely on the compiler to decide either way" (when there is alternative choice and also ensure type safety ,the 2nd case here).
In the last example, the cast happens as follows
Class clazz = ((Integer)b.get(1)).getClass();
And hence the exception, where the second line
System.out.println(b.get(1));
Does not assign to an integer and hence the cast wont happen, assign it to an integer to see it failing.
Integer x = b.get(1); //fails
This question already has answers here:
How do I print my Java object without getting "SomeType#2f92e0f4"?
(13 answers)
Closed 6 years ago.
Integer ki=new Integer("50");
System.out.println(ki);//Here I would expect to print the objects name something like package_name.Class#15db9742 but this didn't happen.
ki=3;//Here I would expect an error but this actually works.
When System.out.println(ki); executed then 50 appeared in the console but when I print other objects some thing like package_name.Class#15db9742 appears why 50 appeared instead of something like package_name.Class#15db9742?
I though ki is type Integer so when I assign the primitive value of 3 I should get an error but I didn't why?
You have two separate questions there:
System.out.println(ki);//Here I would expect to print the objects name something like package_name.Class#15db9742 but this didn't happen.
Because Integer overrides toString. Its implementation:
public String toString() {
return String.valueOf(value);
}
Hmm...or because println(int) exists on PrintStream.
Nope, it's calling System.out.println(Object), which then uses toString on the object. This is because (as the specification tells us) the rule is to first try to find a matching signature without auto-(un)boxing and without varargs; then just with auto-(un)boxing, then at last with both.
ki=3;//Here I would expect an error but this actually works.
That's because of autoboxing: The Java compiler inserts the necessary code to take that primitive 3 and create an Integer instance for it. The bytecode it actually emits does this:
ki = Integer.valueOf(3);
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Which constructor is chosen when passing null?
I recently came across this curiosity while coding a few days back and can't seem to figure out why the following happens:
Given the class below
public class RandomObject{
public RandomObject(Object o){
System.out.println(1);
}
public RandomObject(String[] s){
System.out.println(2);
}
}
When the call new RandomObject(null); is made the output is always 2 regardless of the order in which the constructors were created. Why does null refer to the string array rather than the object?
The key here is that Object is the super type of String[]
Java uses the most specific available method to resolve such cases. Null can be passed to both methods without compilation errors so Java has to find the most specific method here. The version with String[] is more specific - therefore it will be chosen for execution.
Someone else has had this question earlier, check this post
If there are two cases to choose from, the compiler will first try to pick the more specific case. In this case, String will be picked over Object.
In the other question it was String str instead of String[] s
Thus, since String[] is a more specific datatype than its super type Object, it is picked.