Need assistance with question on java generics

Viewed 66

My output is currently:

Avengers@15db9742 Avengers@6d06d69c

I need to figure out how to display the names as well, using the generic print method. I've been trying things like: GenericMethod_violette.<Avengers>print(avenger.getName()) and GenericMethod_violette.<Avengers>print(avenger.trueIdentity()) but after days on this I seem to be stuck.

My output needs to be:

Avengers@15db9742 Avengers@6d06d69c
Tony Stark, Bruce Banner

My GenericMethod_violette.java:

import java.io.ObjectInputStream.GetField;

public class GenericMethod_violette {
  public static void main(String[] args ) {
    Avengers[] avenger = { new Avengers("Tony Stark"), new Avengers("Bruce Banner")};
    
    GenericMethod_violette.<Integer>print(integers);
    GenericMethod_violette.<String>print(strings);
    GenericMethod_violette.<Avengers>print(avenger);

    
  }

  public static <E> void print(E[] list) {
    for (int i = 0; i < list.length; i++)
      System.out.print(list[i] + " ");
    System.out.println();
  }
    
}

My Avengers.java:

public class Avengers
{
   private String trueIdentity;

   public Avengers(String name)
   {
      trueIdentity = name;
    }    

   public String getName()
   {
       return trueIdentity;
   }

   public String sayTrueIdentity()
   {
       return "Hello, I'm " + trueIdentity + "!";
   }
}
3 Answers

you can use write toString inside Avengers

      public class Avengers
        {
           private String trueIdentity;
        
           public Avengers(String name)
           {
              trueIdentity = name;
            }    
        
           public String getName()
           {
               return trueIdentity;
           }
        
           public String sayTrueIdentity()
           {
               return "Hello, I'm " + trueIdentity + "!";
           }
           // write any format you want to print
           @override
           public String toString()
           {
               return this.getName() + this.sayTrueIdentity();
           }
        }

then change your GenericMethod_violette.print method to use toString()

  public static <E> void print(E[] list) {
    for (int i = 0; i < list.length; i++)
      System.out.print(list[i] + " ");
    System.out.println();
  }

Reason for Avengers print format - Avengers@15db9742

In java all objects have a toString() method, which is invoked when you try and print the object.

    System.out.println(myObject);  // invokes myObject.toString()

This method is defined in the Object class (the superclass of all Java objects). The Object.toString() method returns a fairly ugly looking string, composed of the name of the class, an @ symbol and the hashcode of the object in hexadecimal. The code for this looks like:

    // Code of Object.toString()
    public String toString() {
        return getClass().getName() + "@" + Integer.toHexString(hashCode());
    }  

So you need @overrride toString method.

Your print result of Avengers@15db9742 would mean that it is an object that you printed. If you want to print something meaningful, you need to override the toString() method of said object. In this case, of your Avengers object.

public String toString(){
    return trueIdentity;
}

Added notes from @markspace of java toString().

The class Avengers doesn't override the Object::toString method which System.out.println implicitely uses in its implementation. I suggest you to read more at: How to override toString() properly in Java?.

However, this solution requires all the possible objects passed into the method to override such method, which you cannot guarantee. I recommend you to pass a Function<E, String> that exctracts from the generic type the field(s) as String to be printed out:

public static <E> void print(E[] array, Function<E, String> extractor) {
    for (E e: array) {
        System.out.print(extractor.apply(e) + " ");
    }
    System.out.println();
}

The usage is fairly simple (the generic type can be omitted as long as it is inferred):

// both following lines are basically identical
GenericMethod_violette.print(avenger, a -> a.getName());
GenericMethod_violette.print(avenger, Avenger::getName);
// if Avengers have more of the fields or they are to be customized, ex.:
GenericMethod_violette.print(avenger, a -> "Mr." + a.getName().toUpperCase());

Disclaimer: This solution requires Java 8. If you use Java 7 or lower, you are stick to override the Object::toString in all the expected classes:

@Override
public String toString() {
    return this.getName();
}
Related