I'm a JAVA beginner.
I am trying to create a java phonebook which as three main classes
Contacts.java
Phonebook.java
Showphonebook.java
Contacts has two variables that are non-static, name and phone, which hold name and phone numbers of a person.
Then Phonebook is a class which holds the Phonebook objects and has a variable owner which is a string. So basically, the Phonebook object holds a owner and makes references to Contacts object to add contacts to it.
Then the final class Showphonebook is the class that makes a new Phonebook with owner and adds contacts to it.
Here is my code for above:
Contact.java
public class Contact {
private String name;
private String phone;
public Contact(String name, String phone) {
this.name = name;
this.phone = phone;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String toString() {
return name + ": " + phone;
}
}
Phonebook.java
import java.util.*;
public class Phonebook
{
private String owner;
public ArrayList<Contact> contacts = new ArrayList<Contact>();
public Phonebook(String owner) {
this.owner = owner;
}
public void addContact(Contact name) {
contacts.add(name);
}
public void show() {
System.out.println(owner + "'s phonebook");
for (Contact name : contacts) {
System.out.println(name);
}
}
/*public String findContactByName(String contactToSearch) {
for (Contact name : contacts) {
if (this.getName().equals(contactToSearch)) {
}
}
}*/
}
ShowPhonebook.java
public class ShowPhonebook
{
public static void main(String[] args) {
Phonebook phonebook1 = new Phonebook("Sam Johnson");
phonebook1.addContact(new Contact("Kelly Wong", "(02) 12345678"));
phonebook1.addContact(new Contact("Richard Jackson", "(02) 87654321"));
phonebook1.show();
}
}
I wanted to make a method in Phonebook.java which can SEARCH the phonebook to see if a contact exists , else return null.
How can I do this? I was thinking if I will use getName() method in Contact to pull out the NAME of each contact in the contacts ArrayList and compare it to the contactToSearch variable, but since getName() is non-static, how do I do it? I am confused because Contact holds the getName, but to reference that, I need an object, but my only object phonebook1 is in ShowPhonebook class, which I feel has to go through two classes to get there. Not sure how to do it.
Looking for guidance here!
First of all, welcome to stack overflow!
Now I'm assuming you are new to java hence confused about how references and this work in java. To get what you are asking, I would suggest following modification in the commented method-
public String findContactByName(String contactToSearch) {
for (Contact contact : this.contacts) { // changed "name" to "contact"; variable name should be aptly chosen
if (contact.getName().equals(contactToSearch)) {
// TODO: do your thing with "contact" variable
}
}
}
this refers to the current instance of the class. In your case, this will refer to the phonebook1 instance.
Related
So for example.
I have an ArrayList of people. Created through a people object that contains a name, address, age, etc.
How would I then add another list to that, allowing a unique list of hobbies for each person?
So I could have:
James, 32, England, (Football, Tennis)
Chloe, 21, Wales, (Art)
Tried a few things and struggling with it.
import java.util.ArrayList;
public class People {
int id;
String name;
ArrayList<String> hobbies;
public People(int id, String name, ArrayList<String> hobbies) {
this.id = id;
this.name = name;
this.hobbies = hobbies;
}
public People(String name) {
this.name = name;
}
public People() {
// TODO Auto-generated constructor stub
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#Override
public String toString() {
return "People [id=" + id + ", name=" + name + ", hobbies=" + hobbies + "]";
}
}
import java.util.ArrayList;
public class Runner {
public static void main(String[] args) {
// TODO Auto-generated method stub
ArrayList<People> arrayPeople = new ArrayList<>();
ArrayList<String> hobbies = new ArrayList<>();
hobbies.add("Football");
hobbies.add("Tennis");
arrayPeople.add(new People(1,"Paul", hobbies));
hobbies.add("Golf");
arrayPeople.add(new People(2,"James", hobbies));
System.out.println(arrayPeople);
}
}
This creates a hobby list that is the same for each person, not unique.
This creates a hobby list that is the same for each person, not unique.
That's because member hobbies in [Paul] People object has same value as member hobbies in [James] People object, since they are assigned the same value in method main of class Runner. Hence when you change hobbies variable, in method main of class Runner, you are changing for both Paul and James.
The simplest solution is to change the class constructor so that it creates a copy of the hobbies parameter and assigns the copy to the hobbies member:
public People(int id, String name, List<String> hobbies) {
this.id = id;
this.name = name;
this.hobbies = new ArrayList<>(hobbies);
}
However, I suggest that you add methods to class People to manipulate hobbies member, including:
addHobby for adding a hobby
removeHobby for removing a hobby
clearHobbies for removing all hobbies
getHobbies that returns a copy of hobbies (so that code that calls the method cannot change hobbies)
Below code demonstrates.
Note that you should always use the interface – in this case java.util.List – rather than the implementation – in this case ArrayList – in the API so that you can change class People without having to change its API. If you change the API of class People then all other classes that use class People – like class Runner in the code in your question – will need to be changed as well.
import java.util.ArrayList;
import java.util.List;
public class People {
private int id;
private String name;
private List<String> hobbies;
public People(int id, String name, List<String> hobbies) {
this.id = id;
this.name = name;
this.hobbies = new ArrayList<>(hobbies);
}
public People(int id, String name) {
this(id, name, new ArrayList<String>());
}
public People() {
this(0, "");
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void addHobby(String hobby) {
if (!hobbies.contains(hobby)) {
hobbies.add(hobby);
}
}
public void clearHobbies() {
hobbies.clear();
}
public List<String> getHobbies() {
return List.of(hobbies.toArray(new String[]{}));
}
public void removeHobby(String hobby) {
if (hobbies.contains(hobby)) {
hobbies.remove(hobby);
}
}
#Override
public String toString() {
return "People [id=" + id + ", name=" + name + ", hobbies=" + hobbies + "]";
}
public static void main(String[] args) {
List<People> arrayPeople = new ArrayList<>();
People paul = new People(1,"Paul");
paul.addHobby("Football");
paul.addHobby("Tennis");
People james = new People(2,"James");
james.addHobby("Football");
james.addHobby("Tennis");
james.addHobby("Golf");
arrayPeople.add(paul);
arrayPeople.add(james);
System.out.println(arrayPeople);
}
}
Running the above code prints the following:
[People [id=1, name=Paul, hobbies=[Football, Tennis]], People [id=2, name=James, hobbies=[Football, Tennis, Golf]]]
The question seemed unclear to me, however I assume that you created lists such as
[name,age,location]
However, this is not an object. If you create a person object, you can add features inside it. So that when you create a person object, then you will have access to add/edit new features. In your case, your features must be:
Name
Age
Location
List (Whatever you name it, type of it must be an arraylist).
To have a list of people:
class Person{
String name;
int age;
String Address;
...
}
and
ArrayList<Person>
For the people class, if you need each hobby in hobbies to be unique you can have a Set class to store hobbies.
class Person{
String name;
int age;
String address;
Set<String> hobbies;
...
}
If the order does not matter you can use HashSet To maintain the order you can use TreeSet or LinkedHashSet.
class person{
String name;
int age;
String address;
TreeSet<String> hobbies;
...
}
class Person{
String name;
int age;
String address;
LinkedHashSet<String> hobbies;
...
}
To add a hobby to a person.
String hobby = "a hobby";
person.add(hobby);
To add hobbies to a person;
String hobby1 = "hobby1";
String hobby1 = "hobby2";
...
Set<String> hobbies = new TreeSet(); // or Set<String> hobbies = new LinkedHashMap();
hobbies.add(hobby1);
hobbies.add(hobby2);
...
person.addAll(hobby);
For another person with the same hobbies, you need to copy the hobbies, then modifying the hobbies of the second person will not affect the hobbies of the first person.
Set<String> new_hobbies = new TreeSet(old_hobbies); // or new LinkedHashSet(old_hobbies);
another_person.addAll(new_hobbies);
In a nutshell I am trying for the first time to build a couple of Value Objects (VO's) and cannot resolve the this.name usage in my constructors.
I just discovered the concept of Value Objects from this article ("Convert Guard Clauses to Value Objects") and when trying to implement the sample code ran into a few problems where the author oversimplified the example. I have worked all of them out except for one last bug that is preventing the code from building with the following compiler messages:
Compilation failed due to following error(s).
Name.java:6: error: cannot find symbol
this.name = name;
^
symbol: variable name
PhoneNumber.java:10: error: cannot find symbol
this.phoneNumber = phoneNumber;
^
symbol: variable phoneNumber
2 errors
Below are the four class files of my project:
Event.java
public class Event {
public void registerVisitor (Name name, PhoneNumber phoneNumber) {
// Do actual registration...
}
}
Name.java
public class Name {
public Name (String name) {
if (name == null || name.trim ().isEmpty ()) {
throw new IllegalArgumentException ("Name was empty");
}
this.name = name;
}
//...
}
PhoneNumber.java
import java.util.regex.Pattern;
import java.util.regex.Matcher;
public class PhoneNumber {
public PhoneNumber (String phoneNumber) {
Pattern PHONE_PATTERN = Pattern.compile("\\d{10}|(?:\\d{3}-){2}\\d{4}|\\(\\d{3}\\)\\d{3}-?\\d{4}");
if (!PHONE_PATTERN.matcher(phoneNumber).matches()) {
throw new IllegalArgumentException("Number invalid");
}
this.phoneNumber = phoneNumber;
}
//...
}
Main.java
class Main {
public static void main (String[]args) {
Event eventVar = new Event (); //
Name nameVar = new Name("MyName Test");
PhoneNumber phNumVar = new PhoneNumber("999-999-9999");
eventVar.registerVisitor(nameVar, phNumVar);
}
//...
}
As far as "expected results" all I am trying to do is get this to successfully compile and instantiate the objects. My interest is in being able to create VO's that can work effectively as self-validating inputs.
PS: I am using JDK 8 on a Windows system.
Your name class does not have a field called 'name'.
public class Name {
private final String name; //added field
public Name (String name) {
if (name == null || name.trim ().isEmpty ()) {
throw new IllegalArgumentException ("Name was empty");
}
this.name = name;
}
//...
}
The problem is that you try to assign a value to a variable that is not declared.
You need to declare name and phoneNumber as class variables
public class Name {
private String name;
public Name (String name) {
...
this.name = name;
}
}
Also you probably want to make it private, so you will need a getter for it if you want to access it from outside the Name class:
public String getName() {
return name;
}
And the same thing in your PhoneNumber class
public class PhoneNumber {
private String phoneNumber;
public PhoneNumber (String phoneNumber) {
...
this.phoneNumber = phoneNumber;
}
public String getPhoneNumber() {
return phoneNumber;
}
}
Using your current code after these modifications
public void registerVisitor (Name name, PhoneNumber phoneNumber) {
System.out.println("Registering " + name.getName() + " | " +phoneNumber.getPhoneNumber());
}
would output:
Registering MyName Test | 999-999-9999
first time I've tried this. I need to be able to replace an email for subclass Student and sublass Teacher after an email has been inputted, I have a parent class and superclass which is where I believe I need to add my changeEmail method. I may be a way off here but can I use stringBuilder or is there an easier way? Real noob when it comes to this.
SUBCLASS -
public class Teacher extends Member
{
private String qualifications;
public Teacher(String name, String email, String qualifications)
{
super(name, email);
this.qualifications = qualifications;
}
public String getQualifications()
{
return qualifications;
}
public String toString()
{
StringBuffer details = new StringBuffer();
details.append(super.getName());
details.append(' ');
if(qualifications != null && qualifications.trim().length() > 0) {
details.append("(" + qualifications + ")");
details.append(' ');
}
details.append(super.getEmail());
return details.toString();
}
}
SUBCLASS -
public class Student extends Member
{
private int attendance;
public Student(String name, String email)
{
super(name, email);
this.attendance = 0;
}
public int getAttendance()
{
return attendance;
}
public void markAttendance(int attendance)
{
this.attendance += attendance;
}
public void print()
{
System.out.println(super.getName() + " (" + attendance + ")");
}
}
SUPERCLASS -
public class Member
{
private String email;
private String name;
public Member(String name, String email)
{
this.name = name;
this.email = email;
}
public String getEmail()
{
return email;
}
public String getName()
{
return name;
}
public String changeEmail()
{
//..........
}
}
Since changeEmail is a public method in the superclass, the subclasses can access it too. Student (as well as Teacher) is a Member.
public String changeEmail(String newEmailAddress) {
String old = email;
this.email = newEmailAddress;
return old;
}
What I changed was adding a parameter (String newEmailAddress) and then set the new value to the email instance field.
(EDIT: I updated the answer to return the old email address. I don't know why a method like this would return anything but anyways..)
That is called inheritance, basically if you have some shared variables, you can use some parent class and with the keyword extends create some subclasses.
All subclasses, which inherits the parent class, can have their own class variables, but also are having the parent variables.
In your case you can image the diagram like that- obvious, doesnt?
So...
Parent class member is having these class variables:
- String : mail
- String : name
You have two subclasses- Student and Teacher:
Teacher class variables:
qualifications
mail, name (inherited from parent!)
Student class variables:
attendance
mail, name (inherited from parent!)
Notice- with the keyword super you are calling the constructor (or simply "class" other methods) from the parent, so in Teacher and Student class, you will call exactly following:
public Member(String name, String email) {
this.name = name;
this.email = email;
}
To be able change the email, you need following
1) implement methods in parent class
2) optional- add call to child classes, and for usage outside the class also add some external method (without this you can still use public parent class methods)
Eg.
in parent
public void changeEmail(String newEmail) {
this.email = newEmail;
}
public String changeEmailWithReturnOld(String newEmail) {
String oldMail = this.email;
changeEmail(newEmail); //calling above
return oldMail;
}
In childs
public String changeTheMailWithReturnOld(String newMail) {
return super.changeEmailWithReturnOld(newMail); //super means super class, parent
}
Clear? :)
Then you can call following:
Teacher teacher1 = new Teacher("foo", "foo#foo.foo", "whateverFoo");
teacher1.changeEmail("someNewFoo#foo.foo"); //parent method
teacher1.changeEmailWithReturnOld("someNewFoo#foo.foo"); //Child method
I have a problem accessing the arraylist I created in a class. I tried going through the answers of questions similar to mine but unfortunately I was unable to solve the problem.
So I have two classes Student and Person and I want to iterate through the arraylist of Person in the class Student. (The code doesn't really make sense, I know. I just want to understand).
I tried two approaches :
1) creating a variable of type Person in Student class and calling the get method from person class.
2) creating a get method in the class person that returns arraylist.
Both are not working properly when i tried to call the isHere method in the main method.(false was printed instead of true)
I think my two approaches intialise a new array of type Person and not call the arraylist to which elements are already added. How can solve this?
import java.util.ArrayList;
public class Student {
private Person p;
private String name;
private int age;
private String address;
public Student() {
}
public Student(String name, int age, String address) {
this.name = name;
this.age = age;
this.address = address;
}
public boolean isHere(String name) {
p = new Person();
// I also tried for(Person per : p.getList)
for (Person per : this.getL()) {
if (per.getName().equals(name)) {
System.out.println("hi");
return true;
}
}
return false;
}
public ArrayList<Person> getL() {
return p.getList();
}
public Person getP() {
return p;
}
public void setP(Person p) {
this.p = p;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
The Person class:
import java.util.ArrayList;
public class Person {
private String name;
private ArrayList<Person> list = new ArrayList<Person>();
Person() {
}
public Person(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public ArrayList<Person> getList() {
return list;
}
public void setList(ArrayList<Person> list) {
this.list = list;
}
public void add(String name) {
list.add(new Person(name));
}
}
The statement p = new Person() in your isHere(..) method is creating a new Person object. When that Person object is created, the name in object p will be null and the list will be empty. So the for loop is never executed as the list is empty and hence it returns false.
If you ever want your code to run, you should not create the Person object and then immediately iterate through it because it will have nothing. You have to either add something to it or use a Person object which you believe will be populated before you run the isHere(..) method
I have an past exam question that says:
"Create a class Element that records the name of the element as a String and has a public method, toString that returns the String name. Define a constructor for the class (that should receive a String to initialise the name)."
I gave it a go and don't where to go from here...
main class is:
public class builder {
public static void main(String[] args) {
element builderObject = new element(elementName);
}
}
and constructor is:
import java.util.*;
class element {
public int getInt(String[] args) {
Scanner scan = new Scanner(System.in);
System.out.println("Enter the first number");
String elementName = scan.nextLine();
System.out.println("%s");
}
public String toString() {
return elementName;
}
}
Don't get frustrated. Please read java tutorials first and understand the concepts. your exam question is very clear on what you need to do. Atleast for this question, you need to know what is constructor, the purpose of having toString() in a class.
May be the below can help you.
public class Element {
private String elementName;
public Element(String elementName) {
this.elementName = elementName;
}
#Override
public String toString() {
return elementName;
}
}
I can't think of a way to explain this without actually giving the answer, so....
public class Element { /// Create class Element
private final String name; // Record the 'name'
public Element(String name) { // constructor receives and sets the name
this.name = name;
}
public String toString() { // public method toString() returns the name
return name;
}
}
You are missing the constructor itself. The point of constructors is to initialize the object, usually by saving the given parameters to data members.
E.g.:
class Element {
/** A data member to save the Element's name */
private String elementName;
/** A constructor from an Element's name*/
public Element(String elementName) {
this.elementName = elementName;
}
#Override
public String toString() {
return elementName;
}
}
class Element {
private String name = "";
/**
/* Constructor
/**/
public void Element(final String name){
this.name = name;
}
#Override
public String toString(){
return name;
}
}
You don't have a constructor in there. A constructor typically looks something like this:
public class MyClass {
private String name;
private int age;
//This here is the constructor:
public MyClass(String name, int age) {
this.name = name;
this.age = age;
}
//here's a toString method just for demonstration
#Override
public String toString() {
return "Hello, my name is " + name + " and I am " + age + " years old!";
}
}
You should be able to use that as a guideline for making your own constructor.
class Element
{
private String name = "UNSET";
public String getName() { return name; }
public Element(String name) {
this.name = name;
}
public String toString() {
return getName();
}
}
You are missing a constructor you might be looking for something like this
public class Element{
private String name;
public Element(String name){ //Constructor is a method, having same name as class
this.name = name;
}
public String toString(){
return name;
}
}
A note
I take you are starting with java, In java class names usually start with capital letter, thus element should be Element. Its important that one picks up good habits early..