Conditional static field possible? - java

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.

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.

List add function does not operate properly?

public static void main(String[] args) {
// TODO Auto-generated method stub
List<item> l = new ArrayList<item>();
List<Integer> ll = new ArrayList<Integer>();
for (int i = 0; i < 10; i++) {
l.add(new item(i,i));
ll.add(i);
}
System.out.println(l.get(4).getWeight());
System.out.println(ll.get(4));
}
public class item {
private static int value;
private static int weight;
public item(int val, int w) {
setValue(val);
setWeight(w);
}
public static int getValue() {
return value;
}
public static void setValue(int value) {
item.value = value;
}
public static int getWeight() {
return weight;
}
public static void setWeight(int weight) {
item.weight = weight;
}
}
This is my code, and then item is class take two paratemers. But when I add the item into list, the elelments in list have same value(in this case it is 9). For Integer, there is no problem. I think I miss some critical parts of java feature.
Any help appreciated, thank you in advance.
All of your methods and members of item are static. That is, they belong to the item class, rather than a specific instance of that class. The static members are shared among every instance of the class, and so every new item you create is using the same set of data. You will want to make them not be static.
Check out the following official tutorials for more info, they are concise and well-written and will help you:
Non-static, member variables: Declaring Member Variables
Non-static, methods: Defining Methods
static class members: Understanding Class Members
Once you have done this, as Takendarkk astutely points out in a comment, be sure to use this.value = ... instead of item.value = ... (no longer valid) or value = ... (uses local scope value instead of member).

DRY maxima tracking

Suppose I am importing table entries, where a single entry can be stored in a class:
class Foo {
int i1;
int i2;
double d1;
}
After the import is complete, I will need to have access to the imported values themselves, as well as to their normalized versions. So far, I have implemented this functionality as follows:
class FooWithMaxTracking {
private int i1;
private static int i1_max=0;
public void setI1(int value){
this.i1 = value;
if (value > i1_max) { i1_max = value; }}
public int getI1(){
return i1;}
public double normI1(){
return i1/((double)i1_max);}
private int i2;
private static int i2_max=0;
public void setI2(int value){ <code identical to written above> }
public int getI2(){ ... }
public double normI2(){ ... }
// and another set of similar 2 variables & 3 functions for 'double d1'
}
In this implementation I strongly dislike the fact that I had to write the same code many times (only three in this example, but about ten times in the real project). Is there any way to make the code more DRY ("don't repeat yourself")?
If you do not mind a slight loss of performance, you can put all the maxima in a static Map, define a class that holds a getter, a setter, and a norm methods, and replace the individual variables with instances of that class:
private static Map<String,Object> max = new HashMap<String,Object>();
private static class IntMaxTrack {
private final String key;
private int value;
public IntMaxTrack(String k, int v) {
key = k;
value = v;
max.put(key, value);
}
public int get() { return value; }
public void set(int v) {
int m = ((Integer)max.get(key)).intValue();
value = v;
if (value > m) {
max.put(key, value);
}
}
public double norm() {
int m = ((Integer)max.get(key)).intValue();
return val / ((double)m);
}
}
Make a similar class for double, i.e. DblMaxTrack Now you can replace primitives with instances of these classes, and call their get, set, and norm from the corresponding methods of your class.
What about defining one class with the necessary code, like:
public class Bar {
private int i1;
private static int i1_max = 0;
public void setI1(int value) {
// ...
}
public int getI1() {
// ...
}
public double normI1() {
// ...
}
}
And using it sevearl times, like:
class FooWithMaxTracking {
one = new Bar();
two = new Bar();
three = new BarForDouble();
}

Java global variables not updating in new class

I am currently programming a simple Android app that asks the user a series of questions and then tells them how many they got correct. I have one class that has a global variable (called "score") that is private and I have getter and setter methods for it. When the user gets the answer correct, the score is incremented (locally) and updates from 0 to 1 in that class. However, when I try to use the getScore() method I have created, to access the value of score in another class, it says scores value is 0, and not 1.
E.g.
public ClassA {
private int score = 0;
public void setScore(int s) {
this.score = s;
}
public int getScore() {
return score;
}
}
public ClassB {
private ClassA eg = new ClassA();
private int score = eg.getScore();
}
I've been stuck on this for a while and really don't know why this isn't working.
Help is much appreciated.
Thanks.
Set the Score, before getting the Score.
public ClassB {
private ClassA eg = new ClassA();
eg.setScore(5);
private int score = eg.getScore();
System.out.println(score);
}
Hope this helps.
Make sure to actually increment the score in ClassB. Also make score a static variable.
Edit your code like this :
public ClassA {
private static int score = 0;
public void setScore(int s) {
this.score = s;
}
public int getScore() {
return score;
}
}
public ClassB {
private ClassA eg = new ClassA();
int score = 0;
if(answerCorrect())
{
score++;
eg.setScore(score);
}
private int realScore = eg.getScore();
System.out.print("Final Score : "+realScore);
}
And, create a method answerCorrect() to check whether answer is correct or not, this method will return boolean.

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.

Categories

Resources