Multiple instance of class versus array Java - java

My question which of the following examples represents the right practice ?
What are the advantages and downsides of these approaches.
Is there another(right) way to achieve this?
Let's say I have class
public class Person {
private String name;
public Person(String name) {
this.name = name;
}
public String print() {
return this.name;
}
}
And use of class like:
public static void main(String[] args) {
List<Person> people = new ArrayList<Person>();
people.add(new Person("Jane Doe"));
System.out.println(people.get(0).print());
}
And then another way to do this:
public class Persons {
private ArrayList<String> persons;
public Persons() {
persons = new ArrayList<String>();
}
public void putPerson(String name) {
persons.add(name);
}
public String print(int id) {
return this.persons.get(id);
}
}
And use of that:
public static void main(String[] args) {
Persons persons = new Persons();
persons.putPerson("John Doe");
System.out.println(persons.print(0));
}
EDIT:
Assume I have 10 000 of these persons.
Is there any downside to creating 10,000 instances of the class?

I would prefer the first way because there is a rare need to create a wrapper class for keeping a collection (like Persons -> Person). It makes sense if the class Persons gets renamed to a Company/Community, which contains a List of workers/persons and provides specific operations over this list.
public String showAllMembers() { ... }
public void notifyAllMembers() { ... }
Also, the second way breaks the Single responsibility principle. It shouldn't take care about printing a person, the class is responsible for adding/removing them. The Persons can provide to you a specific Person, then you have to call a method print() on a given instance:
Persons persons = ...;
persons.getMember(10).print();
Lets say i have 10 000 of these persons. Is there any downside to create 10 000 instance of class?
In any case, you will have to create 10000+ instances. Consider,
10000 Persons + a List
10000 Persons + a Persons + a List

The first one is more object-oriented than the second, which becomes apparent as soon as you start adding more properties to a person.
For example, consider adding a date of birth to a person. When you have class Person, you modify the class, and everyone who has access to it will be able to get it. You will also be passing the date of birth with the Person object, so any method that takes Person as a parameter will have access to that person's date of birth:
static void displayPerson(Person p) {
// Here, we can print both the name and the date of birth / age
}
public static void main(String[] args) {
...
displayPerson(people.get(0));
}
The second approach would require adding a parallel collection to the Persons class. All users of Persons would get access to date of birth, but unless a method takes the full collection as a parameter, it would have access to only the properties that the caller takes from the collection:
void displayPerson(String name) {
// Here, we have no access to person's date of birth
}
public static void main(String[] args) {
...
displayPerson(persons.print(0));
}

In Java, the first approach is the one to go with. It is more in accordance with the OOP way of doing things.
While there is nothing structurally wrong with the second, it doesn't follow the OOP architecture. You may do this kind of operation in C.
In the first approach, you create a Person class which defines what a person is - its properties, methods, etc. This is the object in Object oriented programming. When you need a Person, you then instantiate one and add it to a list of people.
In the second, you create a array, essentially. You can then create an instance of it and fill in the properties you want. However, I see the following drawbacks for this approach:
The object you're adding to the class doesn't exist anymore. Nowhere have you defined what a person is and what properties it has. These properties only exist in the values you add to the array. This can get very confusing and risky after a while.
No getters and setters. Every operation to retrieve a specific property and update it will result in very complex and redundant iterations on your array. In addition, your class can potentially have a very large number of properties, and every time you want to update a property, you'll have to be very careful to get the right index of that property in the array. It's a recipe for disaster.
Also, a putPerson method which just adds a value to the array? Cringy.
Short answer: don't do the second way, in Java, ever.

In my opinion example A is much easier to understand than B hence I would say code readability and maintainability wise it is better.
Reason is that for example B the persons structure actually involves composition of another structure ArrayList to accomplish generics which in example A, you have achieve it by declaring List<Person>.
Example B is also less flexible than A, because it is always a collection whereas example A you can simply use it as a Person and just plug it into different data structures available in Java. Example if you want to keep track of unique person, you can easily come out with a map that is keyed by <name, Person>, whereas example B would not be as clean because you will be doing something like <name, Persons> where each persons would only contain 1 person. Hence extensiblity wise may not be as great as the other one.
Also to me, A is more of the traditional way of doing object oriented because you are representing a real world object as a class whereas B is really just a wrapper of an object.
Obviously there can be a lot of arguments to this, but I'm happy with others input and critic about this answer.

Related

How to construct a user(/input)-specified number of objects

I'm currently doing an intro level undergrad CS course (learning basics of 'program'&'class' building using Java).
The relevant part of my personal (&job related) project: I have a list of zip codes associated with One county.
I'm gonna define a class called 'County'. Then I'm gonna use this class to construct an object of type County, called 'middlesex'.
ie: County middlesex = new County();
Now, in this object, I want to construct a number of objects of class-type ZipCode.
ie: ZipCode objName = new ZipCode();
(Each such ZipCode object is gonna contain certain instance data).
My problem is this. Assume that I don't know how many zipcodes are contained in the Middlesex county. However, I have a .txt file that contains just a list of all the zipcodes of Middlesex county.
Let's say there are n number of zipcodes in this list.
In the object 'middlesex', of class-type 'County', I want to set up a loop. This loop will scan each zipcode in the list, then construct an object of class-type ZipCode for each zipcode.
Thus the loop may go thru n iterations, and construct n objects of type ZipCode.
Thus, for every iteration of the loop, a unique object-reference-name must be created (corresponding to the particular zipcode in the list).
Part of this problem (but distinct and optional), is that I want to know how (if possible), I can set up a structure that allows an inputted (scanned) string to be used as the name of an object-reference.
I apologize if I've made incorrect terminology use. I know that many are gonna suggest arrays. I haven't learned about them yet, but I gotta read about them over this weekend for school. I'm just gonna try to figure this out for a day or two, and then just move on to using arrays to perform this task.
So, if I've made any sense to anyone, is what I'm trying to do possible without arrays?
Thank u.
You're describing a very basic scenario, one where one object contains (possibly) many references to objects of a 2nd type, what we call a constructor called "composition" where the relationship here is a "has-a" relationship, County has-a (or has-many) zip codes
As opposed to using inheritance to wrongly try to solve this, the "inheritance" relationship or the "is-a" relationship -- County is not a zip code and zip code is not a county.
The code to create this can be very simple, something like:
import java.util.ArrayList;
import java.util.List;
public class County {
private String name;
private List<String> zipCodes = new ArrayList<>();
// constructor that takes county name
public County(String name) {
this.name = name;
}
public void addZipCode(String code) {
zipCodes.add(code);
}
// ..... more code
If a zip code is a single String, then no need to create a new class for this. If however it is more complex and holds more data than a single String, then create a class for ZipCode, and change the code above to something like
import java.util.ArrayList;
import java.util.List;
public class County {
private String name;
private List<ZipCode> zipCodes = new ArrayList<>();
// constructor that takes county name
public County(String name) {
this.name = name;
}
public void addZipCode(ZipCode code) {
zipCodes.add(code);
}
// getters, setters, a decent toString method override...
Where ZipCode could contain....
public class ZipCode {
String code;
// other fields if needed....
public ZipCode(String code) {
this.code = code;
}
// ....
then when reading in data, create your County objects and as each Zip code is read in, add it to the appropriate County object using the addZipCode(...) method.
zipCode is an object of Type ZipCode then what are its fields? Think of the reasons for making it an object and not a variable
"Thus the loop may go thru n iterations, and construct n objects of type ZipCode"
Unforutnality this is not possible without making the use of Arrays
"structure that allows an inputted (scanned) string to be used as the name of an object"
Nope can do that.

How to use an object's class variables to identify an object in java?

I created a class and made 57 objects from it, each one has specific ID number.
Can I create a method which returns an object using an ID as the argument?
For example, assume the name of my class is Things and I made two object from it called apple and dog, they have IDs 1 and 2.
Things.java:
class Things {
private String name;
private int ID;
public Things(String name, int ID) {
this.name = name;
this.ID = ID;
}
}
Main.java:
class Main {
public static void main(String[] args) {
Things apple = new Things("apple", 1);
Things dog = new Things("dog", 2);
}
}
in this example I want to create a method in class "Things" which returns object apple if I use 1 as argument and object dog if I use 2 .
You cannot identify objects by a particular property unless you store it in a special repository
You can create a ThingRepository and can get specific Things by the id.
public class ThingRepository {
private Map<Integer, Things> thingsRepository = new HashMap<>();
public void addThing(int id, Things things) {
thingsRepository.put(id, things);
}
public Things getThingById(int id) {
return thingsRepository.get(id); //Can return null if not present
}
}
The addThing method need not explicitly take the id. If you add a getter to Things, then it can be simplified to
public void addThing(Things things) {
thingsRepository.put(things.getId(), things);
}
Couple of problems you need to address:
Each created Things object has to be added to this somehow (either the caller needs to add or there must be some other wrapper/factory that must do this).
Once a Things is not needed, it must be removed from the above map, else it can lead to memory leak.
Btw, shouldn't Things be named as just a Thing?
There are two aspects here:
you need some sort of data structure that remembers about created objects, and allows you to access them by id, for example a simple Map<Integer, Things>. Each time you create a new Things (should better be called Thing, shouldn't it?!), you go thatMap.put(newId, newThing).
if you want that data to "survive", you would have to somehow persist it (like writing data to a file, database, ...)
If you use Intellij for example press: alt + insert and choose getters/setter.
If not just write your own getters/setter ;).
Like here: https://docs.oracle.com/javaee/6/tutorial/doc/gjbbp.html
But basically if you want to look for Thing with particular Id you need to store somewhere them for example in ArrayList, then iterate through it and if your find element with that Id just return it.
1) Create new ArrayList
2) Iterate through
3) If you find Thing with Id you want, return it.

create multiple instances of a class without array in a loop

I know this question been asked many times, and I've looked through many similar topics but they all include array or list and I don't want to use array or lists, second I don't understand :).
Anyway here's my question: I have a class with name,id,job methods to store these in a variable, and I want to to ask how many Staff the company has, and that's why I cant hard code each variable because the number is unknown thus I need a loop, And am not allowed to use array or list. Any idea or help is appreciated Thanks.
Here's the code for the class:
public class Staff{
public void name(String name){
String staff_name = name;
}
public void id(String id){
String staf_id = id;
}
public void job(String job){
String staff_job = job;
}
}
code for main:
import javax.swing.JOptionPane;
public class P2Q2{
public static void main(String[]args){
System.out.println("How many staff in Department? ");
String staff_num = JOptionPane.showInputDialog(null,"How many Staff are there",
"Department staff numbers",JOptionPane.QUESTION_MESSAGE);
int staff_num_int = Integer.parseInt(staff_num);
for(int i=1;i<staff_num_int;i++){
//somthing in here to create objects for each staff
}
}
}
Here is the whole question:
EDIT:
I just didn't want to provide the whole question, but if this is better there you go.
You can create Staff objects without array or list - but it will not have sense because you will not have access to the objects. If you will not have access to the objects - that means the Garbage Collector will destroy them after you go out the loop scope.
Well if you can't use an array or list, and you want to access to each staff object. You can look into using something such as a hash map. You can store objects in the hash map and just use the staff names as a key to access each object after created and added to the map.

Overrloading methods in Java interface [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
Is it right to overload method in Java interface like below. And then use the method required in your subclass? If not, is there a better way to do it, kindly suggest.
interface IEmployees{
public List<String> getEmployees(List<String> employees, List<String> departments);
public List<String> getEmployees(List<String> employees, String name);
}
class EmployeesByDept implements IEmployees{
public List<String> getEmployees(List<String> employees, List<String> departments){
// select employees belonging to depts in list and return.
}
public List<String> getEmployees(List<String> employees, String name){
throw new UnsupportedOperationException();
}
}
class EmployeesByName implements IEmployees{
public List<String> getEmployees(List<String> employees, List<String> departments){
throw new UnsupportedOperationException();
}
public List<String> getEmployees(List<String> employees, String name){
// select employees with name in list and return.
}
}
in my opinion overloading an interface this way is not a good idea, as this produces unnecessary/useless code at the implementing class.
I would therefore recommend to write 2 or 3 different interfaces like so
interface IEmployees {
}
interface IEmployeesByDept extends IEmployees {
public List<String> getEmployees(List<String> employees, List<String> departments);
}
interface IEmployeesByName extends IEmployees {
public List<String> getEmployees(List<String> employees, String name);
}
This Way you can cleanly implement the interface that matches your case.
Well, yes and no, it depends.
In general there are most certainly cases for it, where appropriate.
In your case though, probably not, and a lot of your issue comes down to more fundamental design problems. So just by reading your snippet it appears the possibilities are that an IEmployees is:
A set of all employees in a system (for example, all of the employees that work on a project or for a company), or
An arbitrary list of employees (includes 1 but also e.g. search results, etc., the semantic equivalent of a List<Employee>, or
A construct that has a list of employees associated with it (for example, a project, or an organization).
But you say:
it is actually an employee filter class. It will be inherited by other filter classes and will implement any one of the overloaded methods in the interface.
So your first minor problem is the interface name itself. IEmployees leaves a lot up in the air, but if you name it something more self-documenting and descriptive, e.g. IEmployeeFilter, then things start to come together a little more obviously.
So now you have a "filter", and it appears you are trying to have multiple separate filter strategies:
By department
By employee name
Possibly others
These are separate filters, and you state your interface defines a filter, and therefore these are more appropriately organized as two separate subclasses.
So first of all the interface should be what is common to all filters. How the filtering is done is not the common aspect. The filtering itself is. So consider:
interface IEmployeeFilter {
public List<String> getEmployees (List<String> employees);
}
Now you have a filter that makes sense, a single common method, and everything else falls into place, e.g.:
class EmployeeNameFilter implements IEmployeeFilter {
private String name;
public EmployeeNameFilter (String name) {
this.name = name;
}
#Override
public List<String> getEmployees (List<String> employees) {
return employees filtered appropriately
}
}
And:
class EmployeeDepartmentFilter implements IEmployeeFilter {
private List<String> departments;
public EmployeeDepartmentFilter (List<String> departments) {
departments = new ArrayList<String>(departments);
}
#Override
public List<String> getEmployees (List<String> employees) {
return employees filtered appropriately
}
}
Etc. Then when you're ready to use one the interface is always the same:
List<String> employees = ...;
IEmployeeFilter filter = new EmployeeNameFilter("bob"); // or...
// IEmployeeFilter filter = new EmployeeDepartmentFilter(...);
List<String> results = filter.getEmployees(employees); // <- interface always the same
Point is, interfaces exist as a tool to make a job easier. When you run into a situation where you have a bunch of classes implementing that interface but they all implement different parts of it, you're starting to defeat the purpose of an interface, and it's a good hint that there's a fundamental change that needs to be made in your design.
That is, a more general rule of thumb can be: If your interface is making your job harder, or making your code more complicated, you've done something wrong. Otherwise, you've done something right.
Hope that made sense.
Your use-case does not warrant the use of an Interface at all
An Interface represents a contract. You defined the contract as being able to fulfill two requirements. If you know you won't be able to provide both parts of the contract, do not use an interface at all.
Additionally, I strongly doubt you have alternative ways of getting these Employees Lists, another reason not to use interfaces.
Alternative solution
I am guessing your IEmployeesXXX classes have no state variable. This is a good indicator that the methods are utility methods which fetch and return a list of objects.
You should make it a classic Utility class, i.e. an abstract final class with static methods.
Here's an example using your own code, wich becomes much cleaner:
public abstract final class Employeesutility{
public static List<String> getEmployees(List<String> employees, List<String> departments){
// select employees belonging to depts in list and return.
}
public static List<String> getEmployees(List<String> employees, String name){
// select employees with name in list and return.
}
}
Notes going forward
I do not like Utility classes much, I would rather make an intermediate class with rich internal representation, and rich collections wich expose your proposed interface methods. But for your use case, this would probably mean duplicate the entire DB (guessing you have one), which would be stupid. Please consider it if ever you decide to create a true Employee class... which you will when your program becomes big enough.

I need some help designing an array

For my homework, we've been tasked with creating:
Person class with variables firstName, lastName, streetAddress, zipCode and phone.
CollegeEmployee extends Person and adds ssn, salary, and deptName.
Faculty extends CollegeEmployee by adding a boolean tenure.
Last but not least, Student extends person by adding GPA and major.
Everything looks good displaying to screen, and I'm moving on to the next part of the assignment which is to create 14 records (7 students, 4 employees and 3 faculty) in an array.
3 different classes, with multiple data types, and I cannot for the life of me figure out how to populate an array with this. This is the first array I've created that's not been completely integer. The Java Tutorials didn't give me anything, and while Java: Generic Static Multidimensional Arrays has some great information, it's a little more than I can wrap my head around right now.
I'd initially thought of creating array[14][10] -- fourteen variables each for ten objects -- but I can't mix data types. That's where I got lost.
Anyone have any suggestions on how to design this array and be able to display the values from it afterward?
Any hints and suggestions would be appreciated!
Thanks.
From what I understand, no need to get fancy with multi-dimensional arrays.
1) Create an array that takes Person instances.
Person [] myPeeps = new Person[14];
2) Create a print method on Person, which subclasses override to print the relevant info.
Because your array expects Person instances, you can put instances of any subclasses of Person, because subclasses always have an is-a relationship with their superclass.
Because Person has a print method, you can call print on anything you pull out of the array. Subclasses provide their own implementations so they can print their relevant data. That way, you don't really care about which subclass any particular instance is; the correct print implementation for the instance is invoked at runtime.
You don't need a multidimensional array. You can make an array of Person objects.
Person[] people = new Person[14];
people[0] = new Student();
people[1] = new Employee();
.
.
.
You could also create a Person[] array, just as you would an int[] array. e.g.
Person[] people = new Person[14]
You can then add people to the Array like this:
people[0] = new Student();
people[1] = new CollegeEmployee();
people[2] = new Faculty();
If you want to check what type of person is in each index you will want to use instanceof. Try looking here for more help
One example of using instanceof is:
if(people[0] instanceof Student){
System.out.println("This person is a student");
}
Or try using generics.
You could create an ArrayList<Person> and can then add any type of person to this ArrayList.
e.g.
ArrayList<Person> peopleList = new ArrayList<Person>();
//People can be added like this
peopleList.add(new Student());
peopleList.add(new CollegeEmployee();)
Again you are able to use instanceof to check which type of person is in each index!
Also if you never write
Person person1 = new Person();
In your code then consider making your class abstract.
To start:
Person[] myArray = new Person[14];
This is essentially why object oriented programming is so wonderful. If you'll notice, all Faculty, CollegeEmployee, and Student are a subset of type Person. Because of this, you can have them all contained in the same dataset if it is declared as type Person.
Person[] array = new Person[14];
You can add all of your objects to that array; however, be careful. When you go to use the elements of the array Java now only knows that each has the methods that a Person does - so therefore you can only make use of firstName, lastName, streetAddress, zipCode, and phone from these elements unless you cast the objects after they are retrieved.
Since they are all of type Person, why not use a Person array?
Person [] people = new Person[14];
You can safely add all types of Person to this array, however you can only treat them as Person (without casting). To have each subclass output customized details, and add this method in Person
class Person {
void print() {
// default Person printing
}
}
and override this method in each subclass to print its member variables:
class Student extends Person {
void print() { // <-- note same method signature!
// print "I'm a Student", GPA, major
}
}
and when the array is populated:
for (Person p : people) {
p.print(); // delegates to print method associated with the underlying type
}
Check out the inheritance tutorial
The class Person is a common superclass to all the types of the objects you want to store in the array. You can create the array based on that common supertype. Then you can access methods that are defined in that tpe on all elements of the array, regardless of the actual type -- the behavior is as defined in the actual type (look up inheritance for java if this is not clear).
If you need specific behavior based on the actual type, you need to cast the array element to the concrete type (you can determine it using instanceof, for example)

Categories