When is a constructor called in nested classes (Java) - java

I was trying to understand how constructors work and came up with two questions. I have two classes, one for an address and another for a person. the Person class has two Address objects in it. Here is a simplified example of what I'm doing:
private class Person{
private String name;
private Address unitedStates;
private Address unitedKingdom;
Person()
{
this.name = "lary"
}
Person(String n)
{
this.name = n;
//Can I call Address(string, string) here on unitedStates and unitedKingdom?
}
}//end of person class
private class Address{
private String street;
private String country;
Address()
{
this.street = "1 Washington sq";
this.country = "United States";
}
Address(String s, String c)
{
this.street = s;
this.country = c;
}
}
}
If I leave Person() as is, will it fill the the values for unitedStates and unitedKindom with "1 Washington sq" automatically?
And
Can I pass arguments for the Address object where I left that comment in the example?

Fields of an object will always automatically be set with a default value, if not initialized by yourself. The value depends on the data type of the field (see here https://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html). The default value of a field that represents an object is null.
Since you didn't initialize the fields unitedStates and unitedKingdom, their values will be null. What you can do is initializing the fields inside the Person constructors:
Person()
{
this.name = "lary";
this.unitedStates = new Address();
this.unitedKingdom = new Address();
}
Person(String n)
{
this.name = n;
this.unitedStates = new Address("myStreet", "myCountry");
this.unitedKingdom = new Address();
}
You could also use one constructor in another with the keyword this. Note that I have added a third constructor that is called by the other constructors:
Person(String n, Address unitedStates, Address unitedKingdom)
{
this.name = n;
this.unitedStates = unitedStates;
this.unitedKingdom = unitedKingdom;
}
Person(String n)
{
this(n, new Address("myStreet", "myCountry"), new Address());
}
Person()
{
this("lary", new Address(), new Address());
}

Address field are just initialized as null. you have to assign it an Address instance, in User constructor for example, like
unitedStates = new Adress();
wich will call the Address's constructor with no parameters.

Related

trying to call superclass method in subclass

Probably a pretty noob question, but I cant figure it out. I have a class Person to store a name that is input from the keyboard
public class Person {
private String firstName;
private String lastName;
public Person()
{
firstName = "";
lastName = "";
}
public Person(String first, String last)
{
setName(first, last);
}
public String toString()
{
return(firstName + " " + lastName);
}
public void setName(String first, String last)
{
firstName = first;
lastName = last;
}
public String getFirstName()
{
return firstName;
}
public String getLastName()
{
return lastName;
}
}
I am trying to call the toString method in a subclass called Patient
public class Patient extends Person {
private int patientID, patientAge;
public Patient()
{
patientID = 0; //for a different part of the class that works
patientAge = 0;
}
#Override
public String toString()
{
return ("Patient Name: "+super.toString());
}
}
I cannot get it to output the name in main when I call the toString method from the Patient class, but when I tested it, it output the name when I call the toString method from the Person class.
The method call in main looks like Patient pnt = new Patient(); System.out.print(Pnt.toString());
it prints out in the console "Patient Name: ". Any feedback on what I am doing wrong or ideas on how to get it to work
Here:
public Person()
{
firstName = "";
lastName = "";
}
Your subclass is missing a reasonable call to a super class constructor. So when you instantiate your Patient objects, the above constructor is used, and all patients end up with "" as first and last name!
When you create a Patient, then a patient should have a name, too! But your constructor in Patient only sets the Patient related fields. And implicitly, the default super constructor is called. Therefore the Person fields are all set to be empty strings!
A much better approach would look like this:
class Person {
private final String firstName;
... lastName
public Person(String firstName, String lastName) {
this.firstName = firstName;
...
and then
class Patient extends Person {
private final int patientID;
public Patient(int patientID, String firstName, String lastName) {
super(firstName, lastName);
this.patientID = patientID;
)
Why is that better: names and IDs don't change (normally). There is no point in having getters for them. You create your object once, and then that data is fixed! There is also no point in having that default constructor in Person. A person with empty names doesn't make sense. Thus: don't create a class that allows you to create "invalid" objects. Your classes model reality. There are no real people without names!
And one other hint: use #Override when overriding methods, so that the compiler can tell you when you get something wrong!
if the problem is to output the name in main when you call the toString method from the Patient class, I think the code bellow will help you.
have you tried to construct the Patient object like this?
public static void main(String[] args) {
Patient p = new Patient();
System.out.println(p.toString());
}
Actually I do not see problem in your code.
Person person = new Person();
person.setName("aa", "bb");
System.out.println(person); // aa bb
Patient patient = new Patient();
patient.setName("cc", "dd");
System.out.println(patient); // Patient Name: cc dd
I think that you set name wrong pr use not correct reference. Check it.
You don't have any constructor for your PATIENT subclass. You don't set any firstName or lastName to any patient.
To keep familiar constructor as you used in your parent class, tru to use:
public Patient() {
super("default_firstName", "default_lastName");
this.patientID = 0;
this.patientAge = 0;
}
public Patient(String firstName, String lastName, int patientAge) {
super(firstName, lastName);
this.patientID = 0; //can be implemented some method for automatically setting numbers
this.patientAge = patientAge;
}
This way you always get firstName and lastName even if constructor will be called empty.
According to you toString method, it's correct and it call super class method:
#Override
public String toString()
{
return("Patient name is "+super.toString());
}
But notice that you return STRING value so to make it visible on the screen remember to use:
System.out.println(patient.toString());
Then it will be visible :)
I have added some comments and code in your Person class that should fix your issues.
public class Person {
private String firstName; //store the first name
private String lastName; //sore the last name
//initialize firstName and lastName to an empty string
public Person() {
firstName = "";
lastName = "";
}
//set firstname and lastname according to the parameters.
public Person(String first, String last) {
//setName(first, last); remove this crap.
// Use the contructor properly when initialize your person object. Like this:
this.firstName = first;
this.lastName = last;
}
//method to output the first name and last name
#Override
public String toString() {
return (firstName + " " + lastName);
}
//method to set firstName and lastName according to the paramters
public void setName(String first, String last) {
//
firstName = first;
lastName = last;
}
}

Static Suggestion. What am I doing wrong?

So I am trying to pass an ArrayList to my main method, but eclipse is telling me I need to change my arraylist to a static. I know I'm doing something wrong but I can't figure it out.
ArrayList<Patient> pList = Doctor.getPatientList();
this is the call I have in my main method.
public class Doctor {
public ArrayList<Patient> patientList = new ArrayList<Patient>();
}
public void loadPatientData() {
BufferedReader read2 = null;
try {
read2 = new BufferedReader(new FileReader("data/patient_list.txt"));
String line;
while ((line = read2.readLine()) != null) {
line = read2.readLine();
if (line == null) {
break;
}
String[] lineValues = line.split(","); //split the string on this value into array
String firstName = lineValues[0];
String lastName = lineValues[1];
String address = lineValues[2];
String city = lineValues[3];
String state = lineValues[4];
String zip = lineValues[5];
String ssn = lineValues[6];
String genderNeedsConvert = lineValues[7];
String weightNeedsDouble = lineValues[8];
String heightNeedsDouble = lineValues[9];
String symptomsNotReady = lineValues[10]; // these need to be broken up further (using semicolons)
char gender = genderNeedsConvert.charAt(0);
double weight = Double.parseDouble(weightNeedsDouble);
double height = Double.parseDouble(heightNeedsDouble);
Patient patient = new Patient(firstName, lastName, address, city, state, zip, ssn, gender, weight, height, symptomsNotReady);
patientList.add(patient); // must be of patient type.
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (read2 != null) {
try {
read2.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public ArrayList<Patient> getPatientList() {
return patientList;
}
This is a shortened version of my Doctor class.
public class Patient {
private String patientID;
private String firstName;
private String lastName;
private String ssn;
private char gender;
private String address;
private String city;
private String state;
private String symptoms;
private String zip;
public ArrayList<Diagnosis> diagnoses = new ArrayList<Diagnosis>();
//private Diagnosis diagnoses = new Diagnosis(0, null);// new diagnoses called as Diagnoses datatype
public ArrayList<Medication> newMedication = new ArrayList<Medication>();
//private Medication newMedication = new Medication(0, null);// newMedication called as medication datatype
ArrayList<String> symptom = new ArrayList<String>();
ArrayList<String> symptomCompare = new ArrayList<String>();
private double weight;
private double height;
int k = 0;
public Patient(String firstName,String lastName,String address,String city, String state,String zip,String ssn,char gender,double weight,double height,String symptoms){
this.firstName = firstName;
this.lastName = lastName;
this.ssn = ssn;
this.gender = gender;
this.weight = weight;
this.height = height;
this.address = address;
this.city = city;
this.state = state;
this.symptoms = symptoms;
this.zip = zip;
this.patientID = ssn.replace("-", ""); // removes dashes from ssn and sets the value to patientID
this.patientID = this.patientID.replace(" ", ""); //removes spaces from patientID
this.patientID = this.patientID + this.firstName.substring(0, 1) + this.lastName.substring(0, 1);
}
and above is the shortened patient class. I've been sitting here for a few hours trying different things but it keeps telling me to change the getPatientList() method to static. What am I doing wrong?
Doctor.getPatientList() is the syntax for calling a static method, since Doctor is a class name.
If you want to call an instance method (and getPatientList() is currently an instance method), you should call it using an instance of a Doctor:
Doctor doctor = new Doctor();
ArrayList<Patient> pList = doctor.getPatientList();
What ever variables/method you declare as static as known as class members. Strictly speaking, they belongs to the class instead of being an object's attribute.
When a variable is static, it exist even before the object is created. So what does that means?
Static methods can access static variables/methods.
Static methods cannot access non-static variables/methods. (because they don't exist)
If you want to let static methods access non-static variables/methods. One of the ways is to instantiate(create) the object which the method/variable you wanted to access belong to that object first.
The reason you need to instantiate first before you can access it is because you want to make them exist first. Class itself is only a blueprint, you need to create an object (to make them exist) before you can interact with it.
Example:
Doctor doctor = new Doctor();
ArrayList<Patient> list = doctor.patientList;
//Only possible if patientList is not private
If patientList is private in Class Doctor, you need to use a getter:
Doctor doctor = new Doctor();
ArrayList<Patient> list = doctor.getPatientList();
//getPateientList is a method in Doctor class
Use static modifier with public ArrayList<Patient> getPatientList():
public static ArrayList getPatientList()
You are invoking this method on class Doctor, and thus this method must be declared static.
You have to declare the class object first then call its function. Like:
Doctor doc = new Doctor();
doc.getPatientList();
Else you will have to make the function static.
In the Doctor class, the patientList, loadPatientData() and getPatientList() members are all "instance" members of the class Doctor, which means you need an instance or an object of the type Doctor.
So, to call getPatientList(), you need to create a Doctor object as below:
Doctor doc = new Doctor();
doc.getPatientList();
static members are accessed using the name of the class where as instance members are accessed using the name of the object.

java - Editing child in list of parents

I've got an abstract class called customer and another classe called payCust that extends this abstract class. There is another client class that initializes a list of customers.List<Customer> custList = new ArrayList<>();
the customer class has a constructor as follows:
public Customer(String name, String email, String mag) {
this.CusEmail = email;
this.CusName = name;
this.magazine = mag;
}
payCust has the following constructor:
public PayCust(String _name, String _email, String _accountType, String _custMag) {
super(_name, _email, _custMag);
this.accountType = _accountType;
}
all the variables have public get and set methods. e.g.
public void setName(String name) {
this.CusName = name;
}
public String getName() {
return this.CusName;
}
my question is that if the custList had a PayCust added to it. how can i edit the accountType of a customer from that list?
note: email is unique to every customer
You will have to check the instance type of the object within the ArrayList and cast it for usage.
Something like this, for example:
for (Customer c : custList){
if(c instanceof PayCust){
PayCust pc = (PayCust) c;
pc.getAccountType();
}
}
You would have to cast it to a PayCust (assuming you know for a fact that it's a PayCust):
PayCust example = (PayCust) custList.get(0);
String accountType = example.getAccountType ();
...

Having troubles creating this object

I'm very new to java, and trying to grasp making an object with two different values.
I'm trying to create a Customer object called customer, with the initial values of 1 and cust1, and then display the customer object to the output with toString()
Thanks for any help in advance.
Here's what I have currently.
public class Customer {
private int id;
private String name;
public Customer(int id, String name) {
this.id = id;
this.name = name;
Customer customer = new Customer(1, "cust1");
}
You have no entry point to your program, which should look like this in your class
public static void main(String[] args)
{
//objects created here
}
You also create a Customer object as a member of your Customer class which means every Customer object contains another.
You can't set Customer members like this
Customer customer = new Customer(); //you also don't have a no argument constructor
customer = 1; //how would it know where to put this 1?
customer = cust1; //same as above
it would be like this (if they were in the right place, as mentioned above)
Customer customer = new Customer(); //if using this method you will need a no argument constructor
customer.id = 1;
customer.name = cust1;
or like this
new Customer(1,"cust1");
In Summary
You need an entry point
You are creating Customer with a no argument constructor but you only have one constructor which has two arguments
You are -for some reason- creating a Customer inside every Customer
You are not setting members of your Customer object in the correct (or even in a valid) way
Don't create a new object instance within a classes constructor — this will result in a StackoverFlowException.
public class Customer {
private final int id;
private final String name;
public Customer(int id, String name) {
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
}
In a separate class you can simply create a new instance by using
Customer customer = new Customer(1, "Name");

Java, How do i use add a string and an integer to an array

This is the array code I have so far:
ArrayList<Data> arrl = new ArrayList<Data>();
arrl.add("Tim", 23);
Need to know how to an integer and a string to the array.
For Example:
names: and ages:
Tim 23
Max 56
Clare 43
I know how to add integers OR strings to array-lists but i can't figure how to incorporate both in the same array.
Your list is taking objects of type Data. So, create a Data class that contains a String for the name and int for the age. Create a Data object for each entry you want and add it to your arrl list.
public class Data {
private String name;
private int age;
/**
* Constructor
*/
public Data(String name, int age) {
this.name = name;
this.age = age;
}
// Getters and Setters go here.
}
In this example I used a constructor to allow easy construction of a Data object with a name and age.
List<Data> arrl = new ArrayList<Data>();
arrl.add(new Data("Tim", 23));
You could have a class Person for instance, where you save the name and age of a person.
Then, you have a ArrayList of Person, and you can store and access that information.
ArrayList is a class that use generics, it means type-safety, so when you declare a class that use generic in its class definition you have to declare the type when making the instance.
If you want to store Stringobjects declare ArrayList in this way:
ArrayList<String> saveString = new ArrayList<String>
You can make a class Person with those instance variables and resolve your problem.
For example:
public class Person {
private String name;
private int age;
public Person(String name,int age){
this.name = name;
this.age = age;
}
}
And then you can use in this way:
ArrayList<Person> people = new ArrayList<Person>();
people.add(new Person("Luis Alberto",15));
Your arraylist is made for Data objects that means you have to create Data object to put it there, `this is what i mean by that arrl.add(new Data("Tim",44));
Make sure that you have class Data with constructor for string and int
Something like this:
public class Main {
public static void main(String[] args) {
ArrayList<Person> arrl = new ArrayList<>();
arrl.add(new Person("Tim", 23));
}
}
class Person {
private String name;
private int age;
Person (String name, int age) {
this.name = name;
this.age = age;
}
}
I think the best approach is what is proposed by Wabs and Ashot Karakhanyan. But if your need, is to have the name and age as different items of your list, you can use the following:
List<Object> arrl = new ArrayList<Object>();
arrl.add("name");
arrl.add(23);

Categories