In Java why would you assign a variable to itself - java

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;
}

Related

Return different value types from an object, depending on the type cast

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.

Getters and Setters and this. keyword

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.

Can I change a variable of an object

I have a student object that can hold name and mark.
public class Student{
Public String name;
Public int mark;
public Student (int argMark, String argName)
{ mark=argMark; name=argName;}
}
when I create a student as :
Student john = new Student(70, "John");
I need to change the mark later while keeping the previous marks
Student temp = john;
temp.mark = 60;
when I print them out they both have 60 marks
System.out.println(temp.mark);
System.out.println(john.mark);
the system shows the answer of : 60 for both of them
I know I can extend a class and have a method for get, set methods and override it, but this is not acceptable for my assignment. Is there any other way to do this?
You can create copy constructor and by doing that you can have new reference with the same attribute values in your temp. Currently John and Temp have same reference and change in one will get reflected in other.
public Student (Student student) {
this.mark = student.getMark();
this.name = student.getName();
}
Few suggestions,
Use getter and setter methods instead of accessing variables directly.
Follow naming conventions. i.e. start variable name with lower case.
When you say
Student Temp = John; // <-- typo for John
you assign a reference to the same instance that Jhon references. Based on your question, you expect a second instance. Something like
Student Temp = new Student(John.Mark, John.Name);
Also, by convention Java variable names start with a lower case letter.

How to use an object without knowing the objects' name

I'm not too sure how to word this so it makes sense, but I'll try my best.
Say I have 2 classes. My main class, and a Person class.
My main class will create some Objects from the Person class like this
public class Example {
static Person bob = new Person(23);//Age
static Person fred = new Person(34);
static Person John = new Person(28);
//..and so on
public static void main(String args[]){
..
}
}
and in my Person class..
public class Person{
private int age;
public Person(int age){
this.age = age;
}
public int getAge(){
return this.age;
}
}
Now, if I wanted the age of fred, I'd just call Fred.getAge();.
But, in my program, I don't know what person I'm getting the age of. It randomly selects one, and I need to get the name without directly calling the object. For example, I would have something like this in my Person class:
public static Object getPerson(){
//Some code to get a random integer value and store it it Var
switch(Var){
case 1:
return bob;
case 2:
return fred;
case 3:
return john;
}
}
What I would expect this to do is return an Object that I could then use like this:
public static void main(String args[]){
System.out.println(Person.getPerson().getAge());
}
What I thought that would have done was first call getPerson() which randomly returns either bob, fred, or john, and then it would call getAge(). So if getPerson() returned fred then it would be the same as doing fred.getAge();
Now, this doesnt work, and this was the only way I thought of that made sense to me.
How do I do this so it actually does what I want?
I'm very new to Java, and OOP, and this is my first time really working with different Objects. So I'm sorry if I'm using the wrong terms and explaining things weirdly.
Change
public static Object getPerson(){
to
public static Person getPerson(){
You can't call getAge on an Object, because the Object type does not have getAge() defined.
Why not put the name as a property of the Person class?
class Person {
// ... your existing code for age...
private String name;
String getName() { return name; }
// add name to constructor...
public Person(String name, int age) {
// set them up here...
}
}
The way I see it, is that name is for you as a human, but variables john are irrelivant to the program and computer.... you can even use p1 = Person("Joe", 42);
To get a person by age, you can use a Map with age as key, and person as value.
It could be the case that this is a misunderstanding, but how I'm interpreting the issue is as follows:
You need a (better) place to store all of your Person objects instead of having them as static variables.
You need a way to randomly select from wherever you're storing those objects.
Let's address the main issue first. You're creating these as static variables when they probably shouldn't be; they should just be created as entries into an array.
The way to do this is through this declaration:
Person[] people = new Person[] {new Person(23), new Person(34), new Person(28)};
The main issue now is that you have no way to refer to which person's age belongs to whom since you haven't attached a name field to any of these instances. You could do that easily:
public class Person {
private String name;
private String age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
// getters for name and age
}
...then you can instantiate your Person with two values.
new Person("Bob", 23);
Now that we've addressed one concern (which was where to store the people in the first place), now we need a way to randomly access them.
For that, we can use Random#nextInt().
Random rand = new Random();
System.out.println("Person's age - " + people[rand.nextInt(people.length)]);
This will randomly pull a Person out of the array and print their age.
If you want to get a random person within the person class you could store a reference to each person created, and then select randomly from that list
public class Person {
// A List of every Person Created.
private static final List<Person> allPeople = new ArrayList<People>();
// A source of random numbers
private static final Random rand = new Random();
...
public Person(int age) {
...
// Every time we create a new Person, store a reference to that person.
addPerson(this);
}
// synchronized as ArrayLists are not thread safe.
private static synchronized addPerson(Person person) {
allPeople.add(person);
}
...
public static Person getRandomPerson() {
// Get a random number between zero and the size of the list.
int random = rand.nextInt(allPeople.size() -1);
return allPeople.get(random);
}
Now this code is not what I would do in a production environment but it the question sounds like an exercise. A better way would be to store the people created in a List in your Example class. But trying to answer the question as you asked it.

How can I initialize an Object when one of the parameters is TBD

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.

Categories

Resources