Call Overloaded methods with ternary operator? - java

What is the rule that I can not call overloaded methods with checking instanceOf with ternary operator?
It may be a stupid question, but I want little explanation about this rule. You can see in screenshot, I can not refer to multiple methods by using the ternary operator.
public class Sample {
public static void main(String[] args) {
Object object = new String("");
Foo.load(object instanceof Integer ? (Integer) object :
object instanceof String ? (String) object : null);
}
public static class Foo {
public static void load(String s) {
//
}
public static void load(Integer s) {
//
}
}
}

Method resolution is done in compile time. At the end of the day, you pass some expression that returns a value to a method. The compiler inspects the expression's type and determines which method it should call.
Here, you're attempting to write an expression that may return different types according to runtime information and invoke a method accordingly. And as you've seen, this just won't fly. Instead, you could explicitly invoke the different methods according to the type (the fact that they have the same name is inconsequential - they are still different methods!):
if (object instanceof Integer) {
Foo.load((Integer) object); // Calls Foo.load(Integer)
} else if (object instanceof String) {
Foo.load((String) object); // Calls Foo.load(String)
} else {
Foor.load(object); // Calls Foo.load(Object)
}

Object obj = getObject();
if(obj instanceof Integer)
load((Integer)obj);
else if(obj instanceof String)
load((String)obj);
else
load(obj);
Error, because the overloaded method is been choosen at the compilation time, but not runtime, when you use instanceof. To move this check to the runtime, do use e.g. if...else.
HINT
load(obj instanceof String ? (String)obj : obj);
This is OK and does not throw compilation error, but what do you think, which overloaded method will be called, when obj = "some string", load(String s) ???
NO!!! load(Object s) for both String and Object instance.

In your case, an empty string or null doesnot test for reference equality.
Your solution will work if the Object object = new String("test");
is there.
Also, for primitive types like int, float etc you don't really need instanceof.. instanceof is more for classes.
Here is a link on how instanceof really works:
https://docs.oracle.com/javase/tutorial/java/nutsandbolts/op2.html

Related

How to compare object type with boolean

import java.util.HashMap;
public class file{
public static void main(String args[]){
Object a;
a = true;
if (a == true){
System.out.println("Yes");
}
}
}
I get the error error: incomparable types: Object and boolean
I was to compare object a which stores a boolean value with an actual boolean type. How do I do that?
This happens because boolean primitive true is boxed for conversion to Object. You need to compare it to another boxed object, like this
if (a == Boolean.TRUE) {
...
}
or like this
if (a.equals(true)) {
...
}
You are comparing an Object reference to a primitive boolean - the types are not compatible for the equality operator (==). You should generally avoid using == with objects unless you really want to check if it is the same reference.
Prefer the equals method to compare objects.
if (Boolean.TRUE.equals(a)) { ... do stuff ... }
Note that we are invoking the method on a statically defined instance and passing the variable to be tested as the argument. The method will handle null arguments and incorrect type arguments (it will return false) so you don't have to.
Try this -
if (Boolean.TRUE.equals(a)) { ... }

How can I return objects of different type from a single function?

I need to return objects of different classes in a single method using the keyword Object as the return type
public class ObjectFactory {
public static Object assignObject(String type) {
if(type.equalsIgnoreCase("abc")){
return new abcClass();
} else if(type.equalsIgnoreCase("def")) {
return new defClass();
} else if(type.equalsIgnoreCase("ghi")) {
return new ghiClass();
}
return null;
}
}
and in another class I am trying to get the objects as
public class xyz{
public void get(){
Object obj=(abcClass)ObjectFactory.assignObject("abc");
}
}
How can I access the methods in abcClass using the obj object??
Your current code will throw an exception if assignObject returns an instance that is not an abcClass, so you can change the type of obj to absClass :
public void get(){
abcClass obj=(abcClass)ObjectFactory.assignObject("abc");
}
I would suggest as one of the commentators on your initial post did. That is, refactor this to use an interface.
Your classes AbcClass, DefClass, and GhiClass, could all implement an interface, lets call it Letters. You can then define a class called LettersFactory, with the method createLetters. At this point, I'd also recommend changing your hard coded string identifiers into an enumeration. For instance:
public enum LetterTypes { ABC, DEF, GHI }
You're factory method can then accept this enumeration, and you have no fears of getting invalid values. The factory method can also return the type Letters (the interface) and you have a more specific version of Object (which is good).
Finally, if you need to determine these types on the fly, you can have a method defined in Letters (forcing all children to implement it) called getType() which returns the LetterTypes enumeration for the class that is implemented.
You could also use the instanceof operator to determine which class you have.
Cheers,
Frank
You can use this as a refrence :-
public Object varyingReturnType(String testString ){
if(testString == null)
return 1;
else return testString ;
}
Object o1 = varyingReturnType("Lets Check String");
if( o1 instanceof String) //return true
String now = (String) o1;
Object o2 = varyingReturnType(null);
if( o2 instanceof Integer) //return true
int i = (Integer)o2;
So similarly you can use your own conditions along with the instanceof operator and can cast it to get the actual object type from Object type.

How to check type of param class?

I have the following method:
public static String getServiceUri(Class<?> c) {
// I'd like to check which type the parameter is...
if(c.getClass().equals(MyClass.class)){
do stuff 1
} else {
do stuff 2
}
}
Invoke method:
getServiceUri(MyClass.class);
On getServiceUri I want to call a WebService based on the type of a ServiceClass.
I know that equals will compare objects instance, but in this case I'm trying to discover the type of object.
Anyone know how I can compare using this kind of approach?
instanceof operator is the best choice..
you can do something like this
if(c instanceof MyClass){
//do your stuff
}
public static String getServiceUri(Class<?> classParam) {
if(classParam instanceof MyClass){
}
}
This is WRONG. It does not even compile because classParam needs to be an actual instance(object) to use the instanceof operator: hence the name.
If you want to know if the classParam is exactly equal to MyClass.class:
public static String getServiceUri(Class<?> c) {
if(classParam == MyClass.class){
}
}
However, if you want to check the entire hierarchy of classParam against MyClass then you can do classParam.isAssignableFrom(MyClass.class)

Check if an object belongs to a class in Java [duplicate]

This question already has answers here:
How to determine an object's class?
(13 answers)
Closed 9 years ago.
Is there an easy way to verify that an object belongs to a given class? For example, I could do
if(a.getClass() = (new MyClass()).getClass())
{
//do something
}
but this requires instantiating a new object on the fly each time, only to discard it. Is there a better way to check that "a" belongs to the class "MyClass"?
The instanceof keyword, as described by the other answers, is usually what you would want.
Keep in mind that instanceof will return true for superclasses as well.
If you want to see if an object is a direct instance of a class, you could compare the class. You can get the class object of an instance via getClass(). And you can statically access a specific class via ClassName.class.
So for example:
if (a.getClass() == X.class) {
// do something
}
In the above example, the condition is true if a is an instance of X, but not if a is an instance of a subclass of X.
In comparison:
if (a instanceof X) {
// do something
}
In the instanceof example, the condition is true if a is an instance of X, or if a is an instance of a subclass of X.
Most of the time, instanceof is right.
If you ever need to do this dynamically, you can use the following:
boolean isInstance(Object object, Class<?> type) {
return type.isInstance(object);
}
You can get an instance of java.lang.Class by calling the instance method Object::getClass on any object (returns the Class which that object is an instance of), or you can use class literals (for example, String.class, List.class, int[].class). There are other ways as well, through the reflection API (which Class itself is the entry point for).
Use the instanceof operator:
if(a instanceof MyClass)
{
//do something
}
I agree with the use of instanceof already mentioned.
An additional benefit of using instanceof is that when used with a null reference instanceof of will return false, while a.getClass() would throw a NullPointerException.
Try operator instanceof.
The usual way would be:
if (a instanceof A)
However, there are cases when you can't do this, such as when A in a generic argument.
Due to Java's type erasure, the following won't compile:
<A> boolean someMethod(Object a) {
if (a instanceof A)
...
}
and the following won't work (and will produce an unchecked cast warning):
<A> void someMethod(Object a) {
try {
A casted = (A)a;
} catch (ClassCastException e) {
...
}
}
You can't cast to A at runtime, because at runtime, A is essentially Object.
The solutions to such cases is to use a Class instead of the generic argument:
void someMethod(Object a, Class<A> aClass) {
if (aClass.isInstance(a)) {
A casted = aClass.cast(a);
...
}
}
You can then call the method as:
someMethod(myInstance, MyClass.class);
someMethod(myInstance, OtherClass.class);

Explicit vs implicit call of toString

I used to use the implicit call of toString when wanting some debug info about an object, because in case of the object is null it does not throw an Exception.
For instance:
System.out.println("obj: "+obj);
instead of:
System.out.println("obj: "+obj.toString());
Is there any difference apart from the null case?
Can the latter case work, when the former does not?
Edit:
What exactly is done, in case of the implicit call?
There's little difference. Use the one that's shorter and works more often.
If you actually want to get the string value of an object for other reasons, and want it to be null friendly, do this:
String s = String.valueOf(obj);
Edit: The question was extended, so I'll extend my answer.
In both cases, they compile to something like the following:
System.out.println(new StringBuilder().append("obj: ").append(obj).toString());
When your toString() is implicit, you'll see that in the second append.
If you look at the source code to java, you'll see that StringBuilder.append(Object) looks like this:
public StringBuilder append(Object obj) {
return append(String.valueOf(obj));
}
where String.valueOf looks like this:
public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();
}
Now, if you toString() yourself, you bypass a null check and a stack frame and go straight to this in StringBuilder:
public StringBuilder append(String str) {
super.append(str);
return this;
}
So...very similar things happens in both cases. One just does a little more work.
As others have said - use the "" + obj method.
According to The Java Language Spec:
If the term is null, use "null"
Primitive types are converted using the boxed-type constructor new Boolean(X) or whatever
toString() is invoked (or equivalent)
if the result of toString() is null, use "null"
Concatenate the strings.
No difference except, like you say, the null safety. Always prefer the former to the latter.
Actually, if your invariant says the object should never be null, it doesn't matter. So it depends on whether or not you accept obj to be null.
It is quite easy to write a generic reference type.
class ref
{
static public class Reference<T>
{
private T value;
public Reference(T value) { set(value); }
public Reference() { set(null); }
public void set (T value) { this.value = value; }
public T get () { return this.value; }
public String toString() { return String.valueOf(this.value); }
}
static void fillString (Reference<String> str)
{
str.set("foo");
}
public static void main (String[] args)
{
Reference<String> str = new Reference<String>("");
fillString(str);
System.out.println (str);
}
}
Running it gives the required output:
javac ref.java && java ref
foo

Categories