I am new to collections and looking for help. I am trying to search a map using a key, and return the values of the key which is from another object. This is my code so far.
public class Employer {
Map<String, NewHire> employee = new HashMap<>();
}
public void addEmployee(String fullName, String age, String location, String JobTitle) {
NewHire newEmployee = new NewHire(age, location, JobTitle);
this.employee.put(fullName, newEmployee);
}
The code for the other object is -
public class NewHire {
private String age;
private String location;
private String jobTitle;
}
public NewHire(String aAge, String aLocation, String aJobTitle) {
this.age = aAge;
this.location = aLocation;
this.jobTitle = aJobTitle;
}
I then create like so -
Employer CompanyA = new Employer();
CompanyA.addEmployee("JohnSmith", "23", "London", "Service Desk");
I wanted to create a method that can search the map for a key specified by the user, in this case "JohnSmith", and if found, it then shows me the age, location and jobTitle of that person but I really am not sure how I would go about this.
The best way to go about it in my opinion is the way Titulum said, using Optional.
I would just leave another way, a bit not so nice, but you may understand it better.
You can Override the toString() method in the NewHire class and use it, or create getters for the properties:
#Override
public String toString(){
return String.format("Age: %s\nLocation: %s\nJobTitle: %s", age, location, jobTitle);
}
// getters
public String getJobTitle() {
return jobTitle;
}
public String getLocation() {
return location;
}
public String getAge() {
return age;
}
On your Employer class, if you want to use the not so much nicer way of doing it (although i recommend using Optional):
public NewHire getEmployeeByName(String fullName){
return employee.get(fullName);
}
Then to use it:
Employer employer = new Employer();
employer.addEmployee("JohnSmith", "23", "London", "Service Desk");
NewHire newHire = employer.getEmployeeByName("sJohnSmith");
if(newHire != null) {
System.out.println(newHire.toString());
// using getters
System.out.println(newHire.getAge());
System.out.println(newHire.getJobTitle());
System.out.println(newHire.getLocation());
}
You can simply write the method as follows:
public Optional<NewHire> findByFullName(String fullName) {
return Optional.ofNullable(employee.get(fullName));
}
This will return you an Optional, which is an Object in Java that contains either something or nothing. To see if the Optional contains anything you can do:
Optional<NewHire> possiblyFoundNewHire = findByFullName("SomeName");
possibleFoundNewHire.ifPresent(newHire -> {
System.out.println(newHire); // Or formatted as you would like.
});
Related
As a task in my beginners course in object oriented programming, I must set two objects in my Partner class as "married".
This is my attempt at beginning:
public class Partner {
String name;
String partner;
public Partner(String name, String partner) {
super();
this.name = name;
this.partner = partner;
}
public String getPartner() {
return partner;
}
public void setPartner(Partner()) { //think i need the object here?
this.partner = partner; //however i don't know how
}
public String getName() {
return name;
}
public static void main(String[] args) {
Partner p1 = new Partner("Name1", idk);
Partner p2 = new Partner("Name2", idk);
}
}
My issue is that I don't know how to use the object in the setPartner method, if that's even the correct way to do it. It should also be possible to get a divorce from the other object by setting one of the objects' partner to null.
It should also make it so that the partners automatically register as married to eachother if one of them is set a married to the other. For example, if p1 is set as the partner of p2, p2 should automaticly be set as the parter to p1 as well.
Create two constructors: one with just name and another with name and partner (of type, Partner) so that you will have the flexibility to initialize an object with just name and then set its partner or initialize with name and partner (if the partner is known).
public class Partner {
private String name;
private Partner partner;
public Partner(String name) {
this.name = name;
}
public Partner(String name, Partner partner) {
this.name = name;
setPartner(partner);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void setPartner(Partner partner) {
partner.partner = this;
this.partner = partner;
}
#Override
public String toString() {
String value;
if (partner != null) {
value = name + ", partner=" + partner.name;
} else {
value = name;
}
return value;
}
public static void main(String[] args) {
// Example 1
Partner p1 = new Partner("Name1");
Partner p2 = new Partner("Name2");
p1.setPartner(p2);
System.out.println(p1);
System.out.println(p2);
// Example 2
Partner p3 = new Partner("Name3");
Partner p4 = new Partner("Name4", p3);
System.out.println(p3);
System.out.println(p4);
}
}
Output:
Name1, partner=Name2
Name2, partner=Name1
Name3, partner=Name4
Name4, partner=Name3
Are you asking how to write setter methods ? Something like this
public void setPartner(String partner) {
this.partner= partner;
}
If you intend for a Partner object to have a pointer to another object of this class, you should change String partner to Partner partner.
You won't always have an initialized Partner object to use in the Partner constructor, so you have 3 options:
add another constructor which doesn't require an argument of type Partner
change the existing constructor
pass null as argument.
In any case, you'll have to initialize the partner field somewhere else.
That's where setters come in. The correct syntax for your setPartner function would be:
public void setPartner(Partner partner) {
this.partner = partner;
}
getPartner() function should be changed accordingly to return the correct type.
Your code in main() can then be something like this:
Partner p1 = new Partner("Name1", null);
Partner p2 = new Partner("Name2", p1);
p1.setPartner(p2);
It should also be possible to get a divorce from the other object by setting one of the objects' partner to null.
That is accomplished by using p.setPartner(null), where p is an object of type Partner. You might also want to set both objects partners to null instead of just one, for easier checking.
We use the builder pattern extensively in our code base, with built objects all having a toBuilder() method. I want to write a unit test that ensures that no fields have been forgotten in the toBuilder() methods, i.e., for any buildable object, I want to a test roughly like this
MyClass obj = getTestObjectWithRandomData();
assertEquals(obj, obj.toBuilder().build());
Now, I can fairly easy write a basic version of getTestObjectWithRandomData() that uses reflection to assign a bunch of values to the fields of any object. However, the snag is that build() often contains tons of validation checks that will throw exceptions if, for example, a certain integer isn't within a sane range. Writing a generalized version of getTestObjectWithRandomData() that conforms all those class-specific validation checks would be impossible.
So, how can I do what I want to do? I'm tempted to segregate the construction and validation code into different methods so that the test doesn't trip on the validation, but then that means that people have to remember to call validate() or whatever on objects after they create them. Not good.
Any other ideas?
How about using Lombok? Would that be an option for you? It will auto-generate the builder code and you'll never again have to worry about it.
https://projectlombok.org/features/Builder
Simply annotate your classes with #Builder
With Lombok
import lombok.Builder;
import lombok.Singular;
import java.util.Set;
#Builder
public class BuilderExample {
private String name;
private int age;
#Singular private Set<String> occupations;
}
Vanilla Java
import java.util.Set;
public class BuilderExample {
private String name;
private int age;
private Set<String> occupations;
BuilderExample(String name, int age, Set<String> occupations) {
this.name = name;
this.age = age;
this.occupations = occupations;
}
public static BuilderExampleBuilder builder() {
return new BuilderExampleBuilder();
}
public static class BuilderExampleBuilder {
private String name;
private int age;
private java.util.ArrayList<String> occupations;
BuilderExampleBuilder() {
}
public BuilderExampleBuilder name(String name) {
this.name = name;
return this;
}
public BuilderExampleBuilder age(int age) {
this.age = age;
return this;
}
public BuilderExampleBuilder occupation(String occupation) {
if (this.occupations == null) {
this.occupations = new java.util.ArrayList<String>();
}
this.occupations.add(occupation);
return this;
}
public BuilderExampleBuilder occupations(Collection<? extends String> occupations) {
if (this.occupations == null) {
this.occupations = new java.util.ArrayList<String>();
}
this.occupations.addAll(occupations);
return this;
}
public BuilderExampleBuilder clearOccupations() {
if (this.occupations != null) {
this.occupations.clear();
}
return this;
}
public BuilderExample build() {
// complicated switch statement to produce a compact properly sized immutable set omitted.
// go to https://projectlombok.org/features/Singular-snippet.html to see it.
Set<String> occupations = ...;
return new BuilderExample(name, age, occupations);
}
#java.lang.Override
public String toString() {
return "BuilderExample.BuilderExampleBuilder(name = " + this.name + ", age = " + this.age + ", occupations = " + this.occupations + ")";
}
}
}
So for the below question, I tried to search online but I couldn't find the answer to it. I am working in Java language.
So I currently have a class, lets say:
public Employee(String emp_id, String location, String name)
{
this.emp_id = emp_id;
this.location = location;
this.name = name;
}
I have created multiple objects of Employee, and I have saved it in an arrayList. Now, I the user will ask which employees are located in New York, or they can ask which employees are named John.
So they can enter location New York. I need to read in the user's request, first identify what they are trying to search, and then see if there are any matching Employees in the array.
I have read in the command, and saved it in an array of strings called Search. The first index holds the name of the field/property of the object, and the second index will hold what the user actually wants to check.
String[] search = new String[] { "location", "New York" }
I was thinking for doing this:
for(Employee e: empList)
if(e.search[0].equals(search[1]))
System.out.println(e)
However, I am not able to do this, since search[0] is not a property name for the Employee object. I am getting this error: error: cannot find symbol.
Is there a way for me to access the object property without the actual name, meaning the name is saved in another String variable?
Please let me know. Appreciate your help.
Thank you.
What you are looking for is the Reflection API. Here's a simple example of how you might achieve what you need. Notice that we can query the class for its Fields and Methods. We can then do checks on Field types or Method return types. Reflection is not for the faint of heart but it can give you some extremely dynamic code.
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class Employee {
public String name;
public int age;
public Employee(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return this.name;
}
public int getAge() {
return this.age;
}
public static void main(String[] args) throws Exception {
Employee e1 = new Employee("Nick", 30);
Class<?> c = e1.getClass();
Field f = c.getField("name");
System.out.print("Type: ");
System.out.println(f.getType());
System.out.print("Object: ");
System.out.println(f.get(e1));
System.out.println();
System.out.println("Methods: ");
Method[] methods = c.getMethods();
for(int i = 0; i < methods.length; i++) {
System.out.print("Name: ");
System.out.println(methods[i].getName());
System.out.print("Return type: ");
System.out.println(methods[i].getReturnType());
// imagine this value was set by user input
String property = "name";
if( methods[i].getName().toLowerCase().equals("get" + property) ) {
System.out.print("Value of " + property + " is: ");
System.out.println(methods[i].invoke(e1));
}
}
}
}
You could write your class to allow querying in this way, by wrapping a Map (or a Properties if you prefer:
public class Employee {
private Map<String,String> properties = new HashMap<>();
public Employee(String emp_id, String location, String name) {
properties.put("emp_id", empt_id);
properties.put("location", location);
properties.put("name", name);
}
public String getProperty(String key) {
return properties.get(key);
}
}
You can expose the fields as getters if you like:
public String getName() {
return this.getProperty("name");
}
The opposite way around, of course, is to explicitly write a getProperty(String) to access fields:
public String getProperty(String key) {
switch(key) {
case "name":
return this.name;
case "empId":
return this.empId;
case "location":
return this.location;
default:
throw new NoSuchFieldException; // or return null, or whatever
}
}
This may seem long-winded, but it's pretty easy and effective.
You can also use Reflection to work with the class at runtime. This is not recommended for new programmers - not because it is difficult as such, but because usually there's a cleaner way. And it subverts Java's access control features (e.g. it can read private fields).
Reflection includes techniques such as Class<?> c = e1.getClass(); Field f = c.getField("name"); -- there are no checks at compile time that e1 has a field called name. It will only fail at runtime.
If you're willing to use the Bean method naming conventions -- mostly simply that getName() is an accessor for a field called name -- then you could use Apache BeanUtils to work with the object. This is also Reflection, but it's wrapped in a more task-centric API.
String name = PropertyUtils.getProperty("name");
... this will:
call getName() and return the result, if getName() exists
throw NoSuchMethodException if there is no getName() method
other exceptions for other failures (see the JavaDoc)
So you could write:
public boolean isMatch(Employee employee, String[] search) {
String key = search[0];
String expectedValue = search[1];
try {
String actual = PropertyUtils.getProperty(key);
return(Objects.equals(actual,expected)); // Objects.equals is null-safe
} catch (NoSuchMethodException e) {
return false;
}
}
This is just pseudocode. But here you are getting each Employee object at index i and getting the name returned in the form of a string from this employee at index i.
for (int i = 0; i < empList.size(); i++)
{
if (empList.get(i).getId().equals(search[1]) || empList.get(i).getName().equals(search[1]) || empList.get(i).getLocation().equals(search[1]))
return true;
}
So basically, iterate through your list of objects Employee. At each employee, getName() returns the string value of the name of this Employee.
That is how you access the properties, with your getter method.
public String getName()
{
return this.name;
}
You can use the getFields() method if the Class, although I recommend you a simpler method if the class have so little properties, you can just use the or operation to achieve this:
for(Employee e: empList)
if(e.getLocation().equals(Search[1])||e.getName().equals(Search[1]))
System.out.println(e)
Using the getFields() method:
String searchValue="The string you have to search";
for(Employee e: empList){
List<Field> selectedFields=new ArrayList<Field>();
for (int i = 0; i < e.getClass().getFields().length; i++) {
if(e.getClass().getFields()[i].getType().getName().equals("String")){
selectedFields.add(e.getClass().getFields()[i]);
}
}
for(Field f:selectedFields){
if(f.get(e).equals(searchValue)){
System.out.println(e);
}
}
}
}
As mentioned in other answers: this can be solved with reflection. Another approach with some java8-sugar:
public static void main(String[] args) {
List<Employee> unfilteredList = new ArrayList<>();
// ... Add the employees
String[] fieldAndExpectedValue = new String[] { "location", "Narnia-City" };
List<Employee> filteredList = unfilteredList.stream().filter(
employee -> objectHasFieldWithValue(employee, fieldAndExpectedValue[0], fieldAndExpectedValue[1]))
.collect(Collectors.toList());
// ...
}
private static <INSTANCE, FIELDVALUE> boolean objectHasFieldWithValue(INSTANCE o,
String fieldName, FIELDVALUE expectedValue) {
try {
Field f = o.getClass().getDeclaredField(fieldName);
f.setAccessible(true);
if (f.getType().isInstance(expectedValue) && expectedValue.equals(f.get(o))) {
return true;
}
} catch (Exception exc) {
exc.printStackTrace();
}
return false;
}
It's weird that all the answers focus on reflection. Design wise, you should be using getters to solve your problem. It is true that you need to use reflection to retrieve a property without any extra logic in that section of code, but your problem should rely on improving the searching logic rather than exposing fields and breaking SOLID OOP design.
From the looks of it you want a simple solution for searching through an array of objects and checking if the a property matches a certain value.
This would be an answer to that question:
///public class Employee {
public bool doesEmployeeMatch(String property, String value){
switch(property){
case "location": return value.equals(this.location);
break;
case "name": return value.equals(this.name);
break;
default: System.out.println("Invalid parameter");
break;
}
}
///where ever you're searching through empList
for(Employee e: empList)
if(e.doesEmployeeMatch(search[0],search[1])){
System.out.println(e);
break;
}
But that isn't how the question should be formed. Best way of forming the question would be "I need to determine the search parameter, then find the Employees that match the value of my parameter." That means you should have two steps to logically handle this actions. First figure out what field you want to find, then find all the employees that have the expected value on said field.
So what would that look like?
First you'll need some getter functions.
public class Employee {
private String emp_id, location, name;
public Employee(String emp_id, String location, String name) {
this.emp_id = emp_id;
this.location = location;
this.name = name;
}
public String getEmp_id(){
return this.emp_id;
}
public String getLocation(){
return this.location;
}
public String getName(){
return this.Name;
}
}
Next up you need to add logic for determining which getter to use.
///sorry I just threw a method name out for you
public bool findEmployeeMatch(String[] search){
switch(search[0]){
case "location":
break;
case "name":
break;
default:
break;
}
Finally add some lambda expressions to impress the masses.
public bool findEmployeeMatch(String[] search, empList){
///other code maybe?
switch(search[0]){
case "location": Arrays.stream(empList).forEach(e)->
if(e.getLocation().equals(search[1])){
System.out.println(e);
}
break;
case "name": Arrays.stream(empList).forEach(e)->
if(e.getName().equals(search[1])){
System.out.println(e);
}
break;
case "emp_id": Arrays.stream(empList).forEach(e)->
if(e.getEmp_List().equals(search[1])){
System.out.println(e);
}
break;
default: System.out.println("Invalid parameter");
break;
}
I can't see why there would be a reason to not check for what field they would want, as using reflection is costly and seeing how this is an app that expects users to search for data in a backend, whether for work or school, I do not believe reflection is the thing you want to be using.
I suggest not to use reflection API at all. It is messy and not type safe.
Instead use Functional interface Java 8 provides or similar constructs if you are not using Java 8. Here is a cleaner type safe solution using Java 8:
public class Search<T> {
private T searchValue = null;
private Function<Employee, T> getter = null;
public Search(T searchValue, Function<Employee, T> getter) {
this.searchValue = searchValue;
this.getter = getter;
}
public T getSearchValue() {
return searchValue;
}
public void setSearchValue(T searchValue) {
this.searchValue = searchValue;
}
public Function<Employee, T> getGetter() {
return getter;
}
public void setGetter(Function<Employee, T> getter) {
this.getter = getter;
}
}
public Optional<Employee> find(List<Employee> empList, Search<?> search){
for (Employee e : empList){
if ( Objects.equals( search.getGetter().apply(e), search.getSearchValue() ) ) return Optional.of(e);
}
return Optional.empty();
}
And you can search like this:
find( empList, new Search<>("Mark", Employee::getName ) ) //finds Employee with name Mark
find( empList, new Search<>("Toronto", Employee::getLocation ) ) //finds Employee with location in Toronto
Update:
Here is method that maps user specified field name to actual Search:
public static Search<String> create(String searchValue, String fieldName){
if ( "name".equalsIgnoreCase(fieldName) ) return new Search<>(searchValue, Employee::getName );
else if ( "location".equalsIgnoreCase(fieldName) ) return new Search<>(searchValue, Employee::getLocation );
else throw new IllegalArgumentException("Unsupported fieldName: " + fieldName);
}
find(empList, Search.create("Toronto", "location" ) )
If I want to validate my input, should I make validation code as private helper methods or create a separate static helper class? Does the validation code increase the size of the object?
More Information
Let's say I have a class
import java.util.Vector;
public class Place {
private final double longitude;
private final double latitude;
private final String id;
private String address;
private String name;
private String types;
private String icon;
private String phoneNumber;
private String websiteUrl;
private int rating;
private Vector<Integer> challenges;
public static class Builder {
// required parameter
private final double longitude;
private final double latitude;
private final String id;
// optional parameter
private String address = "n/a";
private String name = "n/a";
private String icon = "n/a";
private String phoneNumber = "n/a";
private String websiteUrl = "n/a";
private String types = "n/a";
private Vector<Integer> challenges = new Vector<Integer>();
private int rating = 0;
public Builder(double longitude, double latitude, String id) {
assert(longitude >= -180.0 && longitude <= 180.0);
assert(latitude >= -90.0 && longitude <= 90.0);
this.longitude = longitude;
this.latitude = latitude;
this.id = id;
}
public Builder address(String address) {
this.address = address;
return this;
}
public Builder types(String types) {
this.types = types;
return this;
}
public Builder name(String name) {
this.name = name;
return this;
}
public Builder icon(String icon) {
this.icon = icon;
return this;
}
public Builder phoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
return this;
}
public Builder websiteUrl(String websiteUrl) {
this.websiteUrl = websiteUrl;
return this;
}
public Builder builder(int rating) {
this.rating = rating;
return this;
}
public Place build() {
return new Place(this);
}
}
public Place(Builder builder) {
// required parameters
longitude = builder.longitude;
latitude = builder.latitude;
id = builder.id;
// optional parameters
address = builder.address;
types = builder.types;
name = builder.name;
icon = builder.icon;
phoneNumber = builder.phoneNumber;
websiteUrl = builder.websiteUrl;
rating = builder.rating;
challenges = builder.challenges;
}
public double getLongitude() {
return longitude;
}
public double getLatitude() {
return latitude;
}
public String getId() {
return id;
}
public void setAddress(String address) {
this.address = address;
}
public String getAddress() {
return address;
}
public String getTypes() {
return types;
}
public void setTypes(String types) {
this.types = types;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setIconUrl(String icon) {
this.icon = icon;
}
public String getIcon() {
return icon;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
public String getPhoneNumber() {
return phoneNumber;
}
public void setWebsiteUrl(String websiteUrl) {
this.websiteUrl = websiteUrl;
}
public String getWebsiteUrl() {
return websiteUrl;
}
public void setRating(int rating) {
this.rating = rating;
}
public int getRating() {
return rating;
}
#Override
public String toString() {
return "(" + Double.toString(longitude) + ", " + Double.toString(latitude) + ")";
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((id == null) ? 0 : id.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Place other = (Place) obj;
if (id == null) {
if (other.id != null)
return false;
}
else if (!id.equals(other.id))
return false;
return true;
}
public Vector<Integer> getChallenges() {
return new Vector<Integer>(challenges);
}
public void addChallenges(Integer i) {
this.challenges.add(i);
}
public void showChallenges() {
for (Integer i : challenges) {
System.out.print(i + ", ");
}
}
}
If I have to validate address argument before setting it, where should I put the code for validating address in this case?
If you are talking just seeing if the entered String is formatted correctly or if the length is right, then you would use a private method. If you would on the other hand check if the address is correct (look it up on a map) or any more advanced stuff, it would make sense to create a AddressValidator interface and call it from that private method.
The reason for the private method being that you call this both from a constructor, setter or any other method that could suppy an address. The reason for the interface being that you might want to have e.g. an online / offline AddressValidator (MockAddressValidator, or one that calls a different class for each country etc).
As an AddressValidator could be reused in other classes, and to keep your code clean, I would create it as a top level interface + OnlineAddressValidator. This makes your class better readable as well. For full configurability, you might want to think about how you are going to supply the AddressValidator instance, e.g. through the constructor or one defined as a static final validator.
public interface AddressValidator {
static class AddressValidatorResult {
// some results, you might want to return some useful feedback (if not valid)
boolean isValid() {
throw new IllegalStateException("Method not implemented yet");
}
}
public static class AddressValidationException extends Exception {
private AddressValidationException(AddressValidatorResult result) {
// add some implementation
}
}
// don't throw ValidateException here, invalid addresses are normal for
// validators, even if they aren't for the application that uses them
AddressValidatorResult validateAddress(String address);
// don't throw ValidateException here, invalid addresses are normal for
// validators, even if they aren't for the application that uses them
}
public class DefaultAddressValidator implements AddressValidator {
public static class Params {
// some parameters for this specific validator
}
private final Params params;
public DefaultAddressValidator(Params params) {
// creates this validator
this.params = params;
}
#Override
public AddressValidatorResult validateAddress(String address) {
// perform your code here
// I don't like "return null" as it may lead to bugs
throw new IllegalStateException("Method not implemented yet");
}
}
// and use it like this
private void validateAddress(String address) throws AddressValidationException {
// e.g. field AddressValidator set in constructor
AddressValidatorResult result = addressValidator.validateAddress(address);
if (!result.isValid()) {
throw new AddressValidationException(result);
}
}
Should I make validation code as private helper methods or create a separate static helper class?
This totally depends on your context. It's impossible to say what should be the best design, without knowing what you are trying to realise.
After you edit: IMO, it is still not easy to tell you. If you only have to validate the address in one single point of your application (id: the setter method), I would validate it inside the setter method. If the input was invalid, I whould throw an IllegalArgumentException.
Does the validation code increase the size of the object?
However, the answer to your second question is No. To understand why, you have to know what Object Oriented Programming is.
Some references:
http://en.wikipedia.org/wiki/Object-oriented_programming
http://en.wikipedia.org/wiki/Class_(computer_science)
Should I make validation code as private helper methods or create a
separate static helper class?
It depends if you think that you'll need to reuse the same method also in another class for the same purpose(input validation) it is better write the method in a separate static helper class so you can reuse the method and maintain it easily.
If you write the same private helper method in several class each time that you need to make a changes you have to edit each method in each class, with a static helper class you change the code in one place only ...
Read about PropertyChangeListener and Bean Validation.
I tend to validate within the get() and set() methods wherever possible - calling external static methods for common tasks such as checking dates or cleaning input (i.e. to avoid sql injection)
If you only use (and are only ever going to use) the validation within one class, keep it as a private helper method. If in doubt, I tend to pull the functionality out into a static helper class. It makes very little difference to the amount of code, is no more effort to implement, and is much more flexible.
The short answer is: you should implement your validation code the way that your framework tells you to. Typically, this is a public method or an annotation. An interface could work too. If you add code, your class size will increase.
Data validation should be automatically called by your software's infrastructure. This helps to prevent programmers from forgetting to call the appropriate code. So, the methods should be public (an interface would work too).
Frameworks like Struts, Spring, Hibernate and have their own validation systems. Java EE leverages bean validation.
I recommend bean validation, because it performs validation regardless of the input source. When most people think of input validation, they think of data coming from the user e.g. HTTP Request, command console, Swing text field. Spring and Struts validation is often fine for those situations. But in long lived programs developed for enterprises, other data feeds often get introduced e.g. SQL database updates from another programs, database restoration after a crash, enterprise service bus, JMS.
That is why I prefer bean validation. The downside is that "safe sources" (data that you know is untainted) are validated unnecessarily. But with today's processing power, that should rarely be a significant concern.
Java EE Tutorial
Hi i have the following code:
public List<Person> findAll() {
List<Person> copy = new ArrayList<Person>();
for (Person person : personer) {
copy.add(person);
}
return copy;
}
But when i test this i only retrieve the following and not the value:
[Person#15c7850, Person#1ded0fd,
Person#16a9d42]
How do i get the values and not like above. Where i am inserting the person the code looks like this:
public boolean insert(String name, String nbr) {
if (containsName(name)) {
return false;
}
Person person = new Person(name, nbr);
personer.add(person);
return true;
}
and here is my Person class:
class Person {
private String name;
private String nbr;
public Person (String name, String nbr) {
this.name = name;
this.nbr = nbr;
}
public String getName() {
return name;
}
public String getNumber() {
return nbr;
}
}
You're already receiving the objects you want.
What you see is an internal representation of these objects.
You must iterate through them and call their respective methods to see the information you probably want to see.
If you're not satisfied with these results, you must override toString to provide you with more meaningful information.
Update:
after seeing your edit, you should add toString similar to this one in your Person class:
#Override
public String toString() {
return "Name: " + name + ", number: " + nbr;
}
By the way, you're storing nbr as a string, and it's obvious it should be an integer. So, I'd suggest changing its type to an int or Integer.
You are getting a List object back. You can use the Person object to get the data that you need. To get to the Person objects, iterate over the list.
List<Person> people = findAll();
for Person p : people {
String phoneNumber = p.phoneNumber();
String name = p.Name();
}
Override the toString() method in the Person class if you want a better description when printing the results.
Put something like this in the class Person (don't change the method name!):
public String toString() {
return name;//change this line
}
You are printing out an Object that has the default toString inherited from the Object class. This will print out the type of object it is and its location in memory (ie: Person#1ded0fd).
If you'd like it to see something else, you can override the toString method within your class:
public class Person {
private String name;
public Person(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
public String toString() {
return this.name;
}
}
If your class looked like the above, this would allow you to do something like this:
Person p = new Person("John");
System.out.println(p);
> John
You can also just grab it as is and print out any information you want from it without overriding the toString method.
Person p = new Person("John");
System.out.println(p.getName());
> John
What value or class Person's property you aspect to retrieve from the ArrayList? This kind of value(Person#15c7850, etc) shows that the Person's object random id that assigned by JVM when you use
System.out.print(copy).