In my below program i observe that the value of score variable is twice(999000 instead of 499500) it's expected value. Closer look at it suggests that the computation is done twice even though the flag gets set to true after the first invocation. Any idea what is going wrong here? The program is single threaded. Actual computation involves invoking a rest API, but for testing purpose i have removed it.
public class DataClient {
public static void main(String[] args) {
System.out.println(CalculationCache.getScore());
}
}
class CalculationCache{
static{
computeScore();
}
private static int score;
public static int getScore() {
computeScore();
return score;
}
private static boolean flag=false;
static void computeScore(){
if(!flag) {
//calculate the score
for (int i = 0; i < 1000; i++) {
score = score + i;
flag = true;
}
}
}
}
The issue is due to the ordering of class initialization. The static initializers are executed in the order they are defined. The variable flag is initialized only after computeScore() is invoked. Hence flag will be false when the method is called the second time. You might want to get rid of the static block
static{
computeScore();
}
if you want lazy initialization.
Related
I am having a few minor issues with my class methods which I am to increment sequentially. Basically my class compiles, there is a test class and when I run the tester to get the test results I do not get the desired output I am looking for and it is followed by an error message which I will provide below.
My question is when I create an object it starts off with the the prefix + counter but does not increment it right away, I want it to be so that it increments the first object created to 1001 right away and so on and so forth. These error messages are confusing me on how the expected value is something totally different from my desired output.
I have the prefix set and a counter which starts at 1000.
public static final String TICKET_PREFIX = "VAN";
public static int counter = 1000;
public ParkingTicket(){
ticketNumber = generateTicketNumber();
}
}
private String generateTicketNumber(){
ticketNumber = TICKET_PREFIX + counter++;
return ticketNumber;
}
Here is the code from the test class code block where the error is caught
#Test
public void testConstructorTicketNumberSEquential() {
ParkingTicket.resetCounter();
ParkingTicket ticket = new ParkingTicket("Adam White","VAN5225", "1A2B3C",20 );
ParkingTicket ticket2 = new ParkingTicket("Adam White","VAN5225", "1A2B3C",20 );
ParkingTicket ticket3 = new ParkingTicket("Adam White","VAN5225", "1A2B3C",20 );
assertEquals("VAN1001",ticket.getTicketNumber());
assertEquals("VAN1003", ticket3.getTicketNumber());
and this is the error message from the tester
testConstructorTicketNumberSEquential
---
org.junit.ComparisonFailure: expected:<VAN100[1]> but was:<VAN100[7]>
at org.junit.Assert.assertEquals(Assert.java:115)
at org.junit.Assert.assertEquals(Assert.java:144)
at ParkingTicketTest.testConstructorTicketNumberSEquential(ParkingTicketTest.java:238)
Also I have a method to reset the counter. I tried just returning the counter value but I am still getting an error
public static int resetCounter(){
int reset = counter;
return reset;
}
test for the reset counter
#Test
public void testResetCounter() {
ParkingTicket.resetCounter();
assertEquals(1000,ParkingTicket.counter);
}
test run error message
testResetCounter
---
java.lang.AssertionError: expected:<1000> but was:<1005>
at org.junit.Assert.fail(Assert.java:88)
at org.junit.Assert.failNotEquals(Assert.java:743)
at org.junit.Assert.assertEquals(Assert.java:118)
at org.junit.Assert.assertEquals(Assert.java:555)
at org.junit.Assert.assertEquals(Assert.java:542)
at ParkingTicketTest.testResetCounter(ParkingTicketTest.java:264)
You currently never set the counter back to the initial value inside of resetCounter(), and you never use the return value.
In my opinion, the resetCounter() should be a void method, and simply set counter back to an initial value which is contained in a constant.
I named this constant INITIAL_COUNTER:
public static final String TICKET_PREFIX = "VAN";
public static final int INITIAL_COUNT = 1000;
public static int counter = INITIAL_COUNT;
public static void resetCounter() {
counter = INITIAL_COUNT;
}
public static void main(String[] args) {
counter++;
counter++;
System.out.println(counter);
ParkingTicket.resetCounter();
System.out.println(counter);
}
Output:
1002
1000
Here from the example main I made you can see resetCounter properly resets counter back to 1000. Simply change the value of INTIAL_COUNT to change your default count value.
On another note, you wrote you expect VAN1001 to be the ticket value of your first new ParkingTicket("Adam White","VAN5225", "1A2B3C",20 ) when you should actually expect it to be VAN1000.
This is due to using a post-increment on count instead of a pre-increment on the line below:
ticketNumber = TICKET_PREFIX + counter++;
If you want the first ticket to start at 1001 instead, change count++ to ++count, which will increment count by 1 before assigning the ticketNumber value.
I'm just new to Java OOP, and I hardly understand about the class and stuff. I tried to write some code to understand but I didn't succeed. Here is my code, I expected it to return the number of eggs but I don't know why it returns nothing.
class EggCounter {
private int egg;
{
egg = 0;
}
public void eggAdd()
{
egg = egg + 1;
}
public void eggBreak()
{
egg = egg - 1;
}
public void eggAddDozen()
{
egg = egg + 12;
}
public int getEgg()
{
return egg;
}
}
public class EggTest
{
public static void main(String[]args)
{
EggCounter egg = new EggCounter();
egg.eggAdd();
egg.eggAddDozen();
egg.eggBreak();
egg.getEgg();
}
}
It does return 12. Replace the egg.getEgg(); line in your main method with System.out.println(egg.getEgg()); and you will notice it prints 12.
It is returning, it's just that you do nothing with the return value of getEgg. What you need to do is store it into the variable or do something with it. return <value> only returns the given value to the callee, you must store it to use it. Example:
int eggCount = egg.getEgg();
System.out.println(eggCount);
Here, the assignment of eggCount calls egg.getEgg(). The call resolves when the number of eggs is returned, which assigns the return value to eggCount. Finally, it will print out eggCount. If you need the result of egg.getEgg() later, you can simply just output the following:
System.out.println(egg.getEgg());
How this works is the method egg.getEgg() is called. The return value is then resolved, which is passed into the print statement. This gets rid of storing it into a variable you can use later.
I want create Boolean array in global, here code i tried to make
public class BettingHandler extends BaseClientRequestHandler
{
public static int player[] = new int [100];
public static int i;
public static boolean playerAct[];
public void handleClientRequest(User user, ISFSObject params)
{
RouletteExtension gameExt = (RouletteExtension) getParentExtension();
if (BettingHandler.player[BettingHandler.i] != -1)
{
trace("player problem");
BettingHandler.player[BettingHandler.i] = user.getPlayerId();
BettingHandler.playerAct[BettingHandler.i] = true;
i++;
}
trace("If this showed, no error");
}
}
In Eclipse not showed redcross sign in left this code
public static boolean playerAct[];
and here
BettingHandler.playerAct[BettingHandler.i] = true;
I make this for handler in SFS2X, so i check error in SFS2X zone monitor but unfortunately, this script just run till this
trace("player problem");
when remove this code
BettingHandler.playerAct[BettingHandler.i] = true;
script run till this
trace("If this showed, no error");
so i know something wrong with BettingHandler.playerAct[BettingHandler.i] = true;, How could I fix my code?
You never initialized the array but you are trying to use it.
public static boolean playerAct[] = new boolean[100];
Funny thing:
public static int player[] = new int [100];
public static int i;
public static boolean playerAct[];
The first array, there you actually create an array for 100 elements.
You omit that step for your second array. And you are really surprised that the second gives you problems?
Besides: whatever framework your are working with; maybe you should first step back and learn some more about the basics of Java. For example, the above code might work when fixed; but doing everything with public static variables ... looks very much like bad design.
I want to modify a non-static variable from inside my static main function and then return that modified value for use elsewhere. Here is the code:
package servletPackage;
public class Blah {
private int count = 5;
public static void main(String[] args) {
Blah blah = new Blah();
blah.count = 10;
}
// return Count
public int getCount()
{
return count;
}
}
However, when I access this count from a different file, I get 5 when I want to get 10. Its like count will only stay 10 inside the main, then it changes back to 5. How do I change it so that I can return 10 instead? I tried to get rid of the static in main but then it wouldn't run. Any help is appreciated. Thank you!
Edit: here is the javascript code that receives the returned count value of 5 instead of 10
function update3() {
blah.getCount(function(data) {
dwr.util.setValue("demoReply2", data);
});
Is there a way to reset a value of a static variable to their initial state? For example:
I have a lot of variables which holds score, speed, etc. All those variables are changing during the program execution. So when the user fails in a game, I would like to reset ALL variables to their initial state. Is there some way? Because i don't know if it is a good idea to do this manually for EACH variable in my program. for example:
static int SCORE = 0;
static float SPEED = 2.3f;
public void resetGame() {
SCORE = 0;
SPEED = 2.3;
}
Use an object, and set its initial state in the constructor:
public class GameSettings {
private int score = 0;
private float speed = 2.3F;
// methods omitted for brevity
}
...
public void resetGame() {
gameSettings = new GameSettings();
}
Also, please respect the Java naming conventions. ALL_CAPS is reserved for constants. Variables should be lowerCase.
Store the default values.
static final int DEFAULT_SCORE = 0;
static final float DEFAULT_SPEED =2.3;
static int SCORE = DEFAULT_SCORE;
static float SPEED = DEFAULT_SPEED;
public static void resetGame() {
SCORE = DEFAULT_SCORE;
SPEED = DEFAULT_SPEED;
}
Why not just recreate the object if you want it reset? Then it'll implicitly have the default values.
You could just declare your variables without values and have a method initGamestate() which sets all variables to their initial values. Call this function both on initialization of the application and when the user starts a new game.
A more object-oriented solution would be to have a class GameState which has all these variables and sets the default in its constructor. You then start every game by initializing a fresh object with new GameState();
You'll just have to reset them one by one. If you're worried about typos you could do: int initialscore = 0; int score = initialscore; and then reset them to the initial... variables in your function.
I have a lot of variables which holds score, speed, etc
You should put them all into one class and every member get initialsed (if the default won't work).
You will hold the player's state in one reference to an object of this class. To reset simply create a new object of this class and assign it to the reference.
Usually games use more than one thread (for example when using Swing or painting any graphics), e.g. so inputs are not blocked. That means with all the other solutions you might run into race conditions. This solution of Evan Knowles came closest.
I would suggest a immutable GameState class, e.g.
public GameState {
private final int score;
private final int speed;
// initial state/"reset game"
public GameState() {
score = 0;
speed = 2.3;
}
// Private so we are always in a valid state
private GameState(int _score, int _speed) {
score = _score;
speed = _speed;
}
public GameState updateSpeed(int _speed) { return new GameState(this.score, _speed); }
public GameState updateScore(int _score) { return new GameState(_score, this.speed); }
public int getSpeed() { return speed;}
public int getScore() { return score;}
// add getters, setters and whatsoever here. But watch for proper synchronization between threads!
}
The advantage here is that once the values are assigned, they can't be changed anymore ("immutable"/read-only) from the outside, so there are no concurrency issues. Plus, you get a sort of chaing for free (see below)! Moreover, you can safely (de-)serialize the game state for saving/loading games.
Effectively, each GameState represents one state in a finite state machine. Calling either updateSpeed or updateScore is a transition to a new state.
The public default constructor is a transition to the initial state of the state machine.
On a side note, the state machine is finite because the value ranges of score and speed are finite, thus all combiniations of them result in a finite amount of states.
I now assume your class for doing other game stuff is called Game.
public Game {
private volatile GameState gameState = new GameState();
public void resetGame() {
gameState = new GameState();
}
// Just an example
public increaseSpeed(int _additionalSpeed) {
gameState = gameState.updateSpeed(gameState.getSpeed() + _additionalSpeed);
}
// Change more than one value
public changeBoth(int _newSpeed, int _newScore) {
// First way: Create a new GameState, change both values step by step and then assign afterwards.
GameState _newState = gameState.updateScore(_newScore);
// other computations follow
// Do NOT assign to gameSpate here, because the state would be inconsistent then.
_newState = _newState.updateSpeed(_newSpeed);
// At the END of the method, assign the new game state. That ensures that the state is always valid
gameState = _newState;
// Second way: Use method chaining if you don't need to make other computations in between. Again, do this at the end of the method
gameState = gameState.updateScore(_newScore).updateSpeed(_newSpeed);
}
}
The volatile keyword makes sure every thread sees the same value of the gameState variable. You might want to consider using other synchronization/locking techniques instead, too. Alternatively you can make the gameState field static and skip the volatile keyword if you only have one Game object.
Because GameState is immutable(read-only), the state of your game now is always consistent/valid.
A good way is to use a static init() and call it when exception occurs.
package com.kvvssut.misc;
public class ResetStatic {
private static int SCORE = 0;
private static float SPEED = 2.3f;
private static void init() {
SCORE = 0;
SPEED = 2.3f;
}
public static void main(String[] args) {
SCORE = 100;
SPEED = 230.3f;
try {
throw new RuntimeException();
} catch (Exception e) {
init();
}
System.out.println(SCORE);
System.out.println(SPEED);
}
}