Many parameters in java constructor [duplicate] - java

This question already has answers here:
Managing constructors with many parameters in Java
(8 answers)
Closed 4 years ago.
Hi I am a quite beginner in java.
Is it a good way to create construcors with many parameters like in my BookLibrary program?
public class Book implements Serializable {
private String title;
private String directorName;
private String directorSurname;
private String type;
private int issueYear;
private List<String> actorNames;
private List<String> actorSurnames;
private Tuple<String, String> directorFullName;
public Book(String title, String directorName, String directorSurname, String type, int issueYear,
List<String> actorNames, List<String> actorSurnames, Tuple<String, String> directorFullName){
this.title = title;
this.directorName = directorName;
this.directorSurname = directorSurname;
this.type = type;
this.issueYear = issueYear;
this.actorNames = actorNames;
this.actorSurnames = actorSurnames;
this.directorFullName = directorFullName;
}
Or is there any better idea to create such a constructor?

As others already said in comments, using the Builder Pattern would be an option. But if not done properly, that introduces the risk of creating incomplete objects.
But there are more ways to improve your design. E.g. you pass names and surnames (and a full name in case of the director - why only there?) as separate Strings. I'd create a PersonName class that encapsulates these different naming elements, so your constructor becomes:
public Book(String title,
PersonName directorName,
String type,
int issueYear,
List<PersonName> actors) {
...
}
Looks better and makes naming issues more consistent.
And of course, rename that class to be Movie instead of Book.

Creating a constructor with more than 3 parameters it is not a best practice. Because you need to know the order of each parameter. I can recommend you to use getters and setters in this way(for title field of class):
public String getTitle() {
return title;
}
public Book setTitle(String title) {
this.title = title;
return this;
}
By this structure you can create a very pretty constructions while creating a new instance:
Book book = new Book()
.setTitle("Book")
.setType("Comedy")
.setActorNames(Arrays.asList("Abzal"));
The full refactored version of your class:
public class Book implements Serializable {
private String title;
private String directorName;
private String directorSurname;
private String type;
private int issueYear;
private List<String> actorNames;
private List<String> actorSurnames;
private Tuple<String, String> directorFullName;
public Book() {
}
public String getTitle() {
return title;
}
public Book setTitle(String title) {
this.title = title;
return this;
}
public String getDirectorName() {
return directorName;
}
public Book setDirectorName(String directorName) {
this.directorName = directorName;
return this;
}
public String getDirectorSurname() {
return directorSurname;
}
public Book setDirectorSurname(String directorSurname) {
this.directorSurname = directorSurname;
return this;
}
public String getType() {
return type;
}
public Book setType(String type) {
this.type = type;
return this;
}
public int getIssueYear() {
return issueYear;
}
public Book setIssueYear(int issueYear) {
this.issueYear = issueYear;
return this;
}
public List<String> getActorNames() {
return actorNames;
}
public Book setActorNames(List<String> actorNames) {
this.actorNames = actorNames;
return this;
}
public List<String> getActorSurnames() {
return actorSurnames;
}
public Book setActorSurnames(List<String> actorSurnames) {
this.actorSurnames = actorSurnames;
return this;
}
public Tuple<String, String> getDirectorFullName() {
return directorFullName;
}
public Book setDirectorFullName(Tuple<String, String> directorFullName) {
this.directorFullName = directorFullName;
return this;
}
}
Have a good coding!

Related

How to call a method on a array of a class in java?

I'm a begginer doing some exercises on Java OOP so here's my problem.
I have a Book class with this attribute:
private Author[] authors;
I need a method that returns just the names of those authors(name1,name2,..). The Authors class has a getName() method:
public String getName() {
return name;
}
And I tried following code but it doesn't work !
//Method in the Book class
public String getAuthorsNames(){
return authors.getName();
}
Do I need to loop through the array or is there another way ?
private Author[] authors; is array of object Author
you need to add the index then get the name, here is an example:
class Author {
private String name;
public Author(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
and in your class Book:
class Book {
private Author[] authors;
public Book(int authorsSize) {
authors = new Author[authorsSize];
}
public void setAuthor(int index) {
this.authors[index] = new Author("Author Name"):
}
public String getAuthorName(int index) {
return this.authors[index].getName();
}
public String getAllAuthors() {
String all = "";
for (int i = 0; i < authors.length; i++) {
all += authors[i].getName() + ", ";
}
return all;
}
}
After adding Authors .. use getAllAuthors
--- more ---
Instead of Author[] authors = new Authors[size];
You can use ArrayList<Author> authors = new ArrayList<>();
then you can use:
authors.add(new Author("Author name1"));
authors.add(new Author("Author name2"));
authors.add(new Author("Author name3"));
authors.add(new Author("Author name4"));
......

How do I properly display the data from an object within an object?

Creating a linked list that has a class, Notes, that's basically an object that contains NotePages, another class, that contains Strings that are "title" and description. The class Notes extends another class which is the LinkedList class mentioned earlier. The problem is that when I try printing out the Notes with a note page in it, the display comes out like this:
Note one
[]
Assigning what to display in the object looks like:
NotePages page = new NotePages("title one", "Description");
Notes note = new Notes("Note one", page);
note.printNote();
I've tried creating other methods such as a String method to try and return the page properly to no avail.
Here's my code for the Notes object.
public class Notes extends LinkedList{
private String title;
private LinkedList<NotePages> pages;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public LinkedList<NotePages> getPages() {
return pages;
}
public void setPages(LinkedList<NotePages> pages) {
this.pages= pages;
}
public Notes(String title, LinkedList<NotePages> pages) {
this.title = title;
this.pages= pages;
}
void printNote(){
System.out.println(getTitle()+"\n"+getPages());
}
}
I need the display to output something closer to this:
Note one
title one
description
Here is the NotePages Class:
import java.awt.*;
public class NotePages {
private String title;
private String description;
private Color label;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Color getLabel() {
return label;
}
public void setLabel(Color label) {
this.label = label;
}
NotePages(String title, String description, Color label){
this.title = title;
this.description = description;
this.label = label;
}
NotePages(String title,String description){
this.title = title;
this.description = description;
}
void printPage(){
System.out.println(getTitle() + "\n "+ getDescription());
}
}
The change will need to be made in printNote function.
When the constructor for Notes is initialized pages variable gets initialised with a NotePage LinkedList.
pages does not contain the values directly. It contains objects of NotePage. So you need to use a loop for traversing through all the linkedList objects and then print the title and description for every object.
void printNote(){
System.out.println(getTitle());
//no need to use getPages function, pages already has your list
for(int i=0; i<pages.size();i++)
System.out.println(pages.get(i).getTitle()+"\n"+pages.get(i).getDescription());
}
get function will help you get the object at every ith index and then simply use the get functions of your NotePage class to print title and description.
Also the in main function add a linkedList object to the constructor of Note instead of a NotePage.
LinkedList<NotePages> notelist = new LinkedList<>();
notelist.add(page);
//adding LinkedList object to Notes constructor
Notes note = new Notes("Note one", notelist);

assertequal for method of object type

I am trying to make a test method using Junit test case for GetTeextBook() in Course class. Notice that GetTextBook() is type of Textbook object but I always get a failure when I run the CourseTestCase1 class in the method testGetTextBook().
any suggestion?
CourseTestCase1
public class CourseTestCase1 {
private Course course=new Course(101, "Software Engineering");
#Test
public void testGetTextBook() {
Textbook testbook=new Textbook(700, "Data Base System", "Ramez ELmasri",2011);
assertEquals(testbook,course.getTextbook());
}
#Test
public void testGetCourseCode() {
assertEquals(101,course.getCourseCode());
}
#Test
public void testGetName() {
assertEquals("Software Engineering",course.getName());
}
#Test
public void testToString() {
testGetCourseCode();
testGetName();
}
}
Course
public class Course {
private int courseCode;
private String courseName;
private Textbook textbook;
private Semester semestr;
public Course() {
this.courseCode = 0;
this.courseName = null;
this.semestr = null;
this.textbook = null;
}
public Course(int courseCode, String courseName) {
this.courseCode = courseCode;
this.courseName = courseName;
semestr = null;
textbook = null;
}
public Textbook getTextbook() {
return textbook;
}
}
Textbook
public class Textbook {
private int isbn;
private String title, authors;
private int publicationYear;
private TextbookCopy tbcopy;
public Textbook() {
isbn = 0;
title = null;
authors = null;
publicationYear = 0;
}
public Textbook(int isbn, String title, String authors, int publicationYear) {
this.isbn = isbn;
this.title = title;
this.authors = authors;
this.publicationYear = publicationYear;
}
public Textbook(int isbn, String title, String authors, int publicationYear,
String publisher, String distributor, double purchasePrice) {
this.isbn = isbn;
this.title = title;
this.authors = authors;
this.publicationYear = publicationYear;
}
public String getTitle() {
return title;
}
public int getPublicationYear() {
return publicationYear;
}
public String getAuthors() {
return authors;
}
public Textbook getBook() {
return this;
}
public int getISBN() {
return isbn;
}
public String getCopy() {
return Integer.toString(tbcopy.numbersOfCopy);
}
public void USwoltextbook(int isbn) {
}
public void assignNewBook() {
}
public Textbook createNewTextBook(String info) {
return null;
}
}
You need to properly define Textbook.equals() method. Default implementation just checks whether it's the same object. In your case it would be reasonable to check whether field contents is the same. If you are using IDE, there should be a button to generate such equals() method automatically (for example, in Eclipse: Source -> Generate hashCode() and equals()).
The assertEquals method from Junit is written as follows:
static public void assertEquals(String message, Object expected, Object actual) {
if (expected == null && actual == null) {
return;
}
if (expected != null && expected.equals(actual)) {
return;
}
failNotEquals(message, expected, actual);
}
and
static public void assertEquals(Object expected, Object actual) {
assertEquals(null, expected, actual);
}
So as you can see it uses the equals method of the expected object to make the comparison, therefore to make it work properly you should override equalsmethod.

Merge two Arrays of different objects into one Array/collection

I'm facing this task:
I have class A and class B. These two classes are different but almost the same.
I need to somehow merge them into 1 Single array of objects so I will be able to use them later in a list that combines both classes.
Class A:
public class Followers {
private String request_id;
private String number_sender;
private String state;
public String getRequest_id() {
return request_id;
}
public String getNumber_sender() {
return number_sender;
}
public String getState() {
return state;
}
}
Class B:
public class Following {
private String name;
private String state;
private String request_id;
public String getRequest_id() {
return request_id;
}
public String getName() {
return name;
}
public String getState() {
return state;
}
}
I've tried doing this next move:
Object[] obj1 = (Object[]) followers;
Object[] obj2 = (Object[]) followings;
Object[] completeArray = ArrayUtils.addAll(obj1, obj2);
Where followers and followings are both arrays of the corresponding classes. Then in my list adapter I use:
if (values[currentItem] instanceof Followers) { BLA BLA BLA}
else if (values[currentItem] instanceof Following) { BLA BLA BLA}
But I get this exception:
Caused by: java.lang.ArrayStoreException: source[0] of type json.objects.Following cannot be stored in destination array of type json.objects.Followers[]
What will be the best way to merge two arrays of different objects into one array?
Will just implementing the same interface between them do the job and then they will basically be in an array of the interface type?
what other ways do you recommend?
Try this
Object[] completeArray = new Object[0];
completeArray = ArrayUtils.addAll(completeArray, obj1);
completeArray = ArrayUtils.addAll(completeArray, obj2);
If you make both classes implement a common interface you can manipulate arrays/lists of them as if they contains instances of the interface.
public interface Follow {
public String getRequest_id();
public String getState();
}
public class Follower implements Follow {
private String request_id;
private String number_sender;
private String state;
public String getRequest_id() {
return request_id;
}
public String getNumber_sender() {
return number_sender;
}
public String getState() {
return state;
}
}
public class Following implements Follow {
private String name;
private String state;
private String request_id;
public String getRequest_id() {
return request_id;
}
public String getName() {
return name;
}
public String getState() {
return state;
}
}
public void test() {
List<Follow> all = new ArrayList<>();
all.add(new Following());
all.add(new Follower());
for ( Follow f : all ) {
String id = f.getRequest_id();
String state = f.getState();
}
}
Alternatively you could put them in a hierarchy:
public class Entity {
private String request_id;
private String state;
public String getRequest_id() {
return request_id;
}
public String getState() {
return state;
}
}
public class Follower extends Entity {
private String number_sender;
public String getNumber_sender() {
return number_sender;
}
}
public class Following extends Entity {
private String name;
public String getName() {
return name;
}
}
public void test() {
List<Entity> all = new ArrayList<>();
all.add(new Following());
all.add(new Follower());
for ( Entity f : all ) {
String id = f.getRequest_id();
String state = f.getState();
}
}
Or you could make the extra fields into attributes.
enum Attribute {
Follows,
Followed;
}
public static class Entity {
private String request_id;
private String state;
EnumMap<Attribute, String> attributes = new EnumMap<>(Attribute.class);
public String getRequest_id() {
return request_id;
}
public String getState() {
return state;
}
// Factory to make entities.
static Entity make(Attribute attribute, String value) {
Entity e = new Entity();
e.attributes.put(attribute, value);
return e;
}
}
public void test() {
List<Entity> all = new ArrayList<>();
all.add(Entity.make(Attribute.Follows, "Fred"));
all.add(Entity.make(Attribute.Followed, "Gill"));
for (Entity f : all) {
String id = f.getRequest_id();
String state = f.getState();
}
}
There are an infinite number of possibilities.
USE concat
var combined= obj1.concat(obj2); // Merges both arrays
Try this.
private Object[] appendObj(Object[] obj, Object newObj) {
ArrayList<Object> temp = new ArrayList<Object>(Arrays.asList(obj));
temp.add(newObj);
return temp.toArray();
}

Passing Arraylist between activities? Using Parcelable [duplicate]

This question already has answers here:
Android:Passing a hash map between Activities
(5 answers)
Closed 3 years ago.
EDIT: I've updated my question considerably and am now going with Parcelable as my method.
I'm attempting to a pass an ArrayList from one activity to another. I've been reading around and can't seem to find any answers to my problem.
I've got an ArrayList<SearchList> which implements Parcelable SearchList has the following code...
public class SearchList implements Parcelable {
private String title;
private String description;
private String link;
public SearchList(String name, String phone, String mail) {
super();
this.title = name;
this.description = phone;
this.link = mail;
}
public SearchList(Parcel source){
/*
* Reconstruct from the Parcel
*/
title = source.readString();
description = source.readString();
link = source.readString();
}
public String gettitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getLink() {
return link;
}
public void setLink(String link) {
this.link = link;
}
public int describeContents() {
// TODO Auto-generated method stub
return 0;
}
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(title);
dest.writeString(description);
dest.writeString(link);
}
public static final Creator<SearchList> CREATOR = new Creator<SearchList>() {
public SearchList createFromParcel(Parcel source) {
return new SearchList(source);
}
public SearchList[] newArray(int size) {
return new SearchList[size];
}
};
}
However, when I try and do...
List<SearchList> listOfResults = new ArrayList<SearchList>();
intent.putParcelableArrayListExtra("results", listOfResults);
I get not applicable for type (String, List<SearchList> why?
Could you use all String values, and change from bundle.putSerializable() to bundle.putStringArrayList("key", ArrayList<String>_object)
You can use SQLite as alternative. To pass data from one Activity to another. Here the link.

Categories