I'm trapped within this certain predicament of mine and I would gladly accept any suggestion. So here it is:
I'm currently working in a method where a certain variable is assigned a specific value in the beginning part of the method. During the course of the method, that variable is used as a parameter by an external component which basically returns a result code. In one of those result codes, I have to change the value of the prior mentioned variable and repeat the whole process using the new value. The concept is as follows but I have simplified it as much as possible:
public void myMethod (String args[]) {
String server;
server = "some value";
switch (someExternalOperation(server)) {
case 1:
//process....
break;
case 2:
server = "new value";
//repeat myMethod using new value of server String variable
break;
}
}
public int someExternalOperation (String str) {
//after several operation
return 1; //example purposes
}
By the way, I have checked and researched things like goto and other alternative. I may have overlooked some results and ended up asking here. Any help would be much appreciated. Thank you.
One simple option is to have a private overload taking the server parameter - then you can call it recursively:
public void myMethod(String args[]) {
myMethod(args, "some value");
}
private void myMethod(String[] args, String server) {
switch (someExternalOperation(server)) {
case 1:
// process....
break;
case 2:
myMethod(args, "new value");
break;
}
}
You need to make sure that isn't going to recurse infinitely, of course.
Another option would be to just have a loop inside your method:
public void myMethod (String args[]) {
String server = "some value";
while (true) { // Or ideally a different condition...
switch (someExternalOperation(server)) {
case 1:
// process....
// Done! Exit the method...
return;
case 2:
server = "new value";
// We'll now continue to the next iteration of the loop
break;
default:
// ?
}
}
}
I figured a way instead to address. Thanks everyone for reading. I'll just simply use the external operation and check if it will return case 2.
public void myMethod (String args[]) {
String server;
server = "some value";
if (someExternalOperation(server) == 2)
server = "new value";
switch (someExternalOperation(server)) {
case 1:
//process....
break;
}
}
public int someExternalOperation (String str) {
//after several operation
return 1; //example purposes
}
Thanks for your help anyway.
Related
I've run into a problem where I attempt to define a constructor in the first part of a switch/case statement, and then I can't run the code because the program can't get the definition later.
The idea behind passing the constructor information from a switch/case function is that the user chooses what to do, but for some options, one must be done before the other is possible (e.g. Create password and Check password).
If I try doing it this way, it throws a VarMayNotHaveBeenInitialized error (I get the sense the answer is in a try/catch statement, but I don't know enough about them to be sure). I've included some code that is what I've been essentially trying to do below. (The two classes are to best simulate the project I'm working on.)
Any help is appreciated! : )
TestMain.java:
package exitTest;
public class TestMain {
InitializeTest init;
public static void main(String[] args) {
while (true) {
String x = InitializeTest.askQuestion();
switch (x) {
case "set":
InitializeTest init = new InitializeTest();
break;
case "get":
if (init != null) {
init.showExample();
} else {
System.out.println("Error: init not initialized.");
} break;
}
}
}
}
InitializeTest.java:
package exitTest;
import java.util.Scanner;
public class InitializeTest {
static Scanner in = new Scanner(System.in);
public InitializeTest thing1;
public String example;
public static String askQuestion() {
System.out.println("set for set example\nget for check example");
String action = in.nextLine();
return action;
}
public InitializeTest() {
System.out.println("Input string:");
String example = in.nextLine();
}
void showExample() { System.out.println(example); }
}
You include the type when you're declaring variables, not when simply assigning to an existing one. When you write
InitializeTest init = new InitializeTest();
That makes a new init variable, unrelated to the previous one, which stores the newly constructed object. That new variable shadows the existing one, but it gets released after the switch block is over (variables in Java are block-scoped).
To put it to an analogy, it's as though you wanted to tell your friend Alice a secret. But when you went to her house, her neighbor whose name is also Alice happened to be there instead. If you tell that Alice your secret, then your friend doesn't find out. Even though the two happen to share a name, they don't share any memory.
I have an object "JudgesSubmission" with the following methods:
public String getInnovationGrade1() {
return innovationGrade1;
}
public String getInnovationGrade2() {
return innovationGrade2;
}
public String getInnovationGrade3() {
return innovationGrade3;
}
public String getInnovationGrade4() {
return innovationGrade4;
}
Now, when calling these methods, I want to put them in a loop where the called method name gets the index of the loop attached to its end changing the method called. Is this possible?
For example, the following code would never work, but I am writing it to explain what I need:
judgesSubmission metricScores= new judgesSubmission;
int metricSum=0;
for (int i=0;i<4;i++){
metricSum=metricSum
Integer.parseInt(metricScores.getInnovationGrade+"i"());
}
Is there a way to do that or do I always have the full method name written?
What you want to do is not possible... but with reflection such as :
MyObject.class.getMethod("mymethod"+i);
Without reflection you could use a Supplier<String> :
public void process(Supplier<String>... suppliers){
judgesSubmission metricScores= new judgesSubmission;
int metricSum=0;
for (Supplier<String> supplier : suppliers){
Integer.parseInt(supplier.get());
}
}
And call it such as :
MyObject myObject = new MyObject();
process(()->myObject.getInnovationGrade1(),
()->myObject.getInnovationGrade2(),
()->myObject.getInnovationGrade3(),
()->myObject.getInnovationGrade4());
It is not possible without reflection (and is highly not recommended)
Instead you may want to use other methods:
An array of the data (either replacing the 4 methods, or in addition)
String[] getInnovationGrades()
{
return new String[]{innovationGrade1, innovationGrade2, innovationGrade3, innovationGrade4};
}
Then later you can use
for(String innovationGrade : getInnovationGrades())
//do stuff
An argument to get the data you want
String getInnovationGrade(int i)
{
switch(i)
{
case 1:
return getInnovationGrade1();
case 2:
return getInnovationGrade2();
case 3:
return getInnovationGrade3();
case 4:
return getInnovationGrade4();
default:
return ""; //or throw exception, depends on how you wish to handle errors
}
}
Then later you can use
for(int i = 1; i <= 4; i++)
getInnovationGrade(i); //and do stuff with it
I would like to call the isATens method from my main method but im only able to do that when isATens has no parameter. I'v tried putting the same parameter in the caller, but that does't seem to recognize that either.
public class P1L4 {
public static void main(String[] args) {
P1L4 main = new P1L4();
main.run();
isATens(userInput); //<--- this is what I've tried doing.
}
public void run() {
Scanner scanner = new Scanner(System.in);
System.out.println("Name a tens and i'll test if it's one under 100.");
int userInput = scanner.nextInt();
}
public boolean isATens(int userInput) {
System.out.println(userInput);
switch (userInput) {
case 10 : case 20 : case 30 : case 40 : case 50 : case 60: case 70: case 80: case 90 :
isUnderOneHundred(continued);
default :
System.out.println("Not under one hundred");
}
return true;
}
public boolean isUnderOneHundred(int continued) {
return true;
}
}
There are some Java concepts that you apparently haven't learned yet: Scope and Instance vs. static methods. Read the appropriate chapters of your Java textbook if you have difficulties understanding my following comments.
int userInput = scanner.nextInt(); is declared inside the scope of the run() method, and therefore not visible in the main() method. If you want to see userInput outside of the run() method, I'd make it the return value of that method:
public int run() {
...
int userInput = scanner.nextInt();
return userInput;
}
You're mixing instance and static methods without any visible concept when to use which kind. When you want to call an instance method from a static one, you need to name the instance before the dot, so at least it has to be main.isATens(userInput); instead of isATens(userInput); (after you've solved the userInput issue).
Your program logic is strange, e.g. I'd expect a method like isUnderOneHundred(int continued) to return true if the parameter is under 100, but that method doesn't even have any look at its parameter and returns true for any number you pass in.
I have a class with a method that calls a method located in another class, and that method has switch cases. Th e problem is that I am not able to exit from the method with switch cases and get back to the next line after the method that called it. I have searched StackOverFlow for similar questions. I also tried to use the suggested solutions in those answers to questions related to exit from a switch case (using a conditional, using return, etc). Unfortunately, when I use these solutions, I don't go back to the next line in the method that called the switch case method. Rather, I am exiting the whole program with "Build Succeeded message".
Rather than being too abstract, I hope I am not flamed for posting some classes simulating the real problem I am facing. Sorry if the code is too long.
public class TestClass {
ClassWithriginalMethod test;
public static void main(String[] args) {
ClassWithriginalMethod g = new ClassWithriginalMethod();
g.presentMenuOptions();
}
}
This class contains the main method.
The next class is the one which have a method that calls the method with switch cases:
import java.util.ArrayList;
import java.util.Scanner;
public class ClassWithriginalMethod {
private final ArrayList<ClassWithSwitchCases> arr;
Scanner s = new Scanner(System.in);
public void presentMenuOptions() {
System.out.println(
"_____________________________________________________________________________\n"
+ "This Menu contains the following options:\n"
+ "Please choose a number corresponding to your option\n"
+ "1: to get create submenu\n"
+ "2: to get edit sub menu\n"
+ "3: to get view sub menu\n"
+ "4: to get delete sub\n"
+ "5: to exit this operation\n"
+ "_____________________________________________________________________________\n");
String str= s.nextLine();
switch (str) {
case "1":
System.out.println("Entering creation...");
this.createMenu();//This method is working properly and user is moved to nextline, i.e shown the presentMenuOptions().
break;
case "2":
System.out.println("Entering editing...");
/* The below method is the damn method that calls the other class methods with swith cases.*/
this.editMenu();
/*
** What I want is to reach the next methos below this comment when I get back from the switch case.
*/
System.out.println("We've exited from the othe class method with switch cases...");
this.presentMenuOptions();
break;
case "3":
System.out.println("Entering viewing...");
this.viewMenu();
this.presentMenuOptions();
break;
case "4":
System.out.println("Entering deletion...");
this.deleteMenu();
this.presentMenuOptions();
break;
default:
System.exit(0);
}
}
public ClassWithriginalMethod() {
this.arr = new ArrayList<>(0);
}
private void createMenu() {
ClassWithSwitchCases toBeCreated = new ClassWithSwitchCases();
this.arr.add(toBeCreated);
this.checkingArraySize();
this.presentMenuOptions();
}
private void editMenu() {
this.checkingArraySize();
System.out.println("The following objects are available. Please select the object with the corresponding index\n");
this.arr.forEach(p -> System.out.printf("%-15d\t%-15s\t%-15s\n", arr.indexOf(p), p.getfName(),p.getsName())); // we print the array to see the indices and object main elems.
int i = s.nextInt();
ClassWithSwitchCases toBeEdited = this.arr.get(i); //supposedly I am checking through another function if the object of index i is in the array.
toBeEdited.edit(toBeEdited); // it is here where we are calling the switch method in the other class
//this.presentMenuOptions();
}
private void viewMenu() {
this.checkingArraySize();
System.out.println("The following objects are available. Please select the object with the corresponding index");
this.arr.forEach(p -> System.out.printf("%-15d\t%-15s\t%-15s\n", arr.indexOf(p), p.getfName(),p.getsName())); // we print the array to see the indices and object main elems.
int i = s.nextInt();
ClassWithSwitchCases toBeViewed = this.arr.get(i); //supposedly I am checking through another function if the provided number id less than size of List.
toBeViewed.view(toBeViewed); // making this class calling the function in the other class
//this.presentMenuOptions();
}
private void deleteMenu() {
this.checkingArraySize();
System.out.println("The following objects are available. Please select the object with the corresponding index");
int i = s.nextInt();
ClassWithSwitchCases deleted = this.arr.get(i); //supposedly I am checking through another function if the provided number id less than size of List.
deleted.view(deleted); // making this class calling the function in the other class
//this.presentMenuOptions();
}
private void checkingArraySize () {
if (this.arr.size() <= 0) {System.out.println("There are no objects in the aray");}
else {
arr.stream().map((p) -> {
System.out.println("The following objects are available.");
return p;
}).forEachOrdered((p) -> {
System.out.printf("%-15s\t%-15s\t%-15s\n", "index", "fName", "sName");
System.out.printf("_____________________________________________________________________________\n");
System.out.printf("%-15d\t%-15s\t%-15s\n", arr.indexOf(p), p.getfName(),p.getsName());
});
}
}
}
The last class is the one with switch cases:
public class ClassWithSwitchCases {
private String fName;
private String sName;
Scanner s = new Scanner(System.in);
public ClassWithSwitchCases() {
System.out.println("Please enter first name");
this.fName = s.nextLine();
System.out.println("Please enter sur name");
this.sName = s.nextLine();
}
public String getfName() {
return fName;
}
public void setfName(String fName) {
System.out.println("Please enter first name");
this.fName = fName;
}
public String getsName() {
return sName;
}
public void setsName(String sName) {
System.out.println("Please enter sur name");
this.sName = sName;
}
public void edit(ClassWithSwitchCases o) {
System.out.println(
"_____________________________________________________________________________\n"
+ "The Edit Menu contains the following options:\n"
+ "Please choose a number corresponding to your option\n"
+ "1: to edit the object's first name\n"
+ "2: to edit the object's sur name\n"
+ "3: to exit this menu\n"
+ "_____________________________________________________________________________\n");
do {
switch (s.nextLine()) {
case "1":
o.setfName(s.nextLine());
System.out.println(o.toString());// just to check if editing took place
this.edit(o); // put so that we can make other edits.
break;
case "2":
o.setsName(s.nextLine());
System.out.println(o.toString());// just to check if editing took place
this.edit(o);
break;
case "3":
System.out.println("We are leaving the method with switch cases...");
break;
default:
System.out.println("We are also leaving the method with switch cases...");
break;
}
} while ((Integer.getInteger(s.nextLine()) <= 3) && (Integer.getInteger(s.nextLine()) > 0));
}
public void view(ClassWithSwitchCases o) {
System.out.println(o.toString());
}
#Override
public String toString() {
return "_____________________________________________________________________________\n"
+ "First Name:" + this.getfName() + "\n"
+ "Middle Name:" + this.getsName() + "\n"
+ "_____________________________________________________________________________\n";
}
}
If you try to work these classes, you will notice:
I am able to execute the createMenu() method, and then I get the presentMenuOptions() method, as supposed to be.
The viewMenu() and deleteMenu() methods do their work, but they exit from the whole program.
The editMenu() method is giving me nullPointerExeption, but I have no idea which pointer is that.
I have indicated in the comments in the code what I was thinking of.
I added extra System.out.println() messages, as a way to debug my code. Since I am only a beginner, this is as far as I can go at this stage.
If there is any general value from my question it is: How to exit from a method with switch cases and go back to another method, not necessarily the main method.
Many thanks for you help and patience :)
You can use the return statement anywhere in the switch. Most likely, you want to change your break statements to return statements.
It seems to me that while my question is valid, it is not the core problem. The core problem is how do I envision my classes (Objects) and how they are related to each other. In other words, I faced this problem because of the way I orchestrated my solution. If I chose another orchestration (i.e, more proper design patterns), most probably I was not going to face this issue.
It also seems to me that beginners (I am one of them) who are serious to build a big solution will face this "problem pattern" (asking either silly questions, or evading questions like "Why you are doing this? What were you aiming to achieve?" because they run quickly into implementing certain classes while they have not figured out the overall structural, behavioral, and creational aspects of the solution.
Interestingly, though, is that by making these mistakes, they learn.
Thanks for those who answered me and those who will answer or comment.
I have a problem returning a result of String type in Java.
Here is the whole code
import java.util.*;
public class Multiplication
{
static Random randomNumbers = new Random();
static Scanner input = new Scanner(System.in);
static int answer;
public static void multiplication()
{
createQuestion(); //display first question
int guess; //student's answer
System.out.print("Your answer is (-1 to quite): ");
guess = input.nextInt();
while(guess != -1)
{
checkAnswer(guess);
System.out.print("Your answer is (-1 to quite): ");
guess = input.nextInt();
}
} //end method multiplication
//create new question
public static void createQuestion()
{
int num_1 = randomNumbers.nextInt(10);
int num_2 = randomNumbers.nextInt(10);
answer = num_1 * num_2;
System.out.printf("How much is %d times %d?\n", num_1, num_2);
}//end method createQuestion
public static String createResponse(boolean correct)
{
if (correct)
switch(randomNumbers.nextInt(4))
{
case 0:
return ("Very good!");
case 1:
return("Excellent!");
case 2:
return("Nice work!");
case 3:
return ("Keep the good work");
} //end switch
//otherwise, assume incorrect
switch(randomNumbers.nextInt(4))
{
case 0:
return("No. Please try again.");
case 1:
return("Wrong. Try once more.");
case 2:
return("Don't give up!");
case 3:
return("No. Keep trying.");
}//end switch
}//end method createResponse
//check in the student answer correctly
public static void checkAnswer(int guess)
{
if(guess != answer)
{
System.out.println(createResponse(false));
}
else
{
System.out.print(createResponse(true));
createQuestion();
}
}//end method checkAnswer
}//end class Multiplication
And here is the main method
public class MultiplicationTest {
public static void main(String[] args) {
Multiplication app = new Multiplication();
app.multiplication();
}
}
The problem is in the createResponse(boolean correct) method. Here JDE is saying that "This method must return a result of type String". I have mentioned there String type return. But the program is not being executed. Showing a red line under the method createResponse(boolean correct).
Does anybody where I have messed up?
Thanks in advance!
The compiler cannot assert that your method returns a String.
This is because your switch-case may fail to return anything.
You can satisfy the compiler by placing a
return null;
at the end of your method.
The method createResponse might not always reach a return statement in your code. If none of the cases in your second switch statement applies, it will reach the bottom of the code block without returning.
Just make sure you return something at the end of the method (or find another nice solution):
return "";
}//end method createResponse
It's because if none of the conditions in either of the switch statements were met there would be nothing to return. Try something like:
public static String createResponse(boolean correct)
{
String result = null;
if (correct)
switch(randomNumbers.nextInt(4))
{
case 0:
result = "Very good!";
// Insert the rest of the code here, assigning to result rather than returning as above.
return result;
}
you are missing the 'else' part for the 'if' and the 'default' case for the 'switch-case' in the createResponse method.
edit:
ok, the 'else' is not necessary, but I missed that in the first place. the indentation of the second 'switch' is confusing. please use parentheses to avoid this.
Furthermore, the compiler believes that it could happen that none of the 'case' branches will get executed since it is not aware of the nextInt returning Integers in the range of 0..3. you'll need to add the default case to satisfy the compiler.
Compiler is not smart enough yet to know that nextInt(4) may return only 0,1,2 and 3 so it assumes that for case like 5 you current code will not return anything, but if method declares that it will return some value must guarantee that some value will always be returned.
To solve this problem you can change case 3: to default:. This would make compiler assume that even for cases which are not 0,1,2 some value will be returned.
Also it seems that your code would be cleaner if you would use else and additional curly brackets like
public static String createResponse(boolean correct) {
if (correct){
switch (randomNumbers.nextInt(4)) {
case 0:
return ("Very good!");
case 1:
return ("Excellent!");
case 2:
return ("Nice work!");
default:
return ("Keep the good work");
}
} else {
switch (randomNumbers.nextInt(4)) {
case 0:
return ("No. Please try again.");
case 1:
return ("Wrong. Try once more.");
case 2:
return ("Don't give up!");
default:
return ("No. Keep trying.");
}
}// end switch
}// end method createResponse
BTW you can simplify your code a little by using arrays which would store your responses. This way your code could look like
private static String[] good = { "Very good!",
"Excellent!",
"Nice work!",
"Keep the good work" };
private static String[] bad = { "No. Please try again.",
"Wrong. Try once more.",
"Don't give up!",
"No. Keep trying." };
public static String createResponse(boolean correct) {
if (correct)
return good[randomNumbers.nextInt(4)];
else
return bad[randomNumbers.nextInt(4)];
}
or even
public static String createResponse(boolean correct) {
return correct ? good[randomNumbers.nextInt(4)]
: bad[randomNumbers.nextInt(4)];
}