toString method call issues
Hi!
I am having some issues in my very last function I am tasked with writing.
It is using the toString() method to display the objects in an array that match only those from a specific class. For some reason, all I get when I execute the function is white space.
Here's the code (it's a lot, sorry!):
MAIN:
Code:
package assignment.pkg3;
import java.util.Scanner;
public class Assignment3 {
//Function for user menu display and input
public static int getMenuChoice()
{
Scanner keyboard = new Scanner(System.in);
System.out.println("\n-----------------------------"
+ "\nHere are your Choices: \n"
+ "Enter 1 to add a Subscriber \n"
+ "Enter 2 to add an Application \n"
+ "Enter 3 to remove a Subscriber \n"
+ "Enter 4 to remove an Application \n"
+ "Enter 5 to display all Subscribers \n"
+ "Enter 6 to display all Applications \n"
+ "Enter 7 to Quit "
+ "\n-----------------------------\n");
return keyboard.nextInt();
}
public static void main(String[] args)
{
Set<Element> anElementSet;
Element anElement;
Subscriber aSub;
Application anApp;
Scanner keyboard = new Scanner(System.in);
int menuChoice;
String search = "";
boolean isDone = false;
menuChoice = getMenuChoice();
anElementSet = new Set<Element>();
//Initiate loop to display menu
while(!isDone)
{
if(menuChoice == 7)
{
System.out.println("Are you sure you want to quit? (Y/N)");
String askQuit;
askQuit = keyboard.nextLine().toUpperCase();
if(askQuit.equals("Y"))
{
isDone = true;
break;
}
}
switch(menuChoice)
{
case 1:
//add subscriber to Element Set array
anElement = new Subscriber();
anElement.readIn();
anElementSet.add(anElement);
break;
case 2:
//add application to Element Set array
anElement = new Application();
anElement.readIn();
anElementSet.add(anElement);
break;
case 3:
System.out.println("Enter Subscriber's name: ");
search = keyboard.nextLine().toUpperCase();
for(int i = 0; i < anElementSet.size(); i++)
{
anElement = anElementSet.getCurrent();
if(anElement instanceof Subscriber)
{
aSub =(Subscriber)anElement;
if((aSub.getName()).equals(search))
{
anElementSet.removeObject(aSub);
}
else
{
System.out.println("Member not found, "
+ "removal unsuccessful.");
}
}
}
break;
case 4:
System.out.println("Enter Application's name: ");
search = keyboard.nextLine().toUpperCase();
for(int i = 0; i < anElementSet.size(); i++)
{
anElement = anElementSet.getCurrent();
if(anElement instanceof Application)
{
anApp =(Application)anElement;
if((anApp.getName()).equals(search))
{
anElementSet.removeObject(anApp);
}
else
{
System.out.println("Member not found, "
+ "removal unsuccessful.");
}
}
}
break;
case 5:
//display all Subscribers in the Element Set array
anElementSet.displayAllInClass(Subscriber.class.getName());
break;
case 6:
//display all Applications in the Element Set array
anElementSet.displayAllInClass(Application.class.getName());
break;
}
menuChoice = getMenuChoice();
}
}
}
ELEMENT ABSTRACT:
Code:
package assignment.pkg3;
public abstract class Element
{
public String getClassName()
{
// Local data ...
String resultStr;
int whereAt; // Where the . is in the class name
// Logic ...
resultStr = getClass().getName();
whereAt = resultStr.indexOf('.');
return resultStr.substring(whereAt + 1);
}
// Abstract methods readIn, display and eqauls.
// Direct subclasses must implement these in order for them
// not to be abstract.
public abstract void readIn();
public abstract void display();
@Override
public abstract Element clone();
@Override
public abstract String toString();
}
SUBSCRIBER CLASS:
Code:
package assignment.pkg3;
import java.util.Scanner;
public class Subscriber extends Element {
//Field declarations
private String name;
private String url;
private int adClicks;
//Default Constructor
Subscriber()
{
name = "";
url = "";
adClicks = 0;
}
//Set Constructor Fields
Subscriber(String subName, String subUrl,
int subClicks)
{
name = subName;
url = subUrl;
adClicks = subClicks;
}
public Subscriber(String aName)
{
name = aName.toUpperCase();
}
//=============Accessor methods=============
public String getName()
{
return name;
}
public String getUrl()
{
return url;
}
public int getAdClicks()
{
return adClicks;
}
//=============Mutator methods=============
public void setName(String aName)
{
name = aName.toUpperCase();
}
public void setUrl(String aUrl)
{
url = aUrl;
}
public void setAdClicks(int aAdClicks)
{
adClicks = aAdClicks;
}
//=============ReadIn method=============
@Override
public void readIn()
{
Scanner keyboard = new Scanner(System.in);
System.out.println("Subscriber's name: ");
name = keyboard.nextLine().toUpperCase();
System.out.println("Subscriber's url: ");
url = keyboard.nextLine();
System.out.println("Subscriber's ad clicks: ");
adClicks = keyboard.nextInt();
}
//=============Display method=============
@Override
public void display()
{
System.out.println(this.toString());
}
//=============Equals method=============
@Override
public boolean equals(Object otherSubscriber)
{
return name.equals(((Subscriber) otherSubscriber).name);
}
//=============Clone method=============
@Override
public Element clone()
{
Subscriber aClone = new Subscriber();
aClone.name = name;
aClone.url = url;
aClone.adClicks = adClicks;
return aClone;
}
@Override
public String toString()
{
return ("Name: " + name +
"\nURL: " + url +
"\nAd Clicks: " + adClicks);
}
}
APPLICATION CLASS:
Code:
package assignment.pkg3;
import java.util.Scanner;
public class Application extends Element{
//Field declarations
public String name;
public String url;
public int downloads;
//Default Constructor
Application()
{
name = "";
url = "";
downloads = 0;
}
//Set Constructor Fields
Application(String appName, String appUrl, int appDownloads)
{
name = appName;
url = appUrl;
downloads = appDownloads;
}
public Application(String aName)
{
name = aName.toUpperCase();
}
//=============Accessor methods=============
public String getName()
{
return name;
}
public String getUrl()
{
return url;
}
public int getDownloads()
{
return downloads;
}
//=============Mutator methods=============
public void setName(String aName)
{
name = aName.toUpperCase();
}
public void setUrl(String aUrl)
{
url = aUrl;
}
public void setDownloads(int aDownload)
{
aDownload = downloads;
}
//=============ReadIn method=============
@Override
public void readIn()
{
Scanner keyboard = new Scanner(System.in);
System.out.println("Application's name: ");
name = keyboard.nextLine().toUpperCase();
System.out.println("Application's url: ");
url = keyboard.nextLine();
System.out.println("Application's downloads: ");
downloads = keyboard.nextInt();
}
//=============Display method=============
@Override
public void display()
{
System.out.println(this.toString());
}
//=============Equals method=============
@Override
public boolean equals(Object otherApplication)
{
return name.equals(((Application) otherApplication).name);
}
//=============Clone method=============
@Override
public Element clone()
{
Application aClone = new Application();
aClone.name = name;
aClone.url = url;
aClone.downloads = downloads;
return aClone;
}
@Override
public String toString()
{
return ("Name: " + name +
"\nURL: " + url +
"\nDownloads: " + downloads);
}
}
ELEMENTSET (generics) CLASS:
Code:
package assignment.pkg3;
import java.util.ArrayList;
/**
This revised version of the Set<T> generic class uses
the revised version of the Element class, the version
that uses the Object parameter for the abstract method,
equals..
This allows us to reintroduce the isMemberOf method to
the Set data structure.
*/
public class Set <T>
{
// Fields ...
ArrayList<T> theList;
// Will reference an ArrayList of objects
// from the class T.
int currentIndex;
// Index of current element in the set
final int START_CAP = 100;
// Initial capacity of the ArrayList.
// This over-rides the default initial
// capacity of 10.
// Constructor ...
/**
The Set constructor sets up an ArrayList of T references
with STARTSIZE-many cells. It also initializes currentIndex
to -1.
*/
public Set()
{
theList = new ArrayList<T>(START_CAP);
currentIndex = -1;
}
// Test methods
/**
The isEmpty method returns true if the calling object
is empty and false otherwise.
@return true if the calling object is empty and false
otherwise.
*/
public boolean isEmpty()
{
return theList.isEmpty();
}
/**
The isMemberOf method tests to see if the parameter, aT,
is already a member of the Set. This assumes the type
T has an appropriate equals method, redefining the Object
class equals method, so that we are not just comparing
references.
@param anElement the object being checked for membership in
the set
@return true if anElement is already in the set and false
*/
public boolean isMemberOf(T aT)
{
// Local data ...
String paramClass = aT.getClass().getName();
String currClass;
// Logic ...
for (T currT: theList)
{
currClass = currT.getClass().getName();
// Only compare aT against those objects
// that belong to aT's class
if (currClass.equals(paramClass))
{
if (currT.equals(aT))
{
return true;
}
}
}
// No matching object found
return false;
}
// Access methods
/**
The size method returns the number of objects
currently in the set.
@return the value of currentSize
*/
public int size()
{
return theList.size();
}
/**
The getCurrent() method returns a reference to the
current object in the set. Note the pre-condition.
This method should only be called if the set is
not empty. The method advances currentIndex to
the next object to set up for the next call to
getCurrent. If getCurrent returns a copy of
the last object, currentIndex is reset to 0. Note
that this method assumes the type T has a
copy constructor.
Pre: currentIndex is not -1 (which can only
occur if currentSize is not 0).
@return reference to the current object in the set
*/
public T getCurrent()
{
// Local data ...
int saveIndex = currentIndex;
// Logic ...
if (currentIndex == theList.size() - 1)
{
// Recycle to beginning of list
currentIndex = 0;
}
else
{
// Advance currentIndex to next object
currentIndex++;
}
// Return a reference to the current object
return theList.get(saveIndex);
// NOTE: WE ARE RETURNING A REFERENCE
// TO AN OBJECT IN THE SET, NOT A COPY
// OF THE OBJECT. WHY? BECAUSE IF WE
// TRIED TO USE THE clone() METHOD HERE
// THE COMPILER GETS GRUMPY! ALL METHODS
// WE APPLY TO OBJECTS IN THE SET MUST BE
// IN THE Object CLASS.
}
// Mutator methods ...
/**
The add method attenots to add the aT parameter to the set.
It will fail if aT is already in the calling object set.
@param aT the T-thing we attempt to add
@return false if the object is a duplicate and
it couldn't be added and true otherwise
*/
public boolean add(T aT)
{
// Return false if aT is already in the calling object
if (this.isMemberOf(aT))
{
// it's a duplicate - we can't add it
System.out.println("\nMember already present in set, add "
+ "unsuccessful.");
return false;
}
// It's not a duplicate. Add aT
theList.add(aT);
// NOTE: WE ARE ADDING THE REFERENCE TO aT,
// WE ARE NOT CLONING IT.
// Set currentIndex to object we just added if it was the
// first object in the set.
if (theList.size() == 1) currentIndex = 0;
// Successful add
System.out.println("\nMember successfully added to set.");
return true;
}
/**
The clear method resets the set to the empty set.
*/
public void clear()
{
currentIndex = -1;
theList = new ArrayList<T>();
}
public boolean removeObject(T anObject)
{
String paramClass = anObject.getClass().getName();
String currClass;
// Logic ...
for (T currT: theList)
{
currClass = currT.getClass().getName();
if (currClass.equals(paramClass))
{
if (currT.equals(anObject))
{
theList.remove(anObject);
System.out.println("Member found and has been removed from "
+ "the set.");
return true;
}
}
}
return false;
}
//Declare universal class display method
public void displayAllInClass(String theClassName)
{
System.out.println("Here");
if (theList.isEmpty())
{
System.out.println("There are no members in the set. ");
}
else
{
for (int i = 0; i < theList.size(); i++)
{
if(theClassName.equals(theList.getClass().getName()))
{
System.out.println(theList.get(i).toString());
System.out.println("\n");
}
}
}
}
// The display method
/**
The display method displays all of the objects in the
set. This method assumes that the class T implements
the toString method in an appropriate manner, so that
the contents of the relevant object can be displayed.
*/
public void display()
{
// Local variables
// we will display
if (theList.isEmpty())
{
System.out.println("There are no objects in the set. ");
}
else
{
System.out.println("Here are the objects in the set: \n");
for (int i = 0; i < theList.size(); i++)
{
System.out.println(theList.get(i).toString());
System.out.println("\n");
}
}
}
}
Here's the function that's not working correctly:
Code:
public void displayAllInClass(String theClassName)
{
System.out.println("Here");
if (theList.isEmpty())
{
System.out.println("There are no members in the set. ");
}
else
{
for (int i = 0; i < theList.size(); i++)
{
if(theClassName.equals(theList.getClass().getName()))
{
System.out.println(theList.get(i).toString());
System.out.println("\n");
}
}
}
}
Here's the specific line:
Code:
System.out.println(theList.get(i).toString());
When I execute (making sure there are members in the set), it just does not print anything. I know it must be something with the way I'm attempting to execute the toString() method, but I am not sure why.
Thank you for the help! :(happy):
Re: toString method call issues
Quote:
all I get when I execute the function is white space.
What does the output look like?
Add some debug stuff to your printout:
System.out.println("i=" + i + " data=" + theList.get(i).toString() +"<");
Where is the defintion of the toString() method that is being called?
Re: toString method call issues
Here's the debug code:
Code:
public void displayAllInClass(String theClassName)
{
System.out.println("Here1");
if (theList.isEmpty())
{
System.out.println("Here2");
System.out.println("There are no members in the set. ");
}
else
{
System.out.println("Here3");
for (int i = 0; i < theList.size(); i++)
{
System.out.println("Here4");
if(theClassName.equals(theList.getClass().getName()))
{
System.out.println("Here5");
System.out.println("i=" + i + " data=" + theList.get(i).toString() + "<");
System.out.println("Here6");
System.out.println("\n");
}
}
}
}
Output:
Code:
-----------------------------
Here are your Choices:
Enter 1 to add a Subscriber
Enter 2 to add an Application
Enter 3 to remove a Subscriber
Enter 4 to remove an Application
Enter 5 to display all Subscribers
Enter 6 to display all Applications
Enter 7 to Quit
-----------------------------
5
Here1
Here3
Here4
So it looks like I was wrong, it's the if statement that's not executing:
Code:
if(theClassName.equals(theList.getClass().getName()))
Sorry, for leading you down the wrong path, I remember debugging before and sincerely thought it stopped at that print line and not the if statement.
Anyways, let's see here... I myself don't see anything wrong here.
Code:
theList.getClass().getName()
Is pulling the name of the class from theList. And the function call:
Code:
anElementSet.displayAllInClass(Subscriber.class.getName());
is ensuring that the name corresponds with what the user wants to display. A little confused here.
Re: toString method call issues
print out the value of everything and see what they are.
Re: toString method call issues
Ah okay. Well we've found the issue:
I stuck in this snippet of code to find what you were asking for:
Code:
System.out.println(theList.getClass().getName());
System.out.println(Subscriber.class.getName());
System.out.println(Application.class.getName());
Output:
Code:
java.util.ArrayList
assignment.pkg3.Subscriber
assignment.pkg3.Application
So Code:
theList.getClass().getName()
is not referring to a class, instead it's referring to the name of the list itself (or utility, whatever it is). Why isn't the getClass method doing its job!? :(sweat):
Re: toString method call issues
Sorry I'm not following which get method does what and what was printed and why it is not what you expect.
Please post what method was used for each of the classnames/Strings you print out
and add some comments to the post next to the output saying what you expected to be printed out.
What do you expect getClass() to return? Then given that object, what do you expect the getName() method to return?
What does the API doc say?
Re: toString method call issues
Sorry, I want this function:
Code:
public void displayAllInClass(String theClassName)
to print out all objects of the array, theList, that belong to either the Application or Subscriber class.
What I expect this function to do:
Code:
if(theClassName.equals(theList.getClass().getName()))
{
System.out.println(theList.get(i).toString());
System.out.println("\n");
}
is basically say this "If the string "theClassName" equals a specific class in the list (Subscriber or Application), then print out all objects associated with that class.
As of right now, Code:
theList.getClass().getName())
does not do what I expected it to do (return either Subscriber or Application as the class name).
I am unsure what I would use instead in its place.
Re: toString method call issues
Quote:
theList.getClass().getName())
does not do what I expected it to do
Can you show what it does do
and add comments that show what you need or want?
What class is theList? It looks like it's an ArrayList. So I'd expect getName() to return: java.util.ArrayList
Are you wanting to look at the contents of the ArrayList?
Re: toString method call issues
This is what I expect:
Code:
if(theClassName.equals(theList.getClass().getName())) //return theClassName equals either "Subscriber" or "Application"
{
System.out.println(theList.get(i).toString());//print objects in list that belong to the class
System.out.println("\n");
}
Code:
theList.getClass().getName()
currently returns java.util.ArrayList, as you said it would. I want something that returns an appropriate class name (Subscriber or Application).
Re: toString method call issues
theList is an ArrayList.
Do you want to look at the objects that are contained in the ArrayList?
Re: toString method call issues
Yes I do want to look at the contents of the ArrayList and pull out any objects that belong to the specified class.
For example, the function call:
Code:
anElementSet.displayAllInClass(Subscriber.class.getName());
should search through the ArrayList and display ALL objects associated with ONLY the SUBSCRIBER class.
Re: toString method call issues
Read the API doc for the ArrayList class to see what method to use to get a reference to an object in the ArrayList.
When you get an object out of the ArrayList you can test it to see if it is the type of object you are looking for.
Re: toString method call issues
The only methods I see that would be helpful are get() and indexOf(). Do these seem correct?
I already have a method from my last program that uses indexOf to find the class name, but I cannot use that in my current program.
Code:
public String getClassName()
{
// Local data ...
String resultStr;
int whereAt; // Where the . is in the class name
// Logic ...
resultStr = getClass().getName();
whereAt = resultStr.indexOf('.');
return resultStr.substring(whereAt + 1);
}
I don't understand how I can apply that logic to the ArrayList. Sorry for the ignorance, I am fairly new to Java.
Re: toString method call issues
How did you get the 300+ lines of code you posted?
When not sure what a method for a class does, write a small test program, maybe 20 lines, and use the method to see what it does.
Create an ArrayList, add some objects (Strings are easy) and then try both get() and index() to see what they do.
Re: toString method call issues
I wrote all of it minus the Set class and getClassName method which our instructor provided for us.
I suppose I'm just drawing a blank, I will try everything I know of and see what works.
Re: toString method call issues
Figured it out.
Code:
if(theClassName.equals(theList.get(i).getClass().getName()))
Works fine, thank you.
Re: toString method call issues