Java Builder Object Printing Null

147 Views Asked by At

I have created a Person, class and a Professor class that both use the Builder Pattern to create objects. The Professor class takes a Person object as an argument in its constructor. I am trying to use both classes together, but when I attempt to print out a professor, get the following output: null null (instead of Bob Smith).

Here's what I tried so far:

Person:

public class Person {
    private String firstname;
    private String lastname;
    private int age;
    private String phoneNumber;
    private String emailAddress;
    private char gender;

    public Person(){}

    // builder pattern chosen due to number of instance fields
    public static class PersonBuilder {
        // required parameters
        private final String firstname;
        private final String lastname;

        // optional parameters
        private int age;
        private String phoneNumber;
        private String emailAddress;
        private char gender;

        public PersonBuilder(String firstname, String lastname) {
            this.firstname = firstname;
            this.lastname = lastname;
        }

        public PersonBuilder age(int age) {
            this.age = age;
            return this;
        }
        public PersonBuilder phoneNumber(String phoneNumber) {
            this.phoneNumber = phoneNumber;
            return this;
        }
        public PersonBuilder emailAddress(String emailAddress) {
            this.emailAddress = emailAddress;
            return this;
        }
        public PersonBuilder gender(char gender) {
            this.gender = gender; 
            return this;
        }

        public Person build() {
            return new Person(this);
        }
    }

    // person constructor
    private Person(PersonBuilder builder) {
        this.firstname = builder.firstname;
        this.lastname = builder.lastname;
        this.age = builder.age;
        this.phoneNumber = builder.phoneNumber;
        this.emailAddress = builder.emailAddress;
        this.gender = builder.gender;

    }

    @Override
    public String toString() {
        return this.firstname + " " +  this.lastname;
    }
}

Here's the Professor class:

package com.example.hardcodedloginform;

import java.util.List;

public class Professor extends Person{
    private Person professor;
    private double salary;
    private String courseTaught;
    private List<Student> students;
    private int professorID;


    public static class ProfessorBuilder {
        // required fields
        private Person professor;
        private int professorID;

        // optional fields
        private double salary;
        private String courseTaught;
        private List<Student> students;


        public ProfessorBuilder(Person professor, int professorID) {
            this.professor = professor;
            this.professorID = professorID;
        }



        public ProfessorBuilder salary(double salary) {
            this.salary = salary;
            return this;
        }
        public ProfessorBuilder courseTaught(String courseTaught) {
            this.courseTaught = courseTaught;
            return this;
        }
        public ProfessorBuilder students(List<Student> students) {
            this.students = students; 
            return this;
        }

        public Professor build() {
            return new Professor(this);
        }
    }

    private Professor(ProfessorBuilder builder) {
        this.salary = builder.salary;
        this.courseTaught = builder.courseTaught;
        this.students = builder.students;
    }

    @Override
    public String toString() {
        return "" + super.toString();
    }
}

And here is the Main class where I try to print out a professor object:

public class Main {

    public static void main(String[] args) {
        Person profBobs = new Person.PersonBuilder("Bob", "Smith")
                .age(35)
                .emailAddress("[email protected]")
                .gender('M')
                .phoneNumber("818-987-6574")
                .build();
        Professor profBob = new Professor.ProfessorBuilder(profBobs, 12345)
                .courseTaught("MAT101")
                .salary(15230.01)
                .build();
        System.out.println(profBob);
    }

}

I would like the printout in the console to be "Bob Smith", but what I am seeing is: null null. I checked and found that the Person object profBobs is, in fact, created properly and does print out the name "Bob Smith" when I attempt to print it the same way. I don't know why my Professor prints: null null.

1

There are 1 best solutions below

0
Konrad Rudolph On BEST ANSWER

Your Professor constructor fails to initialise any member fields of its base class.

There are multiple ways to solve this. One solution has ProfessorBuilder extend PersonBuilder:

public class Professor extends Person {
    // Remove the `person` field! A professor *is-a* person, it does not *contain* it.
    private double salary;
    private String courseTaught;
    private List<Student> students;
    private int professorID;

    public static class ProfessorBuilder extends Person.PersonBuilder {
        // required fields
        private int professorID;

        // optional fields
        private double salary;
        private String courseTaught;
        private List<Student> students;

        public ProfessorBuilder(Person professor, int professorID) {
            super(professor);
            this.professorID = professorID;
        }

        // …
    }

    private Professor(ProfessorBuilder builder) {
        super(builder);
        this.salary = builder.salary;
        this.courseTaught = builder.courseTaught;
        this.students = builder.students;
    }
}

For this to work you also need to mark the Person constructor as protected rather than private.

Furthermore, your Professor.toString method implementation made no sense: it essentially just called the base class method, so there’s no need to override it. And prepending the empty string does nothing.