a java static method - java

I have a class like this
public class StockCodes
{
public static boolean loaded = false;
public static long lastUpdate = 0;
private static long freq = 1000 * 60 * 60 * 24;
public static HashMap<String, Stock> stockMap = new HashMap<String, Stock>();
public static ArrayList<Stock> getCodes()
{
long now = System.currentTimeMillis();
if ((StockCodes.loaded) && ((now - StockCodes.lastUpdate) < freq))
{
System.out.println(StockCodes.loaded);
return stockList;
}
else
{
HttpFetcher fetcher = new HttpFetcher();
....
log.info("Load " + stockList.size() + " Stocks");
StockCodes.loaded = true;
StockCodes.lastUpdate = now;
return stockList;
}
}
public static void main(String[] args)
{
StockCodes.getCodes();
}
}
When I run the java application , it outputs "true". Telling us the stockcodes have loaded.
But when i debug the java appliction, it goes into the else. I do not understand why it runs in this way, especially why it outputs "true" the first time i run the application. Could someone else give me some help ,thank you ~

With the code given above, the control by default should always go in the else block and print nothing. You can verify it.
Not if you have some more places where you call the getCodes() method, then it will differ. Having said this, please verify if there is no other place with a call to getCodes(). ie its invoked single time via main()

The getCodes() function essentially caches the result if the function has been run more than once. The first getCodes() will not print "true", but all subsequent calls will
Run from the command line
public static void main(String[] args)
{
StockCodes.getCodes();
}
this should output nothing to STDOUT.

Your if statement is clean. When I have one of these type of mistakes I go the old fashion route. I put a series of
System.out.println
statements in that section of the code to track where you code is going when it not in debug mode. It is clunky but it works.

When I run your code it goes through the else whether I run in debug mode or regular.
I think you lost a line of your code. Did you have
System.out.println(StockCodes.loaded);
in your else branch also? If you did, and you had it located below your line StockCodes.loaded = true; then it will be printing true for you.
I suggest you use more detailed debugging, something like System.out.println("In the if branch"); and below that in the else branch, a line like System.out.println("In the else branch"); I think you are tricking yourself by having too little output.

Related

How to use correctly assertThrows on set of values?

I've been learning Java just for a bit, so please advise how exception throwing test should look like in this case?
I have following Gambling Machine Class. And then 2 tests for it. I do not really know what should follow the "Integer" in second method (shouldThrowWhenNumbersOutOfRange). Could you please advise as to the exact syntax?
public class GamblingMachine {
public int howManyWins(Set<Integer> userNumbers) throws InvalidNumbersException {
validateNumbers(userNumbers);
Set<Integer> computerNumbers = generateComputerNumbers();
int count = 0;
for (Integer number : userNumbers) {
if (computerNumbers.contains(number)) {
count++;
}
}
return count;
}
private void validateNumbers(Set<Integer> numbers) throws InvalidNumbersException {
if (numbers.size() != 6) {
throw new InvalidNumbersException();
}
if (numbers.stream().anyMatch(number -> number < 1 || number > 49)) { //anyMatch-function to check whether any element in list satisfy given condition
throw new InvalidNumbersException();
}
}
private Set<Integer> generateComputerNumbers() {
Set<Integer> numbers = new HashSet<>();
Random generator = new Random();
while(numbers.size() < 6) {
numbers.add(generator.nextInt(49) + 1);
}
return numbers;
}
}
private GamblingMachine machine = new GamblingMachine();
#ParameterizedTest
#NullAndEmptySource
public void shouldThrowWhenNumbersEmpty(Set<Integer> numbers) throws InvalidNumbersException {
Assertions.assertThrows(NumberFormatException.class, () -> {
Integer.parseInt(" ");
});
}
#ParameterizedTest
#CsvFileSource(resources ="/numbersOutOfRange.cvs", numLinesToSkip = 1)
public void shouldThrowWhenNumbersOutOfRange(Set<Integer> numbers) throws InvalidNumbersException {
Assertions.assertThrows(NumberFormatException.class, () -> {
Integer. //how code should look like here?
});
}
The point of a test is to, you know, test something. Your shouldThrowWhenNumbersEmpty test doesn't do that (well, it tests that Integer.parseInt(" ") throws something. It does, of course. You... don't have to test the core libraries).
In other words, your gambling machine tests need to be calling some stuff from your GamblingMachine class. The idea is to test GamblingMachine. Not to test Integer.parseInt.
It's also a bizarre test: Why in the blazes is shouldThrowWhenNumbersEmpty parameterized? I assume the point of that test is: "Ensure that the gambling machine works as designed when passing an empty set of numbers in, specifically, the part of the design that states that an InvalidNumbersException is thrown if you do that".
Which is done with something like:
#Test
public void shouldThrowWhenNumbersEmpty() {
Assertions.assertThrows(InvalidNumbersException.class, () -> {
Set<Integer> empty = Set.of();
machine.howManyWins(empty);
});
}
Parameterized tests are a fairly exotic concept. Your test setup appears to be falling into a trap: It appears to be set up that you repeat all the logic that is already in your gamblingmachine class, to then apply this logic to the incoming (parameterized) data, figure out what your gambling machine ought to be doing, and then double check its work.
That's not how you should write tests. Tests focus on a specific result. Parameterized tests can make sense, but only if the stuff you have to do for any given input is roughly the same. For example:
Good use of parameterized testing
You have a csv file containing a bunch of lines, each of which has 6 rolls + the correct answer. Your parameterized test treats each line the same: Call howManyWins using the 6 rolls as input, then check that howManyWins returns the expected value.
Bad use of parameterized testing
You have a csv file containing a bunch of lines, each of which has 6 rolls. Your parameterized test will calculate the right result for the rolls, then invoke gambling machine, and check that the gambling machine gives the same answer as what you calculated.
This is bad: You're just repeating the code. It also means your test code is itself doing more than the very basics (it's doing a bunch of business logic), thus raising the question: Who tests your test, then?
Both of your test methods seem like they should NOT be parameterized, unless that csv also contains results.

How do I fix this stack overflow error in my code below?

I am trying to find the square of a number using the scanner method but keep getting a
stackflow error. I am new to programming will be glad if someone helps me out.
My code is as below
import java.util.Scanner;
interface Number {
int findSqr(int i); // Returns the square of n
}
//a class A which implements the interface Number.
class A implements Number {
public int findSqr(int i) {
return findSqr(i);
}
}
public class Question5_1{
public static void main (String[] args){
A a = new A(); // an object of class A
// Reading a number from the keyboard
Scanner sc = new Scanner(System.in);
int i = sc.nextInt();
System.out.print(a.findSqr(i));
}
}
Fix the line which invokes the function recursively return findSqr(i) with return i * i as follows --
public int findSqr(int i) {
return i * i;
}
What you did there is an infinite recursion. The bit where it says
public int findScr(int i) {
return findSqr(i)
}
essentially calls the very same method an infinite number of times in the return statement.
What happens is, that you execute the method, and it tries to return an integer. What you wrote though is a return statement that "returns" another call of the same method, so it gets executed again. Then the whole thing starts over again, so you get a StackOverflow.
Since there is no other code present, I have no idea what you are actually trying to do, but the return findSqr(i) line is what causes the problem.
Initially, recursion may be a rather complicated subject to really wrap you head around, I suggest you either avoid it for now (although it enables you to solve many problems in a really elegant way) or try to understand it a bit better maybe. I'd suggest the Wikipedia article about recursion, although it gets complicated quite fast, or any other tutorial on it, just look it up on Google.

Java Loop InputStream until boolean = false

I have this input stream that checks if I have a certain CAD file open or not. I am doing this by using an input stream to run a tasklist command with the name I want to check. I currently have a boolean that returns true if the specific CAD file isn't open. If the CAD file is open, it returns false. However, I want it to be able to loop this until the CAD file is open because as of right now I have to keep running it in order for it to work. I also need to be able to check this boolean from a separate class. I have it in my main right now so i could test it. My code looks like this...
public class AutoCadCheck {
public static void main(String[] argv) throws Exception {
String notOpen = "INFO: No tasks are running which match the specified criteria";
StringBuilder textBuilder = new StringBuilder();
String command = "tasklist /fi \"windowtitle eq Autodesk AutoCAD 2017 - [123-4567.dwg]";
int i;
InputStream myStream = Runtime.getRuntime().exec(command).getInputStream();
while ((i = myStream.read()) != -1) {
textBuilder.append((char) i);
}
String output = textBuilder.toString();
boolean logical = output.contains(notOpen);
if (logical) {
System.out.println("DWG Not Open");
} else {
System.out.print(output);
}
myStream.close();
}
}
My other class is going to have an 'if statement' that checks whether my boolean "logical" is false, and if so, print something. I have tried every possible method I could think of, but I cannot get it to function the way I want it to. Every other thing I found involving looping an inputstream didn't really apply to my situation. So hopefully someone can help me out in achieving what I want to do.
I would start by moving everything out of main and into a different class. This will make retrieving values and calling specific functions easier. Then create an object of that class in main. Once that is done, I'd create a get method for the boolean variable. Now to focus on the loop. Once the object is created in main, create a conditional loop inside of main which calls the function you need until a different condition is met. This condition might be met once the file is open. After the condition is met, it exits to another loop that relies on another conditional, such as user input.
public class AutoCadCheck {
public static void main(String[] argv) throws Exception {
AutoCadFile file = new AutoCadFile();
//loop 1
//Some conditional so the program will
//continue to run after the file has been found.
// while(){
//loop 2
//check to see if the file is open or not
//while(logical){
//}
//}
}
}
Other class
import java.io.IOException;
import java.io.InputStream;
public class AutoCadFile {
private String notOpen;
private StringBuilder textBuilder;
private String command;
private int i;
private InputStream myStream;
private String output;
private boolean logical;
public AutoCadFile() {
notOpen = "INFO: No tasks are running which match the specified criteria";
textBuilder = new StringBuilder();
command = "tasklist /fi \"windowtitle eq Autodesk AutoCAD 2017 - [123-4567.dwg]";
output = textBuilder.toString();
logical = output.contains(notOpen);
try {
myStream = Runtime.getRuntime().exec(command).getInputStream();
} catch (IOException e) {
e.printStackTrace();
}
}
public void checkForFileOpen() {
try {
while ((i = myStream.read()) != -1) {
textBuilder.append((char) i);
}
if (logical) {
System.out.println("DWG Not Open");
} else {
System.out.print(output);
}
myStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public boolean getFileBoolean() {
return logical;
}
}
My other class is going to have an if statement that checks whether my boolean logical is false ...
Well, logical is a local variable within a method. So no code in another class is going to be able to see it.
There are two common approaches to this kind of thing:
Make the variable (i.e. logical) a field of the relevant class. (Preferably NOT a static field because that leads to other problems.)
Put your code into a method that returns the value you are assigning to logical as a result.
From a design perspective the second approach is preferable ... because it reduces coupling relative to the first. But if your application is tiny, that hardly matters.
I can see a couple of other significant problems with your code.
When you use exec(String), you are relying on the exec method to split the command string into a command name and arguments. Unfortunately, exec does not understand the (OS / shell / whatever specific) rules for quoting, etcetera in commands. So it will make a mess of your quoted string. You need to do the splitting yourself; i.e something like this:
String[] command = new String{} {
"tasklist",
"/fi",
"windowtitle eq Autodesk AutoCAD 2017 - [123-4567.dwg]"
};
Your code potentially leaks an input stream. You should use a "try with resource" to avoid that; e.g.
try (InputStream myStream = Runtime.getRuntime().exec(command).getInputStream()) {
// do stuff
} // the stream is closed automatically ... always

How to modify Java code while running in debug mode?

How can I enable this "Debugging in Runtime" Notch is talking about in this video in Eclipse?
As a test, I'd like to be able to edit the output of the following code and change it to "Hello Runtime Debugging" while it's running.
public class HelloWorld {
public static void main(String[] args) throws InterruptedException {
doIt();
}
private static void doIt() throws InterruptedException {
for (int i = 0; i < 1000; ++i) {
System.out.println("Hello World " + i);
Thread.currentThread().sleep(100);
}
}
}
EDIT: I modified the code, now I get the results I was looking for. Suraj Chandran's answer below explains it.
private static void doIt() throws InterruptedException {
for (int i = 0; i < 1000; ++i) {
print(i);
Thread.currentThread().sleep(100);
}
}
private static void print(int i) {
System.out.println("Hello Sir " + i);
}
Eclipse supports hot swapping code during debugging , out of the box.
While debugging, just change any code and save it, Eclipse will automatically transfer the modified code to the target VM.
Note that you can't make structural changes to the code, like adding new methods, changing method signature or adding new fields. But you can change the code within a method.
EDIT: Note that changing the code during deubgging will make that method re-execute form the beginning, resetting the local variables in that method.
You need to make sure that Project > Build Automatically is checked.
Otherwise it might not work.
After enable Project-> Build Automatically, hot swapping code in debug mode is ok to me
I may misunderstand the question, but if you run a program in Eclipse in debug mode (Run/Debug), you can edit the content of methods during the program runs (if JVM supports it). Regularly you can not change the imports, method signatures, class definitons, etc, just the content of the methods.

Using a String in run configurations as an argument and using it in an if-statement

The code below works as long as the argument in the run configuration equals "-output". But when the arguments are empty the compiler throws and ArrayOutOfBoundsException.
The point of this piece of code would eventually be to;
- Perform an action when -output is written in the run configurations arguments
- Perform something else if the arguments are empty or different from -output
I found many problems that looked like this one. But I've been working on a solutions for far to long, so I started a new post. Help is very much appreciated.
...
public static void main(String[] args) {
Version_5 v5 = new Version_5("Test");
{
if(args[0].equals("-output")){
System.out.println("It works");
}
}
}
...
You need to check if you have arguments first, that's all.
if ((args.length > 0) && (args[0].equals("-output")) {
...
You might also consider using an argument-parsing library, of which there are several.
What are the extra brackets for?
As you can see String args[] is an array with a specific size. If you don't pass an argument the size is zero. Before you check what is at args[0] check if args has a size with args.length.
if (args.length>0){
//do something
}
else if (args[0].equals("-output")){
System.out.println("It works");
}

Categories