I'm new to coding and I'm confused about getters and setters in Java.
I know that getters and setters are used for encapsulation. But if you have a constructor that creates a person of a specific gender and length. Should both of these characteristics have a setter and a getter?
public Person(Gender gender, Length length) {
this.gender = gender;
this.length = length;
}
Does the this.gender serve as a setter? If no, what's its function?
Do I need to make a getter and setter for these? In code examples i've found they only have a getter, but not a setter. But i don't really understand why.
Thanks in advance!
In code examples I've found they only have a getter, but not a setter. But I don't really understand why.
The functionality you describe is so when a Person object is created, nobody can set its gender and length.
If a user wishes, he/she can create a new Person (new Person(...)) with attributes as they wish. But after a Person is created, you cannot set the attributes.
But does the this.gender = gender work as a setter or not? I can't seem to find out what its function is.
It does work as a setter (though not a setter by itself since it's not a function). But only within the constructor. As I said above.
Note that if the gender and length fields of a Person are not private then they can potentially be set/get outside of a set/get methods.
The constructor example code you have given is used to set/initialize the variables of Person class when you create Person object by invoking the constructor method. Internally, the attribute values get set by this. So, you can say it's functionality is like setter. After this you only need getters to fetch and use the value held by these attributes.
However, you can also write specific setter method for each attribute to set the values individually for each of them on the same Person object explicitly.
Regards
Manoj
Getter and setter methods in object oriented programming is for controlling the client not to change your variables in an unexpected behavior.
public Class Person{
private int gender;
private int length;
public Person(int gender,int length){
this.gender = gender;
this.length = length;
}
public int getGender(){
return this.gender;
}
public void setGender(int setGender){
if(setGender==1 || setGender == 0){
this.gender = setGender;
}else{
this.gender = -1;
}
}
public int getLength(){
return this.length;
}
public void setLength(int setLength){
if(setLength>100){
this.length = setLength;
}else{
this.length = -1;
}
}
}
like in this code sample, if you have some constraints about your variables and you need to dictate client to update these variables in your way, you should use getter and setter methods in order to control your variables updating way.
In this example, if the client's gender is different from 0 or 1 (if it enters invalid gender code) we are assigning -1 to its variable in order to see that invalid gender, length logic is also same.
Related
I've seen methods that return a different value types from an object depending on the type cast, similar to this:
(String) Object.get() //returns a string
(Integer) Object.get() //returns an int
etc.
I’m trying to replicate this behavior (for learning purposes) by creating an Employee class like this:
public class Employee {
String name;
int age;
public Employee (String name, int age){
this.name = name;
this.age = age;
}
public int getAge() {
return age;
}
public String getName(){
return name;
}
}
Now, let's assume I create a new Employee object:
Employee tomJones = new Employee("Tom Jones", 38);
Is it possible to somehow do this (see below)?
(String) tomJones.get() //returns “Tom Jones”
(Integer) tomjones.get() //returns 38
I'm trying to replicate some behavior that I've previously seen in code and not having all the problem's details makes it quite hard for me as a beginner to come up with something. So, I tried using different interfaces and some lambdas, but only managed to make a mess, with no result.
That is not possible and if you are trying to overload the method then the number of parameters in two methods should be different or the data types of the parameters or the Order of the parameters.
so I have been trying to understand what property exactly mean. I have searched for previously asked Q/A in stackoverflow and other website but the answers that I came across were not specific as to whether fields(instance variables) that are modified with setters and getters are also called properties.
The definition I came across was "a combination of setters and getters methods that modify fields of an object"
Below is just a small piece of code to make you understand my question better if you need more clarification.
//property?
String name;
//property?
public void setName(String n){
name = n;
}
//property?
public String getName(){
return name;
}
Properties means any members that belongs to the class. It could be variable, objects of other/ same class, methods of that class etc.
basically getter/setter are used for those member variables only.
Local variables are properties of that method that it belongs to and not property of the class.
In the OOP world, "property" has a rather broad sense and its specific meaning depends on the context. Generally, it is an attribute of an entity; ith may be a name or an age of a person, a color of a flower, a height of a building etc. A property has its name and its value (e.g. flower.color = red -- here color is the name, and red is the value), the value may belong to different types (or classes): a string, a number, a person, an enterprise... It may have a constant value (that never change during the lifetime of the owner (the entity it belongs to)) or it may have a variable value that can be changed by the user. In the software area it can be talked about at a conceptual level of the domain analysis and the software design; in this case people usually don't care how exactly it would be implemented. As well, it may be used at the level of concrete implementation (program code), and then the means to implement this concept depend on the programming language.
In Java, for example, when we say 'property' we usually mean a field (variable) of an object and a couple of methods (or a single method for read-only properties) to access its value (getter and setter):
class Person {
private String name; // the field to hold the value
public Person(String name) { // Constructor
this.name = name // The name is given at the moment it's been born
}
public String getName() { return Name; } // getter
// No, name can't be changed after it's been born -- it's a read-only property, thus no setter
// public void setName(String name) { this.name = name; } // otherwise the setter would look like this
}
In such a case, a user can acces the value of the property with the following code:
System.out.println(thisPerson.getName());
Other languages (like C#, for example) have means to code properties in somewhat more convenient way:
class AnotherPersonType {
private string name // a field to hold the value
public string Name
{
get => name; // getter, the same as "return this.name;"
set => name = value; // setter, the same as "this.name = value;"
}
}
.....
anotherPerson.name = "John"; // It looks like an assignment,
// but in fact, the setter is invoked
I am learning Java at University but I am struggling to understand why you would assign a variable to itself inside a constructor.
This is example code:
private String name;
private int age;
private boolean student;
private char gender;
public Person(String name, int age, boolean student, char gender)
{
this.setName(name);
this.age = age;
this.student = student;
}
I am struggling to understand the purpose of 'this.age = age' and 'this.student = student'. These values are already assigned to whatever they hold so why would you need to do that? My only theory is that it is to initialize the variable but I'm not sure.
You are not assigning the variable to itself, this.VAR and VAR are different variables.
When using a class in Java, you can refer to your attributes by using the this prefix. In many methods the this prefix is optional because there is not any method parameter with the same name. However, when a method has variables that have the same name than the class attributes, it is mandatory to use the this prefix to differentiate between the class attribute and the method parameters (otherwise the most local variable - the method parameter - hides the most global one - the class attribute).
So when you are using:
this.age = age
you are initializing your class attribute to the value of the method parameter called age.
Notice that you can avoid using the this prefix if the method parameters have always different names than the class attributes:
private String name;
private int age;
private boolean student;
private char gender;
public Person(String name, int ageParam, boolean studentParam, char genderParam){
setName(name);
age = ageParam;
student = studentParam;
gender = genderParam;
}
Personally, I think that using the this prefix is more polite because you can quickly look if you are modifying your class attributes and the method parameters preserve its useful name (which is better to document and understand the code).
The critical point here is that there are two variables called age. The first is the local variable which is a parameter to the constructor; the second is the instance variable of the Person class.
Inside the constructor, the parameter hides the instance variable, so just writing age will always refer to the parameter. However, if you write this.age, you must be referring to the instance variable. Thus:
this.age = age
assigns the value of the constructor parameter to the instance variable.
This is only because of naming conventions that you have this, in fact this is 100% the same :
private String name;
private int age;
private boolean student;
private char gender;
public Person(String nnn, int aaa, boolean sss, char ggg){
this.setName(nnn);
this.age = aaa;
this.student = sss;
this.gender = ggg;
}
But with this, this. becomes useless, because age = a; is ok, that's why when there is a misunderstand possible you use this. to precise that it's the attribute of the class, different of the parameter of the constructor.
this.age = age , this.age is the variable associated with class Person's object (this keyword refers to the class' object reference) , and age is a local variable (it's scope is just within constructor definition) whose value that you are passing in the constructor to be assigned to the object's variable.
So when you call class's constructor when creating object :
Person p = new Person("name",22,true,'M');
the p object's age will be set as 22 .
If you would have used :
public Person(String name, int yearsOld, boolean student, char gender)
{
this.setName(name);
age = yearsOld;
//here you could avoid using this since local variable name is different and age will refer to class level's age .
this.student = student;
}
I am using QueryDSL in my project to return a list of Person groupBy LastName and no of persons with that lastName. Below is the Person.java
#Entity
class Person {
private String firstName;
private String lastName;
private boolean isCitizen;
private int age;
private int groupByCount; //Property to return groupByCount - could use Group tuple for this, but doing a research trying to set it as an object field.
//Constructors to support n! ways of object creation - where n is no of fields in the object
public Person(String lastName, int groupByCount){
this.lastName = lastName;
this.groupByCount = groupByCount;
}
public Person(int age, int groupByCount){
this.age = age;
this.groupByCount = groupByCount;
}
public Person(boolean isCitizen, int groupByCount){
this.isCitizen = isCitizen;
this.groupByCount = groupByCount;
}
// keeps going to cover all possible constructors - i want to avoid this for maintainability reasons - want to be able to build objects dynamically with different parameters
//Below is code for Getter and setters for above fields
}
The QueryDSL query which uses these Constructors are below.
personRepo.getQueryDSL().createQuery(person).groupBy(person.lastName)
.list(Projections.constructor(Alarm.class, person.lastName, person.count());
personRepo.getQueryDSL().createQuery(person).groupBy(person.age)
.list(Projections.constructor(Alarm.class, person.age, person.count());
personRepo.getQueryDSL().createQuery(person).groupBy(person.isCitizen)
.list(Projections.constructor(Alarm.class, person.isCitizen, person.count());
How to avoid writing those n! constructors for a class with n fields using QueryDSL ?? I tried Projections.bean like below, after removing the constructors in the Person class
personRepo.getQueryDSL().createQuery(person).groupBy(person.isCitizen)
.list(Projections.bean(Alarm.class, person.isCitizen, person.count());
It complains .count() is not a valid expression. It is notable to assign the value of count to groupByCount field in person object. How to set groupByCount of the person object with person.count() value using Projections.bean method ??
Thanks in Advance. Really appreciate your help.
I believe that Projections.fields is what you're looking for. Have the setter names in the POJO mirror the column names in the query - it looks like you already have this in place.
I chained .as method on top of .count to groupByCount attribute as shown below. This way I was able to avoid writing n! constructors.
personRepo.getQueryDSL().createQuery(person).groupBy(person.isCitizen)
.list(Projections.bean(Alarm.class, person.isCitizen,
person.count().as(person.groupByCount));
This is related to a Java homework assignment.
I've written a class for creating instances of Course Objects, each course has parameters like course name, max number of students and a room number. However for some of the classes the room is not known. Is there a way to initialize and a Course Object without the room number?
public class ITECCourse {
private String name;
private int code;
private ArrayList<String> students;
private int maxStudents;
private int room = 0;
. . .
//Constructor
public ITECCourse(String courseName, int courseCode, int courseMaxStudents, int room) {
this.name = courseName;
this.code = courseCode;
this.students = new ArrayList<String>();
this.maxStudents = courseMaxStudents;
this.room = room;
You have a few options:
You could create a second constructor that does not take a room number:
public ITECCourse(String courseName, int courseCode, int courseMaxStudents)
You could change room from and int to an Integer. This would allow a null value.
Either way, you'd want to add a method setRoomNumber() to allow the user to provide that value later.
Yes, you can overload the constructor. As well as the constructor that you have above you can add a new one to the class that would look like this:
public ITECCourse(String courseName, int courseCode, int courseMaxStudents) {
this(courseName, courseCode, courseMaxStudents, 0);
}
This would then allow you to not have the room default to a certain value in the case that it has not been set.
Another good thing about doing it this way is that by calling the other already existing constructor you're not running into the issue of repeating code everywhere (to set all the values).
See this question for more details on best practices
Add a second constructor that doesn't take (or set) the room number.