Explicit vs implicit call of toString - java

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

Related

Java - String.format , skip if null [duplicate]

Consider the custom toString() implementation of a bean:
#Override
public String toString() {
String.format("this is %s", this.someField);
}
This yields this is null if someField is null.
Is there a way to override the default null string representation of null-valued arguments to another text, i.e., ? without calling explicitly replaceAll(...) in the toString method?
Note: The bean inherits from a superclass that could implement Formattable (http://docs.oracle.com/javase/7/docs/api/java/util/Formattable.html) but I just don't seem to understand how to make this work.
EDIT: The snippet is over-simplified for the sake of example but I'm not looking for ternary operator solutions someField==null ? "?" : someField because:
there can be (potentially) a great many fields involved in toString() so checking all fields is too cumbersome and not fluent.
other people whom I have little control over (if any) are writing their own subclasses.
if a method is called and returns null that would either imply calling the method twice or declaring a local variable.
Rather, can anything be done using the Formattable interface or having some custom Formatter (which is final btw.)?
With java 8 you can now use Optional class for this:
import static java.util.Optional.ofNullable;
...
String myString = null;
System.out.printf("myString: %s",
ofNullable(myString).orElse("Not found")
);
For a Java 7 solution that doesn't require external libraries:
String.format("this is %s", Objects.toString(this.someField, "?"));
The nicest solution, in my opinion, is using Guava's Objects method, firstNonNull. The following method will ensure you will print an empty string if someField is ever null.
String.format("this is %s", MoreObjects.firstNonNull(this.someField, ""));
Guava docs.
A bit late on the subject, but this could be a quite clean-looking solution :
First, create your own format method...
private static String NULL_STRING = "?";
private static String formatNull(String str, Object... args){
for(int i = 0; i < args.length; i++){
if(args[i] == null){
args[i] = NULL_STRING;
}
}
return String.format(str, args);
}
Then, use it as will...
#Test
public void TestNullFormat(){
Object ob1 = null;
Object ob2 = "a test";
String str = formatNull("this is %s", ob1);
assertEquals("this is ?", str);
str = formatNull("this is %s", ob2);
assertEquals("this is a test", str);
}
This eliminates the need for multiple, hard-to-read, ternary operators.
If you don't want to use replaceAll(), You can assign a default text(String) for someField.
But if some time this may assign null again. So you can use validation for that case
this.someField == null ? "defaultText" : this.someField
To avoid repeating ternary operator you can wrap it in more readable method that will check if your object is null and return some default value if it is true like
static <T> T changeNull(T arg, T defaultValue) {
return arg == null ? defaultValue : arg;
}
usage
String field = null;
Integer id = null;
System.out.printf("field is %s %n", changeNull(field, ""));
System.out.printf("id is %d %n", changeNull(id, -1));
System.out.printf("id is %s %n", changeNull(field, ""));
output:
field is
id is -1
id is
You could just do
String.format("this is %s", (this.someField==null?"DEFAULT":this.someField));
From java 7, you can use Objects.toString(Object o, String nullDefault).
Applied to your example: String.format("this is %s", Objects.toString(this.someField, "?"));
public static String format(String format, Object... args){
for (int i=0;i<args.length;i++){
if (args[i]==null) args[i]="";
}
return String.format(format,args);
}
then use the method ,ok
To keep the original value of someField (in case null is a valid value), you can use a ternary operator.
String.format("This is %s", (this.someField == null ? "unknown" : this.someField));

How to get elements from Generic Object?

public void method(Object variable){
System.out.println(variable.toString());
}
When I invoke the method above, I get the following output:
<Heading element1=value1 element2=value2 element3=value3/>
How can I get only 'value3' from this object's toString method without resorting to String operations or Regex with the Matcher class?
As it has been remarked in the comments, you cannot do what you're attempting without using a regex or at least casting the Object to something more specific and then retrieving the property value you're looking for.
You might want to try something like
public void method(Object variable){
if (variable instanceof MyClass){
MyClass mc = (MyClass) variable;
System.out.println(mc.getMyProperty());
} else {
//... regex implementation ...
}
}

Call Overloaded methods with ternary operator?

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

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)

Categories