How to get one particular attribute from a class with several attributes? - java

I have this object. I want to access email attribute only in another class so I could check if the email is valid using assert in test directory. How do I access only email attribute from Person in another class to use it later to validate the email?
public class Person {
String name;
int year;
int month;
int day;
String email;
String phonenr;
public Person(String name, int year, int month, int day, String email, String phonenr) {
this.name = name;
this.year = year;
this.month = month;
this.day = day;
this.email = email;
this.phonenr = phonenr;
}
This is the class I want to access email attribute from:
public class PersonValidator {
public static boolean email(String email){
Person onePerson = new Person();
return false;
}
}
This is test class to test if email is valid:
class PersonRegisterTest {
#Test
void checkValidEmail() {
assertTrue(PersonValidator.email("adrianJames#oslomet.no"));
assertTrue(PersonValidator.email("example#example.com"));
assertTrue(PersonValidator.email("example.example#yahoo.com"));
}

Good practice in Java is to make all fields private, and create "getters and setters", i.e. functions to get and set values. For example:
public class Person {
private String email;
public void setEmail(String email) {
this.email = email;
}
public String getEmail() {
return this.email;
}
}
This way of doing things has several advantages:
If you you decide you want to change what values are allowed in a field, you can do that using the setter method. For example, if you want to impose a minimum length on emails, you can put if (email.length() < 10) return; in your method to prevent emails shorter than 10 characters
If you decide you want to retrieve emails over the internet or some other way, you do not have to change your code.
Many tools and frameworks expect Java objects to be in this format. Notable examples include Jackson for JSON serialization, and Spring/Spring Boot, for web application development, as well as many many more.
P.S. if you are sick of writing getters and setters:
Check if your IDE has a way of automatically generating them (most of them do)
Look into a library called Lombok, it provides the #Data annotation which can generate these methods automatically at compile time. (https://projectlombok.org/)

Its better to keep your data members/variables inside the class Person as private, and you can add getters and setters method, which you can access from outside the class and using which you can access the data members/variables of your class.
You can do something like:
public class Person {
String name;
int year;
int month;
int day;
String email;
String phonenr;
public Person(String name, int year, int month, int day, String email, String phonenr) {
this.name = name;
this.year = year;
this.month = month;
this.day = day;
this.email = email;
this.phonenr = phonenr;
}
public String getEmail()
{
return this.email;
}
}

For your case I'd make the the Person.email as package private - so it can stay as it is now, and put the PersonValidator class in the same package where you have Person class.
That would make you able to pass whole Person object to validator method like:
public static boolean email(Person person) {
String email = person.email;
return false;
}
But this is very isolated and not well designed. Also, there are plenty of ways being able to call methods from one class in another. E.g. create isEmailValid method in Person class and where you could directly use the email variable when calling PersonValidator.email(email).
Many of those uncommon approaches are most likely to invalidate SOLID, clean code and some other principles (like too tight coupled classes).
Like other answers stated it's much better to keep object fields well encapsulated (i.e. using private access modifier) and later access them with get/set methods.
Then regardless if you first create Person object (e.g. parse the Person list from file and then validate if they have correct email or get request params from smth like HTTP request for new person) you could call PersonValidator.email(personObject.getEmail() or PersonValidator.email(emailParam).
The package of keeping the PersonValidator class depends only on the convention of your project.
Having the "getters/setters" methods in an object, i.e. getEmail() setEmail(String email) getName() setName(String name) is common and good convention to keep your code well designed.
It's a good practice to implement such when applicable.
Just for further reading:
Having public getter method for email field in Person class shouldn't invalidate any coding standards (not even YAGNI-You Ain't Gonna Need It), because there could be plenty of future usages (e.g. displaying it for person/client using your program).
The mentioned encapsulation term in short words, it's about keeping inner implementation of an object inside it - i.e. not making it visible by other classes.
There're situations where an object modifies its inner fields by its methods, which are not the "setters" ones, but the current field value should always be accessed with getField() method.
"Don't overdesign, but keep future growth in mind" (i'm probably not citing anyone :P ).
The further use case could be to validate more field members of a Person object, which could result in having:
class PersonValidator {
public static boolean validatePerson(Person person) {
return validEmail(person.getEmail()) &&
//other validators when needed &&
validPhone(person.getPhonenr());
}
//very hard to validate
//most likely if has just a numbers (replacing "-" before)
//and only a length check (at least 3 without country code)
public static boolean validPhone(String phone) {
return false; //
}
public static boolean validEmail(String email) {
return false;
}
}
Again, as stated in other answers, it's much better to try searching for existing validator libraries, than writing new one - REALLY, REALLY.
There're different lenths and formats of phone numbers (mostly dependend on country), check this out.
The shortest valid email address could be a#a, or " "#a, but those are local email addresses. Check this wiki or this github gist to see some strange valid examples.
And the name, it depends on country laws and they are some which probably could accept the first names such as "A" or "Ben11" and the weirdest surname in Poland is "Cyps Albo Zyps".

First add getters to you Person object/class and make the internal state of the object only accessible via the getters:
public class Person {
private final long id;
private final String name;
private final String email;
public Person(long id, String name, String email) {
this.id = id;
this.name = name;
this.email = email;
}
public String getEmail() {
return email;
}
// Other 2 getters
}
Then build a validator that can validate email address format, or better use a library (like https://commons.apache.org/proper/commons-validator/) for that:
public final class EmailValidator {
private EmailValidator() { }
public static boolean isValidEmail(String email) {
// check if valid email and return true or fale
}
}
Call the validator by getting the email address from new person by calling the getter. The validator shouldn't have any knowlegde of the Person object.
public static void main(String[] args) {
Person newPerson = new Person(1L, "test user", "valid#hotmail.com");
if (EmailValidator.isValidEmail(newPerson.getEmail())) {
System.out.println("Valid email address");
} else {
System.out.println("Invalid email address");
}
}

Related

User input and using methods from another class

Still learning Java, bit of an idiot and I apologize for the trouble. I have a question with regards to using user input from a main.class with an employee.class with getters and setters and returning those back to the main.class. Is this the correct way of using methods from the employee.class with user input? Would it be okay to just point me to the right direction.
Here's the Employee.class which needed a default value of true.
public class Employee() {
private String id = "100";
private boolean manager = true;
public Employee(String id, String name, int numOfYears) {
this.id = id;
this.name = name;
this.numOfYears = numOfYears;
}
public Employee(String id, String name, int numOfYears, double
monthlySalary, boolean manager) {
this.id = id;
this.name = name;
this.numOfYears = numOfYears;
this.monthlySalary = monthlySalary;
this.manager = manager;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public boolean getManager() {
return manager;
}
public void setManager(boolean manager) {
if (manager == true) {
System.out.println("Yes");
this.manager = manager;
} else {
System.out.println("No");
this.manager = manager;
}
}
}
And here's the Main.class
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.println("Enter employee ID:");
int i = input.nextInt();
String id = Integer.toString(i);
System.out.println("In management? True/False");
boolean manager = input.nextBoolean();
Employee empId = new Employee(id);
empId.setId(id);
Employee empManager = new Employee();
empManager.setManager();
}
}
Would the correct way to input the user values be
Employee empManager = new Employee(manager);
empManager.setManager();
I'm not sure if I could ask, but I feel like I probably have more errors, if it'd be okay to just nudge in the right direction.
It's not the correct way.
The correct way would be to define a proper constructor:
public Employee(String id, boolean isManager)
{
this.id = id;
this.isManager = isManager;
}
and call it like that:
Employee employee = new Employee(id,isManager);
Brief hint: For booleans, it's a good practice to name them with "isXYZ" - that's why I've changed the name. Also, an if(var == true) can be written as if(var) - the true is implicit.
The right answer is that there is no "right" answer. This is 100% a philosophical question with a number of "right" answers. That said, there are some things most developers will agree with that you need to consider for you to decide which "right" answer is the right one FOR YOU.
What parameters should you pass via constructor? The constructor should be used to enforce REQUIRED values at the time of construction. For example, name and id we can agree should be required fields. But, what about managerName? Maybe the manager has not been assigned at the time of hire for some reason (i.e. position is vacant).
Since it's OK to have setter methods, might as well use them. There is nothing wrong with providing a setter method and use such method to set a value AFTER the object is created. As a general rule, we include getter/setter methods for all fields. HOWEVER, I think it is better to decide which fields (if any) are constant and provide setters (obviously) for variable fields only.
For argument's sake, let's assume that a person should not be able to change his or her name. IN that case, I would design my Employee class like this:
public class Employee {
private final String name; // Required (constant)
private final String id; // Required (constant)
private String phoneNo; // optional
private String managerName; // "optional"
private boolean isManager; // required (variable)
public Employee (String name, String id) {
this.name = name;
this.id = id;
}
public void setPhoneNo(String phoneNo) { this.phoneNo = phoneNo; }
public void setManagerName(String managerName) { this.managerName = managerName; }
}
Also, consider default values. In Java, Primitive Data Types have default values as follows: numeric primitives have a default value of 0. Boolean primitives default to false, character primitive default to the Unicode character value of NULL (\u0000). This means that, unless you need to override the default value, setting the value might be optional (even though the value is required). What does that mean? In your example, you have a boolean flag to indicate whether an employee is in management. Knowing that the majority of employees are not going to be in management, the above example's constructor should be enough. For someone that is hired as manager, you can provide three-argument constructor to pass "true" to this boolean field OR simply build the employee object with the existing constructor and then use the setter method to set this flag to true.
Employee hector = new Employee("Hector", "100");
hector.setManager(true);
The above will be as acceptable as
Employee hector = new Employee ("Hector", "100", true);
Having this three-argument constructor does not invalidate the need for the two argument one. It is fine to keep both. However, if you must do so, use a telescoping pattern...
public Employee (String name, String id, boolean isManager) {
this(name, id); // calling the two-arg constructor
this.isManager = isManager;
}

Loop over object setters java [duplicate]

This question already has answers here:
Invoking all setters within a class using reflection
(4 answers)
Closed 5 years ago.
I have a POJO object and a collection of appropriate data.
import java.util.ArrayList;
import java.util.List;
public class TestPojo {
private String name;
private String number;
private String id;
private String sex;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public static void main(String[] args) {
TestPojo test = new TestPojo();
List<String> sampleData = new ArrayList<>();
sampleData.add("Bob");
sampleData.add("641-613-623");
sampleData.add("id-1451");
sampleData.add("Male");
test.setName(sampleData.get(0));
test.setNumber(sampleData.get(1));
test.setId(sampleData.get(2));
test.setSex(sampleData.get(3));
}
}
My question is how can i fill my POJO object with data in a loop? Is it posible to iterate all object setters and set data from List in appropriate places? I know that reflection can help in this case.
Here is an simple example to call setters via reflection (which needs to be adjusted):
[if this is a good approach, is another question. But to answer your question:]
public static void main(String[] args) throws Exception
{
//this is only to demonstrate java reflection:
Method[] publicMethods = TestPojo.class.getMethods(); //get all public methods
TestPojo testObj = TestPojo.class.newInstance(); //when you have a default ctor (otherwise get constructors here)
for (Method aMethod : publicMethods) //iterate over methods
{
//check name and parameter-count (mabye needs some more checks...paramter types can also be checked...)
if (aMethod.getName().startsWith("set") && aMethod.getParameterCount() == 1)
{
Object[] parms = new Object[]{"test"}; //only one parm (can be multiple params)
aMethod.invoke(testObj, parms); //call setter-method here
}
}
}
You can also save all setter-methods in an list/set for later re-use...
But as others already said, you have to be careful by doing so (using reflection)!
Cheers!
You can't easily - and you shouldn't.
You see, your POJO class offers some setters. All of them have a distinct meaning. Your first mistake is that all of these fields are strings in your model:
gender is not a string. It would rather be an enum.
"number" is not a string. It should rather be int/long/double (whatever the idea behind that property is)
In other words: you premise that "input" data is represented as array/list is already flawed.
The code you have written provides almost no helpful abstractions. So - instead of worrying how to call these setter methods in some loop context - you should rather step back and improve your model.
And hint: if this is really about populating POJO objects from string input - then get your string into JSON format, and use tools such as gson or jackson to do that (reflection based) mapping for you.
"Iterating over methods" seems pretty much of a wrong idea in OO programming. You could simply add a constructor to your class setting all of your attributes, and then just call that constructor in a loop as desired to create new objects with data you desire.
In your class define:
public TestPojo(String name, String number, String id, String sex){
this.name = name;
this.number = number;
this.id = id;
this.sex = sex;
}
Also using a List makes no much sense here. I'd recommend using a HashMap to then iterate over it in a for loop making proper calls of the above constructor.

A real life example of public properties being bad

Countless times I've read that public properties on a class are a major faux pas, but I fail to see why on data that doesn't get transformed going in/out.
example of something I would write
public class Employee
{
public String firstName;
public String lastName;
private int ssn = 0;
public boolean setSsn(String s)
{
//makes perfect sense why something like an ssn would use a getter setter
//some code to validate ssn
if(!validSsn(s)){
ssn = 0;
return false;
}
ssn = raw;
return true;
}
public String getSsn()
{
return ssn;
}
private boolean validSsn(String s)
{
//validation goes here
retrun val;
}
//I don't understand why I should make firstName private
// and then write
public void setFirstName(String s)
{
firstName = s;
}
public String getFirstName(String s)
{
return firstName;
}
}
please provide a scenario in which this would cause a problem and please be specific, not "because it causes issues when other people use your code" WHY? Why does it cause issues. Thanks in advance for constructive criticism and detailed answers :D
Imagine that your code has gone to production. I write a front-end that uses your Employee class that accesses firstName and lastName directly.
6 months go by, and now there's a new business requirement that you add validation to the name fields.
Where are you going to add it? You're going to have to make the fields private and add set methods, and this will force me and everyone else using your code to re-write our apps.
If you had encapsulated that data properly in the first place, all we'd have to do is recompile using the new version of the library with your code.

Any way to get all data types within a custom object?

I'm developing an open source API for measuring run-time allocation for custom objects easily. While I can write the cache handling algorithms just fine, I'm having an issue accessing all of the data types within a custom object organically. I'm wanting to write this API to take any custom object so long as it has the following data types currently supported:
Int
String
Short
Byte
Long
Float
Double
Char
Boolean
Bitmap (for Android only but can be excluded)
For instance, take this custom object class
package productions.widowmaker110.byteme;
/**
* Created by Widowmaker110 on 11/20/2015.
*
* This object class is meant to mimick possible data types held within a single object
*
* For simplicity, I will be mimicking a simplified user profile data
*/
public class ExampleObject {
private String Name;
private int Age;
private String Location;
private String Sex;
private String Description;
/**
* Empty Constructor
*/
public ExampleObject() {}
/**
* Basic constructor with initializing data
*
* #param _Name String with the name of the user
* #param _Age Integer with the age of the user
* #param _Location String containing the curret city and state of the user
* #param _Sex String Male, Female, Transgender, or Other
* #param _Description String short blurb about the user
*/
public ExampleObject(String _Name, int _Age, String _Location, String _Sex, String _Description)
{
this.setName(_Name);
this.setAge(_Age);
this.setLocation(_Location);
this.setSex(_Sex);
this.setDescription(_Description);
}
public String getName() {
return Name;
}
public void setName(String name) {
Name = name;
}
public int getAge() {
return Age;
}
public void setAge(int age) {
Age = age;
}
public String getLocation() {
return Location;
}
public void setLocation(String location) {
Location = location;
}
public String getSex() {
return Sex;
}
public void setSex(String sex) {
Sex = sex;
}
public String getDescription() {
return Description;
}
public void setDescription(String description) {
Description = description;
}
}
What I want to do is take something like this and "transfer" all of the data points to my cache handling class while maintaining the object in its current form if I can help it. My first idea was to have an object have an array of every data type of a given object but then that seems convoluted to me to deconstruct a custom object in such a way. I might be looking at it wrong but if I do something like:
Object(int[] int_array, String[] string_array, short[] short_array,
long[] long_array, byte[] byte_array, float[] float_array,
double[] double_array, char[] char_array, boolean[] boolean_array,
Bitmap[] bitmap_array)
And ask the programmer to enter in all of their data points by placing them in an array.
My end goal for this API is to drop it into a project and have all of that nasty cache handling done for you instantly.
EDIT My apologies for making it unclear. I was trying to give the whole scope of the project but may have given too much. Is there any way to take a custom class and parse it without ever knowing what fields are available as long as they fall into the bullet-point list I made at the top? I can do the caching part myself. Does that make it clearer?
EDIT #2 JFPicard pointed out using Java reflection for this sort of handling. After looking at the oracle documentation and these:
Jenkov
JavaCodeGeeks
I found something like this to be extremely helpful.
import java.lang.reflect.Method;
...
Method[] methods = MyObject.class.getMethods();
for(Method method : methods){
System.out.println("method = " + method.getName());
}
Thanks!
I think that you need to use reflection to get all the getters of the object and get the data to do something.
Here's a good tutorial to help you: https://docs.oracle.com/javase/tutorial/reflect/member/methodModifiers.html

Are the builder pattern and a DSL equivalent - or is one more expressive?

Assumptions
I'll limit this to internal DSLs - but if you can give me a good reason why I should consider external DSLs - I'll listen to that.
If you want to answer this in Clojure or Scala and explain why I'm wrong - I'm cool with that too.
I heard a friend say the other day:
You know, a DSL and the builder pattern - they're basically the same thing.
To me this sounded strange, as I had always assumed a DSL would always be more expressive than the Builder Pattern.
My question is: Are the builder pattern and a DSL equivalent - or is one more expressive?
So I took a look - here is a User Builder Pattern in Java:
public class User {
private final String firstName; // required
private final String lastName; // required
private final int age; // optional
private final String phone; // optional
private final String address; // optional
private User(UserBuilder builder) {
this.firstName = builder.firstName;
this.lastName = builder.lastName;
this.age = builder.age;
this.phone = builder.phone;
this.address = builder.address;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public int getAge() {
return age;
}
public String getPhone() {
return phone;
}
public String getAddress() {
return address;
}
public static class UserBuilder {
private final String firstName;
private final String lastName;
private int age;
private String phone;
private String address;
public UserBuilder(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public UserBuilder age(int age) {
this.age = age;
return this;
}
public UserBuilder phone(String phone) {
this.phone = phone;
return this;
}
public UserBuilder address(String address) {
this.address = address;
return this;
}
public User build() {
return new User(this);
}
}
}
Here is the above builder pattern being used:
public User getUser() {
return new
User.UserBuilder("John", "Doe")
.age(30)
.phone("1234567")
.address("Fake address 1234")
.build();
}
Here is usage of an Internal DSL in Java:
Person person = constructor().withParameterTypes(String.class)
.in(Person.class)
.newInstance("Yoda");
method("setName").withParameterTypes(String.class)
.in(person)
.invoke("Luke");
field("name").ofType(String.class)
.in(person)
.set("Anakin");
I don't think that you can even compare these 2 different concepts.
A DSL is a language for a specific domain i.e it has primitives and composition rules that allows you to talk about a specific domain.
A builder pattern is a pattern i.e a solution template that you apply to a problem to come up with a solution and then you use that solution. In your code example, the UserBuilder class comes out of applying the builder pattern, it itself is not builder pattern.
It seems that you are trying to compare them syntactically as your sample code is trying to show. In both the example code you show that syntactically, both DSL and a builder patter class, have the same feature i.e a chain of method calls and that leads to the thought that you can compare them. I don't think that comparison is fair as that can only allow you to compare them in a same language i.e there is no way to compare them syntactically across different programming languages.
You can implement a DSL using the builder pattern OR you can also implement DSL using other patterns too. A pattern is a solution template for a set of problems, builder pattern is one such template for the problem of implementing a DSL but it is not the only one.
Of course DSLs include a lot of things which aren't a builder pattern. So no, they aren't the same thing.
If you consider every builder pattern to be a DSL (for the domain of constructing objects of a particular class), then you obviously get that DSLs in general are more expressive than builder patterns. But a DSL is not more expressive than the builder pattern; any single DSL can't do everything that the builder pattern can do.
Had your friend said
You know, for constructing Plain Old Java Objects, the builder pattern is a kind of DSL.
... then I'd agree.
However, in Clojure, you don't need a builder class or a DSL to construct an object concisely.
POJOs translate into records, which imitate (hash) maps. There is a somewhat clunky
syntax for creating a record from a map.
Given
(defrecord User [first-name last-name age phone address])
... then
(map->User {:first-name "John"
:last-name "Doe"
:address "Fake address 1234"})
... produces
{:first-name "John",
:last-name "Doe",
:age nil,
:phone nil,
:address "Fake address 1234"}
... which is a User record, though it prints like a map.
So, for this purpose, Clojure takes the DS out of DSL and you're just left with a language construct.

Categories

Resources