This question already has answers here:
How do I print my Java object without getting "SomeType#2f92e0f4"?
(13 answers)
Closed 7 years ago.
I created a program with a new class called Student that sets and gets different variables such as name, GPA, if they are enrolled and when they are enrolled (this is a String, it is intended to be). The problem is that when I try to store the information into an array and/or array list and print it I get the hash code printed instead of the information. The program is not entirely complete, but I am trying to address the hash code issue first. If you could assist I would much appreciate. Thank you in advance!
Student st = new Student();
System.out.println(st.getName());
Student1();
Student st1 = new Student("John");
}
public static void Student1() {
System.out.println("Enter the data for student 1 :");
Student st = new Student();
Scanner keyboard = new Scanner(System.in);
String name = keyboard.next();
double GPA = keyboard.nextDouble();
boolean enrolled = keyboard.nextBoolean();
String date = keyboard.next();
for (int i =0; i<5; i++){
Student newStudent = new Student();
newStudent.setName(name);
newStudent.setGPA(GPA);
newStudent.setEnrolled(enrolled);
newStudent.setDate(date);
ArrayList <Student> strList = new ArrayList<Student>();
Student student[] = new Student[5];
newStudent.getName();
student[i] = newStudent;
strList.add(newStudent);
System.out.println(student[i]);
}
Student Class
public class Student {
private String name;
private double gpa;
private boolean enrolled;
private String enrollDate;
public Student() {
this.name = "";
this.gpa = 0.0;
this.enrolled = false;
this.enrollDate = "none";
}
public Student(String name1) {
this.name = name1;
this.gpa = 0.0;
this.enrolled = false;
this.enrollDate = "none";
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
public void setGPA(double gpa) {
this.gpa = gpa;
}
public double getGPA() {
return this.gpa;
}
public void setEnrolled(boolean enrolled) {
this.enrolled = enrolled;
}
public boolean getEnrolled() {
return this.enrolled;
}
public void setDate(String date) {
}
}
This is because you are putting a student object into the array:
Student student[] = new Student[5];
newStudent.getName();
student[i] = newStudent;
strList.add(newStudent);
System.out.println(student[i]);
Here when you are printing, you are not printing the students name, but rather the object itself. Whenever you do a System.out.println on an object the hashcode is returned.
Was this your problem?
If you want a String representation of an object, this object must implement toString(). If you don't the default in the JVM is to print the hash code.
If you want to print a specific field of your object, you should explicitly print that field, through a method if necessary; like System.out.println(student[i].getName());
If you are trying to print a whole array, you should use Arrays.toString().
please override toString() method as currently it is only printing by default implementation of toString() method from Object class which is set to current object's hashcode().
This kind of printing will get the instance address and not a print of it.
Because you want to print a reference type, the VM doesn't know how you want it display or whatever or not some of the fields aren't for printing.
It's apt to you, Overriding "public String toString()" method and implement your own format.
Related
I hope you are able to help me.
My question is:
When passing an instance of an object that is in an arraylist, and I pass that arraylist to another class, how do I access it's atributes?
I can access the attributes before passing it to another class.
The "Main" class, passes on the data, to the "Employees" class.
Employees employees = new Employees();
employees.addEmployee("Orlando", "Silva", 111111111, "St. King's Street", 111111111, 11111111111111L, employees.getMinimumWage(), employees.getDayShift());
employees.addEmployee("Rui", "Guilherme", 111111111, "St. King's Street", 111111111, 11111111111111L, employees.getMinimumWage(), employees.getNightShift());
employees.addEmployee("Marco", "Alberto", 111111111, "St. King's Street", 111111111, 11111111111111L, employees.getMinimumWage(), employees.getNightShift());
The "Employees" class receives the data, adds it to an array, and from that array goes to the "AllStaff" class
Notice, that I have access to the atributes, in the method "addToAllStaff()"
public class Employees {
// Atributes
public String name;
private String lName;
private int nID;
private String address;
private int phNum;
private long nSocialSecNum;
private double minimumWage = 740.83;
private double employeeWage;
private String dayShift = "Day shift", afternoonShift = "Afternoon shift", nightShift = "Night shift";
private String shift;
private ArrayList<Employees> employeesArrayList = new ArrayList<Employees>();
private AllStaff allStaff = new AllStaff();
//---------------------
// Constructors
public Employees(){
}
public Employees(String name, String lName, int nID, String address, int phNum, long nSocialSecNum, double minimumWage, String shift){
this.name = name;
this.lName = lName;
this.nID = nID;
this.address = address;
this.phNum = phNum;
this.nSocialSecNum = nSocialSecNum;
this.employeeWage = minimumWage;
this.shift = shift;
//----------------
extraWage();
}
//---------------------
public void addEmployee(String name, String lName, int nID, String address, int phNum, long nSocialSecNum, double minimumWage, String shift){
Employees employee = new Employees(name, lName, nID, address, phNum, nSocialSecNum, minimumWage, shift);
employeesArrayList.add(employee);
addToAllStaff();
}
void addToAllStaff(){
System.out.println("(Class Employees) employees size: " + employeesArrayList.size());
for (int i = 0; i < employeesArrayList.size(); i++){
System.out.println("Employee names: " + employeesArrayList.get(i).getName());
System.out.println("Employee names: " + employeesArrayList.get(i).name);
}
allStaff.addEmployees(employeesArrayList);
}
}
In the class "AllStaff", is where I don't have access to the attributes
public class AllStaff {
static ArrayList <AllStaff> employeesArrayList;
public AllStaff(){
}
public void addEmployees(ArrayList listOfEmployees){
System.out.println("List of employees size: " + listOfEmployees.size());
for (int i = 0; i < listOfEmployees.size(); i++){
System.out.println("Employee names: " + listOfEmployees.get(i).getName());
System.out.println("Employee names: " + listOfEmployees.get(i).name);
}
this.employeesArrayList = listOfEmployees;
}
For the whole code, please visit this link: https://github.com/OrlandoVSilva/test-to-github/tree/master/test-to-github/src/mercado
I hope this question has everything you need.
Thanks
When using a List (or any object that can be generic), it's a good practice to specify the type of List you're dealing with. In your case, the method addEmployees(ArrayList listOfEmployees) takes in parameter an ArrayList, which could be an ArrayList of literally any object. It could be an ArrayList of Employees, Strings, Integers, whereas you just want it to be an ArrayList of Employees.
the solution is to change your ArrayList into a ArrayList<Employees> listOfEmployees
public void addEmployees(ArrayList<Employees> listOfEmployees){
System.out.println("List of employees size: " + listOfEmployees.size());
for (int i = 0; i < listOfEmployees.size(); i++){
System.out.println("Employee names: " + listOfEmployees.get(i).getName());
//The above should work just fine :)
System.out.println("Employee names: " + listOfEmployees.get(i).name);
//This one will work too as the "name" attribute is public but as you have a getName() method, you probably should make it private :D.
}
this.employeesArrayList = listOfEmployees;
}
To explain it quickly without too much details, when you're using a List object, you must specify the List's type by putting <> around it. If you don't, the default type is Object which is the parent of every types in java.
Also, i guess your static ArrayList <AllStaff> employeesArrayList; is meant to be your list of employees. So replacing it with static ArrayList <Employees> employeesArrayList; seems to be what you want to do :D
You missed generics type in AllStuffs addEmployees() method argument. That is the problem. It should be like this:
public void addEmployees(ArrayList<Employees> listOfEmployees){
Problem:
I'm trying to figure out how to access the Student Array class in order to create four entries for each Student object, but I'm not sure how to do so, while also allowing the program to create more than just one Student.
public class ClassRoster<T> {
public static void main(String[]args) {
ClassRoster<Student> classroster = new ClassRoster<Student>();
Scanner keyboard = new Scanner(System.in);
System.out.println("Add/Drop/Search?");
String action = keyboard.nextLine();
boolean done = false;
Object temp, c, d, e;
int fresh, soph, jun, sen;
Student test = new Student();
while(!done) {
if(action.equalsIgnoreCase("Add"))
{
int counter = 0;
System.out.print("Enter Student ID");
temp = test.setID(keyboard.nextInt());
System.out.println("First name?");
c = test.setFirstName(keyboard.nextLine());
System.out.println("Last name?");
d = test.setLastName(keyboard.nextLine());
System.out.println("Academic Level?");
e = test.setLevel(keyboard.nextLine());
...
}
And I have another class called Student, where there are four different data entries (ID, FirstName, LastName, Academic Level).
I'm not sure how to access the object which I have created in the correct way. It just gives me an error in this Driver class, and I don't know how to correctly access the array bag.
but I'm not sure how to do so while also allowing the program to create more than just one Student
Currently you are only creating one specific instance of student with Student test = new Student(); To actually create more than one student, you will have to iterate the whole process of reading all four data entries (ID, FirstName, LastName, Academic Level). Instead of having to initialize the fields (your four data entries) with specific set methods, I would recommend you letting the Student class initialize them with the class constructor. Meaning the Student class should look something like this:
public class Student{
private final int ID;
private final String firstname;
private final String lastname;
private String level;
public Student(int ID, String firstname, String lastname, String level){
this.ID = ID;
this.firstname = firstname;
this.lastname = lastname;
this.level = level;
}
ID, firstname and lastname are set to final as you foresee them not to change. However the academic level is ought to change and therefore is not set to final. Now that you have set up a constructor for your Student class, we can get to how to allow the program to insert multiple students at once.
public static void main(String[]args) {
ClassRoster<Student> classroster = new ClassRoster<Student>();
Scanner keyboard = new Scanner(System.in);
System.out.println("Add/Drop/Search?");
String action = keyboard.nextLine();
boolean done = false;
while(!done) {
if(action.equalsIgnoreCase("Add")) {
System.out.print("Enter Student ID");
int ID = keyboard.nextInt();
System.out.println("First name?");
String firstname = keyboard.nextLine();
System.out.println("Last name?");
String lastname = keyboard.nextLine();
System.out.println("Academic Level?");
String level = keyboard.nextLine();
Student student = new Student(ID, firstname, lastname, level);
//we have now created a new instance of Student, now we have to save it in your classroster
classroster.add(student);
}
System.out.println("Next action?");
action = keyboard.nextLine();
if(action.equals("done") done = true; //if you write 'done', your loop will finish executing
}
I don't know about your implementation of classroster, but I assume you have implemented it with some kind of list or map, which is why I call the add(Student s) method after creating an instance of Student. To actually then access all students, you will have to implement a method in classroster that returns the saved list of classroster and then iterate through the returned list in the main loop. To actually see what the students look like, you will also have to implement methods for the student instances to for example print out their full names.
I see that you are having a little trouble with arrays, maps and lists as you don't know how to access your students yet. I recommend you reading up on the difference between these three data structure types and simply try to implement them in a small example to see how they work.
I am doing the question below:
A university wishes to keep student records in such a way that there are no
duplicate student record for any student. Student details are as follows: national
ID card number, surname, first name, address and programme of study.
i. Write a class named Student which will allow the creation of objects with
the above-mentioned attributes. Only the implementation of the
constructor is required.
ii. Amend the class above to make all the Student objects orderable based
on their surname, in case two students have the same surname, their Id
card number will be used to order them.
iii. Write code to declare a suitable data structure to store the records
iv. Write code to add a student object, S1, to the list.
v. Write code to ask the user for an integer, n, and then allows insertion of n
Students objects in the data structure.
vi. Write code to display all the details of all the Student objects from the data
structure.
Here is what I have come up with so far:
import java.util.Comparator;
import java.util.Scanner;
import java.util.SortedSet;
import java.util.TreeSet;
public class Student {
private String nID;
private String lname;
private String fname;
private String address;
private String pos;
public Student(String nID, String lname, String fname, String address, String pos){
this.nID=nID;
this.lname=lname;
this.fname=fname;
this.address=address;
this.pos=pos;
}
public Student() {
// TODO Auto-generated constructor stub
}
final static Comparator<Student> nameComparator=new Comparator<Student>(){
public int compare(Student A, Student B){
if((A.lname.compareTo((B.lname)))<0){
return -1;
}
else if(A.lname.compareTo(B.lname)>0){
return 1;
}
else{
return (A.nID.compareTo(B.nID));
}
}
};
public String toString(){
return "National ID: "+ nID+ " First Name: "+ fname+ " Last Name: "+ lname+ " Address: " +address+ " PoS"+pos+"\n";
}
public static void main(String[] args){
Scanner sc= new Scanner(System.in);
SortedSet<Student> names= new TreeSet<Student>(nameComparator);
int num;
System.out.println("Enter the number of students");
num=sc.nextInt();
Student a = new Student("daaa", "Jam", "Jick", "iiii", "ooooo");
Student b = new Student("bba", "Aarav", "Gash", "iiii", "pooo");
Student c = new Student("ccaa", "Jam", "Kick", "iiii", "ooooo");
names.add(a);
names.add(b);
names.add(c);
for(int i=0; i<num; i++){
names.add(new Student());
}
for(Student i: names){
System.out.println(i.toString());
}
}
}
I am not sure of how to do the 5th part of the question or if I understood it well.
When I execute this program I get null point exception at the name comparison and the add method in the for loop. I know the null pointer exception is because I have not added any arguments in the student object names.add(new Student()); but I want to find the right way of doing it.
This
for(int i=0; i<num; i++){
names.add(new Student());
}
will always add Student having all "null" fields. Use your other constructor instead:
public Student(String nID, String lname, String fname, String address, String pos){
I need to have a class with two constructors, one with and one without arguments. The one without is supposed to call the other with Randomized arguments, so not default ones.
Here is some sample code:
public Human(int ageIn, String nameIn){
this.name = nameIn;
this.age = ageIn;
}
public Human(){
String[] names = {"Peter", "Olof", "Alva", "Sanna", "Carl", "Illona"};
double random = Math.random();
int nameIndex = (int)(names.length*random+0.5);
String name = names[nameIndex];
random = Math.random();
int age = (int)(100*random+0.5);
this(age, name);
}
The thing that makes this hard is that this() has to be in the beginning of a constructor, but I have to define and figure out name and age before I can call the first constructor with them.
Is there any way around this?
You can make static methods which make these random values. Then on line 1 of your constructor you can call:
public Human(){
this(getRandomAge(), getRandomName());
}
Alternatively you could create a factory method to create a 'random' Human:
public class MyProgram {
public static void main(String[] args) {
Human someRandomStranger = Human.createRandomHuman();
//...
}
}
public class Human {
public Human(int ageIn, String nameIn){
this.name = nameIn;
this.age = ageIn;
}
// ...
public static Human createRandomHuman(){
String[] names = {"Peter", "Olof", "Alva", "Sanna", "Carl", "Illona"};
double random = Math.random();
int nameIndex = (int)(names.length*random+0.5);
String name = names[nameIndex];
random = Math.random();
int age = (int)(100*random+0.5);
return new Human(age, name);
}
}
This would keep your constructors clear from stuff that shouldn't be there in the first place.
A default constructor that randomly assigns values to it's fields might be accidentially called in your code and create unwanted results.
A properly named factory method on the other hand would help prevent such mistakes and clearly communicate your intention.
How about something like this?
public class Human {
public Human() {
this(null, -1);
}
public Human(String name, int age) {
if(name == null) {
name = //your random name generation code
}
if(age == -1) {
age = //your random age generation code
}
this.name = name;
this.age = age;
}
}
Don't mix concerns. A Human should not care about choosing a random name based on a predefined set of names nor compute a random age !
I would rather delete the no-arg constructor (except if you have one defined value for a name and for an age, but it seems that it's not your case) and extract this logic outside of Human, typically in a HumanFactory.
I created a constructor with methods to create "student" objects and part of it is supposed to assign a student number to each student and increase that number by one with each student created.. mine aren't increasing.
this is the constructor
String firstNameInput;
public Student(String fName, String lName, String maj, double gpa)
{
this.firstName = fName;
this.lastName = lName;
this.major = maj;
this.gpa = gpa;
sNumber = 1234567;
}
Here's the method that returns the student number
public int getsNumber() {
return sNumber + count++;
}
here's my toString method
public String toString()
{
return sNumber + " " + firstName + " " + lastName + " " + major + " " + gpa;
}
and here's where a student gets added.
public static void main(String[] args) {
ArrayList<Student> list = new ArrayList<>();
Student s1 = new Student("Terra", "Ramey", "EE", 3.4);
list.add(s1);
Let me know if I need to include all of my code to figure out where the problem is, but I think it's with one of these
count++ is located inside the method getsNumber(). There are two problems with that:
The method is never called (at least, not in the code you've shown), hence you don't see the number increase.
You would presumably call this method whenever you want to know the student number of a student - so every time you try to figure that out, the number will increase.
Since this looks like homework, I won't tell you where to place count++, but here's a strong hint: which method is run each time a new student is created (and never otherwise)?
Also, see the other posters' advice about static (you haven't shown the declaration of count, so we can't tell if you're already using it). However, please make sure that you understand what static does and how a static variable is different from a nonstatic one (a lot of new programmers end up throwing static around, thinking it's magic and hoping it will solve their problems).
Add a static variable to the class. Something like the following :
private static int count = 0;
private int studentNumber;
Then in the constructor add the following :
public Student(String fName, String lName, String maj, double gpa)
{
this.firstName = fName;
this.lastName = lName;
this.major = maj;
this.gpa = gpa;
sNumber = 1234567;
count = count +1; // to keep the count
this.getStudentNumber = count;
}
Also add the following method to the Student class:
public int getStudentNumber(){
return this.studentNumber;
}
Then in your main you can access the count by :
Student student = new Student(//parameters);
System.out.println(Student.count);
System.out.println(student.getStudentNumber());
If you are allowed to use static fields to store the current count, I think you'll find adding a private static int currentCount to the class and then assigning the field sNumber = count++; might work for you.
Make sure that you use an AtomicInteger instead of just an int. That way, your constructor can be called by several threads simultaneously safely.