Using private variables [duplicate] - java

This question already has answers here:
What is the point of setters and getters in java? [duplicate]
(14 answers)
Getter-Setter and private variables [duplicate]
(5 answers)
Closed 8 years ago.
public class Addition
{
private int number1,number2;
public void setNumber1()
{
}
public int getNumber1()
{
}
public void setNumber2()
{
}
public int getNumber2()
{
}
}
what is point of keeping variables private if i can access them using public getter and setter method.

Having a setter method allows you to implement logic prior to assigning a value to the private variable. This prevents other code from assigning arbitrary values to your private variable which might cause your object to be in an invalid state. For example:
Without setter method
public class Man {
public int height;
}
//...some code
man.height = -1; // BOOOM!
With setter method:
public class Man {
private int height;
public void setHeight(int h) {
this.height = h >= 0 ? h : 0;
}
}
//...
man.setHeight(-10); // Will keep the man in valid state

You can add a validation in setters.
private int age;
public void setAge(int a){
if(a>0){
this.age = a;
}else{
this.age = 0;
}
}

You can assume that making a variable as private is a basic guideline for coding. If you make them public it is accessible for outside world and any one can modify it.
Suppose that number1 should always be +ve int in your case. So the setter method will have check and help you to avoid setting -ve values to it. See below:
public void setNumber1(int number)
{
if(number >= 0)
{
this.number1 = number
}
else
{
//you can throw exception here
}
}

It follows a important Object Oriented Property Encapsulation .
For example I have a integer variable price with public modifier(Any one can access it)
public int price;
now we know that price can not negative but it is public so we don't have any control in this. Now see it with respect to encapsulation
private int price;
public void setPrice(int price)
{
if(price>0)
this.price=price
}
Here we have control, no one can set negative value of price. This is the power of Encapsulation "Giving Control".

Related

Return enum into toString and accessor methods

As the code showed below, I'm trying to make user input the speed (1,2,3) into the enum and return the input back into toString method.
private enum speed
{
SMALL(1),
MEDIUM(2),
FAST(3);
private int speedValue;
private speed (int speedValue)
{
this.speedValue = speedValue;
}
public int getSpeed()
{
return speedValue;
}
public static Optional<speed> get(int speedValue)
{
return Arrays.stream(speed.values())
.filter(spe -> spe.speedValue == speedValue)
.findFirst();
}
}
private boolean on;
The problem is when I put this.speed = speed or any other stuff, the speed class will be missing with error "speed cannot be resolved or is not a field"
This happened the same in the toString class.
public Fan(speed seed, boolean on)
{
speed.get() = seed; //what shall i put here
this.on = on;
}
public boolean getOn()
{
return this.on;
}
public String toString()
{
return speed; //what shall i put here
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("Please enter speed");
int sp = sc.nextInt();
System.out.println("On/Off");
boolean on = sc.nextBoolean();
Optional<speed>spe = speed.get(sp); //getting enum integer values
System.out.println(spe.get());
Fan fan = new Fan(sp, on)
Is there any solution that I would be able to return the integer value of enum into the public class and toString class?
With private enum speed {...} you declare the enum type speed, but you never declare a field of this type.
If you want to have a field named speed of this enum type you must declare it with private speed speed;.
This looks confusing and therefore I suggest that you follow the Java naming conventions where names of classes start with an uppercase letter (and enum types are classes).
That means your enum type should be written as
public enum Speed {
SMALL(1),
MEDIUM(2),
FAST(3);
private int speedValue;
private Speed (int speedValue) {
this.speedValue = speedValue;
}
public int getSpeed() {
return speedValue;
}
public static Optional<Speed> get(int speedValue) {
return Arrays.stream(Speed.values())
.filter(spe -> spe.speedValue == speedValue)
.findFirst();
}
}
Your Fan class needs these fields:
private boolean on;
private Speed speed;
The constructor is
public Fan(Speed seed, boolean on) {
speed = seed;
this.on = on;
}
or, assuming that the parameter name seed is a spelling mistake and it should be speed instead:
public Fan(Speed speed, boolean on) {
this.speed = speed;
this.on = on;
}
The other methods:
public boolean getOn() {
return this.on;
}
public String toString() {
return speed.toString();
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("Please enter speed");
int sp = sc.nextInt();
System.out.println("On/Off");
boolean on = sc.nextBoolean();
Optional<Speed> spe = Speed.get(sp); //getting enum integer values
System.out.println(spe.get());
Fan fan = new Fan(spe.get(), on);
// note that the above line produces not output. Why should it?
// if you want to see the result of f.toString() you need to print it out:
System.out.println(fan.toString());
// or shorter (since println() calls toString() automatically):
System.out.println(fan);
}
Note 1: I also changed the placement of the opening braces ({) to follow general Java conventions - for seasoned Java programmers this looks less surprising.
Note 2: as Mark Rotteveel correctly remarks: the Fan class has a public constructor and therefore the Speed enum should also be declared public. Otherwise no one outside of the Fan class will be able to construct a new Fan object.

How to know how many times a method has been called from main class?

My problem is to find out how many times the weight() method is being called from the main class. I should calculate it in the totalWeightsMeasured() method.
The output of the code should be 0,2,6. (EDIT// I had earlier here 0,2,4 but the output should really be 0,2,6)
But I just don't have any idea how can you calculate it and I have tried to google and everything but I just don't know how to do it. (and you are not supposed to add any more instance variables)
CLASS:
public class Reformatory
{
private int weight;
public int weight(Person person)
{
int weight = person.getWeight();
// return the weight of the person
return weight;
}
public void feed(Person person)
{
//that increases the weight of its parameter by one.
person.setWeight(person.getWeight() + 1);
}
public int totalWeightsMeasured()
{
return 0;
}
}
MAIN:
public class Main
{
public static void main(String[] args)
{
Reformatory eastHelsinkiReformatory = new Reformatory();
Person brian = new Person("Brian", 1, 110, 7);
Person pekka = new Person("Pekka", 33, 176, 85);
System.out.println("total weights measured "+eastHelsinkiReformatory.totalWeightsMeasured());
eastHelsinkiReformatory.weight(brian);
eastHelsinkiReformatory.weight(pekka);
System.out.println("total weights measured "+eastHelsinkiReformatory.totalWeightsMeasured());
eastHelsinkiReformatory.weight(brian);
eastHelsinkiReformatory.weight(brian);
eastHelsinkiReformatory.weight(brian);
eastHelsinkiReformatory.weight(brian);
System.out.println("total weights measured "+eastHelsinkiReformatory.totalWeightsMeasured());
}
}
The trick is to use the existing instance variable weight, which is not used yet, as the counter.
public class Reformatory
{
private int weight;
public int weight(Person person)
{
int weight = person.getWeight();
this.weight++;
// return the weight of the person
return weight;
}
public void feed(Person person)
{
//that increases the weight of its parameter by one.
person.setWeight(person.getWeight() + 1);
}
public int totalWeightsMeasured()
{
return weight;
}
}
As pointed out by Satya, introduce a static counter variable as follows:
public class Reformatory {
private static int weightMessurements = 0;
public int weight(Person person) {
// increment counter
weightMessurements++;
// messure weight
return person.getWeight();
}
public void feed(Person person) {
// increase weight
person.setWeight(person.getWeight() + 1);
}
public int totalWeightsMeasured() {
int result = weightMessurements;
// reset counter so that the output matches 0,2,4 instead of 0,2,6
weightMessurements = 0;
return result;
}
}
I think I have the solution which will not require you to add any instance or static variables whatsoever.
Since inside this block of code you already have a local variable named weight.
public int weight(Person person) {
int weight = person.getWeight();
/return the weight of the person
return weight;
}
Therefore, in the scope of that method you have two variables called weight but one is an instance variable and one is a local variable. You can differentiate between the two by writing this.weight for the instance variable, or just weight for the local variable.
All you need to do is to rename the current instance variable weight to weightsMeasured so that it clearer which variable you are referring to.
And then simply add weightsMeasured++ into the weight(Person person) method and return weightsMeasured from the totalWeightsMeasured() method.
So the final code would look like this:
public class Reformatory
{
private int weightsMeasured; //Renamed instance variable
public int weight(Person person) {
weightsMeasured++; //instance variable incremented
int weight = person.getWeight(); //This is the local variable
//return the weight of the person
return weight;
}
public void feed(Person person) {
//that increases the weight of its parameter by one.
person.setWeight(person.getWeight() + 1);
}
public int totalWeightsMeasured() {
//return the number of times the method was called
return weightsMeasured;
}
}
So rather than adding any new variables, we just renamed the existing instance variable that wasn't being used.
A slightly modified and shorter version of the above answers is:
public class Reformatory {
private int weight;
public int weight(Person person) {
this.weight++; //count the number of times when the weight gets measured.
return person.getWeight();
}
public int totalWeightMeasured() {
return weight; //return the number of times when the weight gets measured.
}
}

The type of the expression must be an array type but it resolved to float

I hit a bump when I'm doing my Java code. I feel like I somehow got the concept messed up, like I not sure for this:
void setScore(float[] sco)
{
sco = score;
}
public void setScore(float sco, int id)
{
sco[id] = score;
}
The error message corresponds to "sco[ID] = score; "
The type of the expression must be an array type but it resolved to float
I'm confused what I should put in the bracket, the book asks me to put "float[] score" instead of "float[] sco", but it doesn't work, so I edited a bit after several trials. This part of coding generally describes the method of overloading that stores the score for 5 subjects.
And this is my whole coding:
public class Score {
float math, english, physics, chemistry, biology;
float sum, average;
float[] score;
int id;
void setMath(float Math) {
math = Math;
}
void setEnglish(float English) {
english = English;
}
void setPhysics(float Physics) {
physics = Physics;
}
void setChemistry(float Chemistry) {
chemistry = Chemistry;
}
void setBiology(float Biology) {
biology = Biology;
}
void setSum(float Sum) {
sum = math + english + physics + chemistry + biology;
}
void setAverage(float Average) {
average = sum / 5;
}
float getMath() {
return math;
}
float getEnglish() {
return english;
}
float getPhysics() {
return physics;
}
float getChemistry() {
return chemistry;
}
float getBiology() {
return biology;
}
float getSum() {
return sum;
}
float getAverage() {
return average;
}
public void setScore(float[] sco)
{
sco = score;
}
public void setScore(float sco, int id)
{
sco[id] = score;
}
}
Now my problem solved! Since I just changed like this:
public void score()
{
}
public void setScore(float[] score)
{
sco = score;
}
Can anyone tell me why now the problem resolved? Will really appreciate a lot!
You are assigning a value of the class variable score to the parameter sco when you should do the opposite. In other words:
Your code says:
sco = score;
But what you should do is:
score = sco;
In both functions you need to switch the order of score and sco so that score gets the value of sco.
As far as your error, in setScore(float sco, int id) you defined parameter sco as a float but you are trying to access it as an array (by saying sco[Id] = score). That is why you are getting your error message.
The type of the expression must be an array type but it resolved to float
Like I said, you can fix this by switching the order again:
sco[Id] = score;
Into:
score[Id] = sco;
EDIT:
As far as this part:
I'm confused what I should put in the bracket, the book asks me to put "float[] score" > instead of "float[] sco", but it doesn't work, so I edited a bit after several trials. This > part of coding generally describes the method of overloading that stores the score for 5 > subjects.
Since you wanted to know how to use the same names for parameters and class variables, as #Smutje mentioned, you should use the keyword this.
That way, there is no ambiguity with which score you are using:
this.score belongs to your class called Score and can be used in any function inside the class. It is visible to everything inside the class.
score is a function parameter local to a function setScore() and can only be used inside setScore(). It is only visible inside the function.
Therefore, including everything mentioned, you should make the following changes:
Change:
public void setScore(float sco, int id)
{
sco[id] = score;
}
void setScore(float[] sco)
{
sco = score;
}
To:
public void setScore(float score, int id) // changed sco to score
{
this.score[id] = score; // switched order, added keyword this
}
void setScore(float[] score) // changed sco to score
{
this.score = score; // switched order, added keyword this
}
I guess you mixed up the variable names:
void setScore(float[] sco)
{
sco = score;
}
public void setScore(float sco, int id)
{
sco[id] = score;
}
because score is the field which you want to populate and sco is the parameter which you want to populate score with. The code above does not change any contents of Score, so try to swap it to
void setScore(float[] sco)
{
this.score = sco;
}
public void setScore(float sco, int id)
{
this.score[id] = sco;
}
it also would have helped if you have started using this to mark instance fields explicitly.
Check again how you set your score:
void setScore(float[] sco)
{
sco = score;
}
What is sco? What you want to assign to what?
You are assigning your local variable to the parameter. It should be the other way around. (this.score = sco)

Superclass resets already active objects

It's a little bit difficult but i'll try to explain my problem. I've created a program with a superclass (RichIndustrialist) two subclasses (PredecessorRichIndustrialist and another one I didn't add) and 4 subclasses to these subclasses (CrazyRichIndustrialist and another 3). Now, the program is too difficult to explain but the problem is actually simple. My constructor is in the superclass and every subclass use it to initilize. Every time I create a new subclass object like CrazyRichIndustrialist, it resets all the already existed subclasses (from any subclass) to the value of the new object. I don't know how to fix this. Thank you in advance...
RichIndustrialist:
package Mortal;
import java.util.Random;
public class RichIndustrialist implements Mortal {
private static String Name;
private static double holdings;
private static int Alive;
public RichIndustrialist(String Rich_Name, double Rich_holdings) {
this.Name = Rich_Name;
this.holdings = Rich_holdings;
this.Alive = 1;
}
public int isAlive() {
return (this.Alive);
}
public void setHoldings(double new_holdings) {
this.holdings = new_holdings;
}
public double getHoldings() {
return (this.holdings);
}
public String getName() {
return (this.Name);
}
public void die() {
this.Alive = 0;
}
public void getHeritage(double heritage) {
this.holdings = this.holdings + heritage;
}
}
PredecessorRichIndustrialist:
package Mortal;
import java.util.Arrays;
public class PredecessorRichIndustrialist extends RichIndustrialist {
private static String Name;
private static double holdings;
private RichIndustrialist[] successors = {};
private static int Alive;
public PredecessorRichIndustrialist(String Rich_Name, double Rich_holdings) {
super(Rich_Name,Rich_holdings);
}
public void die() {
super.die();
}
public void Inheritance(double holdings, RichIndustrialist[] successors) {
int i = 0;
while (i < successors.length) {
int Alive = successors[i].isAlive();
System.out.println(Alive);
if (Alive == 0) {
removeSuccessor(successors[i]);
i++;
} else {
i++;
}
}
}
public void addSuccessor(RichIndustrialist new_successor) {
RichIndustrialist[] new_successors = new RichIndustrialist[successors.length + 1];
if (successors.length == 0) {
new_successors[0] = new_successor;
successors = new_successors;
} else {
for (int i = 0; i < successors.length; i++) {
new_successors[i] = successors[i];
}
new_successors[new_successors.length - 1] = new_successor;
}
this.successors = new_successors;
}
public void removeSuccessor(RichIndustrialist removed_successor) {
RichIndustrialist[] new_successors = new RichIndustrialist[this.successors.length - 1];
int j = 0;
for (int i = 0; i < this.successors.length; i++) {
if (!this.successors[i].equals(removed_successor)) {
new_successors[j] = this.successors[i];
} else {
j--;
}
j++;
}
}
public RichIndustrialist[] getSuccessors() {
return successors;
}
}
CrazyRichIndustrialist:
package Mortal;
import java.util.Random;
public class CrazyRichIndustrialist extends PredecessorRichIndustrialist {
private RichIndustrialist[] successors = {};
private static String Name;
private static double holdings;
private static int Alive;
public CrazyRichIndustrialist(String Rich_Name, double Rich_holdings) {
super(Rich_Name,Rich_holdings);
}
public void die() {
super.die();
Inheritance(getHoldings(),getSuccessors());
}
public void addSuccessor(RichIndustrialist new_successor) {
super.addSuccessor(new_successor);
}
public void removeSuccessor(RichIndustrialist removed_successor) {
super.removeSuccessor(removed_successor);
}
public void Inheritance (double holdings , RichIndustrialist[] successors) {
super.Inheritance(holdings, successors);
for (int i=0; i<successors.length-1; i++)
{
double random = new Random().nextDouble();
double amount = this.holdings * random;
successors[i].getHeritage(amount);
holdings = this.holdings - amount;
}
successors[successors.length-1].getHeritage(this.holdings);
this.holdings = 0;
}
public String getName(){
return super.getName();
}
public double getHoldings(){
return super.getHoldings();
}
public RichIndustrialist[] getSuccessors(){
return super.getSuccessors();
}
public void setHoldings(double new_holdings){
super.setHoldings(new_holdings);
}
public int isAlive() {
return super.isAlive();
}
public void getHeritage(double heritage) {
super.getHeritage(heritage);
}
}
Most of your fields are static. What that means is that all the instances of your classes share the same value. When you call the constructor, the static fields are modified, which affects all the existing instances.
For example:
this.Name = Rich_Name;
should actually have been written:
RichIndustrialist.Name = Rich_Name;
You can read about the difference between instance and class (or static) members in this tutorial.
The following fields should be declared as non-static. When these fields are declared as static each RichIndustrialist instance will share these fields and their assigned values. Declaring them as non-static allows each RichIndustrialist instance to have its own copy of these fields, which is autonomous from the other instances of RichIndustrialist.
private String Name;
private double holdings;
private int Alive;
Here is a good description of static from the Java Tutorial
Sometimes, you want to have variables that are common to all objects.
This is accomplished with the static modifier. Fields that have the
static modifier in their declaration are called static fields or class
variables. They are associated with the class, rather than with any
object. Every instance of the class shares a class variable, which is
in one fixed location in memory. Any object can change the value of a
class variable, but class variables can also be manipulated without
creating an instance of the class.
Your properties/variables are static. and we know static variable are shared between all the objects.
That is the reason the last object will replace the existing value of your variables
Suggestion:
change your static modifier to instance modifier
From
private static String Name;
private static double holdings;
private static int Alive;
To
private String Name;
private double holdings;
private int Alive;
I am sure your problem will resolve.
You are declaring the Name member field in all of your classes, you should only declare it in the super-class and let the other sub-classes (re)use it.
Furthermore, you declared the field as static, all instances of your class will use the same field, which is probably not what you intended, so remove the static part.
Same goes for all of your other member fields.
Note: do not start the member fields with a capital: Name should be defined and used as name. Class names on the other hand should start with a capital! This is a generically accepted Java convention and keeps things more clear/separated.

Conditional static field possible?

I have a class as follows:
public class Level{
public int level;
public int score;
}
Basically, I would want to behave the score as static for a particular value of level. For example,in a competition, a team has multiple competitors, each contributes to the score for a particular level. I wish to add each of their contributions to the score whenever level is equal.
I was wondering if it could be done this way.
EDIT
I feel the problem will be more easy to visualise if I change my Class a bit like this:
public class Participants{
public String name;
public String teamID;
public int[] levelScores; //where the level is denoted
//by the index of this array
}
Now, for all participants with the same teamID, the levelScores must be shared and contribution of any participant object with same teamID must be added to the corresponding levelScore.
That involves changing the code and is unlikely to be worth the extra complexity IMHO. I would just use the code you have (and make the fields final if you can)
abstract Level {
public int getLevel();
public int getScore();
}
class LevelOne extends Level {
public int getLevel() { return 1; }
public int getScore() { return LEVEL_ONE_SCORE; }
}
class LevelTwo extends Level {
private final int score;
public int getLevel() { return 2; }
public int getScore() { return score; }
}
class LevelN extends Level {
private final int level;
private final int score;
public int getLevel() { return level; }
public int getScore() { return score; }
}
Change to using accessor methods (getters/setters) and do this:
class Level {
private static int levelOneScore;
private int level;
private int score;
public int getLevel (
return level;
);
public int getScore() {
return level == 1 ? levelOneScore : score;
}
public void setScore(int score) {
if (level == 1) {
levelOneScore = score;
} else {
this.score = score;
}
}
}
I've omitted the setLevel() method because it feels like level should be final. If level is final, you could (and should) implement this as a separate class that overrides the get/set score methods.
Just had a look at your profile... you're learning by yourself, so I'm assuming that you won't use anything like JNDI, Spring or any other kind of container or framework.
The simplest way of doing this without resorting to a completely static class hierarchy is to use the level as a key to reference the score:
public class Level {
private static Level instance = null;
private static Map<Integer, Integer> scoreMap = new HashMap<Integer, Integer>();
public static Level getInstance() {
if (instance == null) {
instance = new Level();
}
return instance;
}
public static int getScore(int level) {
return scoreMap.get(level);
}
public static void setScore(int level, int score) {
scoreMap.put(level, score);
}
}
Any class that uses Level will do it in this way:
int myLevel = 1; // I assume the class will know its level somehow
Level scoreKeeper = Level.getInstance();
int myScore = scoreKeeper.getScore(myLevel);
This solution uses the horrible Singleton anti-pattern, but it will get you going with what you probably want to achieve.
No, I don't think it is possible. static is only one copy shared across application. You need to think about re-design your code.
STATIC DATA is shared by all the instances of the class. your level 1 instance would share it so does your levelN:).
There is a lot of overhead associated with this answer, but you can create a score class that has one field int score and point all level objects where level = 1 at the score object. That way every time the score is changed, it is changed for all objects that point to it.
It is not possible to do it the way you're thinking.
But it is possible to make a class with a single static method that returns the score to the appropriate input value.
The method:
public static int(int level) {
if(level==1) {
return //what you want.
}
}
I hope I helped.

Categories

Resources