Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I'm new to Java and my function has a lot of try/catch blocks that I would like to clean up. I wanted to take each section and put it in a separate private helper method and only call a few functions within the main function, but when I do so, I get a java.util.NoSuchElementException for Scanner.
Here is the original function. Any help would be much appreciated.
public void playGame(List<Card> deck, FreecellOperations<Card> model, int numCascades,
int numOpens, boolean shuffle) {
try {
Scanner scan = new Scanner(rd);
try {
Objects.requireNonNull(model);
Objects.requireNonNull(deck);
} catch (NullPointerException npe) {
throw new IllegalArgumentException("Cannot start game with null parameters.");
}
try {
model.startGame(deck, numCascades, numOpens, shuffle);
} catch (IllegalArgumentException iae) {
ap.append("Could not start game. " + iae.getMessage());
return;
}
ap.append(model.getGameState() + "\n");
while (!model.isGameOver()) {
String source = scan.next();
if (source.substring(0, 1).equals("q") || source.substring(0, 1).equals("Q")) {
ap.append("Game quit prematurely.");
return;
}
String cardIndex = scan.next();
if (cardIndex.substring(0, 1).equals("q") || cardIndex.substring(0, 1).equals("Q")) {
ap.append("Game quit prematurely.");
return;
}
String destination = scan.next();
if (destination.substring(0, 1).equals("q") || destination.substring(0, 1).equals("Q")) {
ap.append("Game quit prematurely.");
return;
}
int pileNumber = 0;
PileType sourceType = null;
boolean isValidSource = false;
while (!isValidSource) {
try {
switch (source.charAt(0)) {
case 'F':
sourceType = PileType.FOUNDATION;
pileNumber = this.validMoveCheck(source, 4);
isValidSource = true;
break;
case 'O':
sourceType = PileType.OPEN;
pileNumber = this.validMoveCheck(source, numOpens);
isValidSource = true;
break;
case 'C':
sourceType = PileType.CASCADE;
pileNumber = this.validMoveCheck(source, numCascades);
isValidSource = true;
break;
default:
throw new IllegalArgumentException();
}
} catch (IllegalArgumentException iae) {
ap.append("Invalid source pile. Try again.\n");
source = scan.next();
if (source.equals("q") || source.equals("Q")) {
ap.append("Game quit prematurely.");
return;
}
}
}
int cardNum = 0;
boolean isValidCard = false;
while (!isValidCard) {
try {
cardNum = Integer.parseInt(cardIndex);
isValidCard = true;
} catch (NumberFormatException nfe) {
ap.append("Invalid card number. Try again.\n");
cardIndex = scan.next();
if (cardIndex.equals("Q") || cardIndex.equals("q")) {
ap.append("Game quit prematurely.");
return;
}
}
}
PileType destType = null;
int destPileNum = 0;
boolean isValidDest = false;
while (!isValidDest) {
try {
switch (destination.charAt(0)) {
case 'F':
destType = PileType.FOUNDATION;
destPileNum = this.validMoveCheck(destination, 4);
isValidDest = true;
break;
case 'C':
destType = PileType.CASCADE;
destPileNum = this.validMoveCheck(destination, numCascades);
isValidDest = true;
break;
case 'O':
destType = PileType.OPEN;
destPileNum = this.validMoveCheck(destination, 4);
isValidDest = true;
break;
default:
throw new IllegalArgumentException();
}
} catch (IllegalArgumentException iae) {
ap.append("Invalid destination pile. Try again.\n");
destination = scan.next();
if (destination.equals("q") || destination.equals("Q")) {
ap.append("Game quit prematurely.");
return;
}
}
}
try {
model.move(sourceType, (pileNumber - 1), (cardNum - 1), destType, (destPileNum - 1));
ap.append(model.getGameState() + "\n");
} catch (IllegalArgumentException iae) {
ap.append("Invalid move. Try again. " + iae.getMessage() + "\n");
}
}
ap.append("Game over.");
} catch (IOException ioe) {
return;
}
}
First, In order not to get java.util.NoSuchElementException, you need to check if the next line exists using hasNextLine().
Add that check in your while loop:
while (!model.isGameOver() && scan.hasNextLine()) {
...
}
Second, you got pretty good code styling tips in the other comments here, I suggest you to take them :)
A few comments:
First, you can replace a lot of these try/catch blocks with simple if statements (or eliminate them altogether).
For example:
default:
throw new IllegalArgumentException();
}
} catch (IllegalArgumentException iae) {
ap.append("Invalid destination pile. Try again.\n");
destination = scan.next();
if (destination.equals("q") || destination.equals("Q")) {
ap.append("Game quit prematurely.");
return;
}
}
Why not just do:
default:
ap.append("Invalid destination pile. Try again.\n");
destination = scan.next();
if (destination.equals("q") || destination.equals("Q")) {
ap.append("Game quit prematurely.");
return;
}
break;
or something like that instead? Why bother with the exception?
Also, this logic is incorrect:
cardNum = Integer.parseInt(cardIndex);
isValidCard = true;
The fact that it's an integer doesn't prove that it's a valid card. What if someone entered 5,321? Clearly, that is an int, but it's not an actual card. Also, see here (as well as its duplicates) for ways to encapsulate this.
Related
Why I get 'Resource leak: '' ' error even when I use close() method in Java?
I put the whole code and used comments where about where I get the error message and where I close the Scanner method.
I use Eclipse, Java 13.
Here's the code.
import java.util.*;
import java.io.*;
import java.lang.reflect.InvocationTargetException;
public class VehicleTest {
public static void main(String[] args) {
VehicleTest vtest = new VehicleTest();
try {
vtest.menuLoop();
} catch(IOException e) {
System.out.println("IO Exception!");
System.exit(1);
} catch(CloneNotSupportedException e) {
System.out.println("CloneNotSupportedException");
System.exit(1);
}
}
private void menuLoop() throws IOException, CloneNotSupportedException {
Scanner scan = new Scanner(System.in);
ArrayList<Vehicle> arr=new ArrayList<Vehicle>();
Vehicle vehicle;
/** Deleted the hard coded adds so it doesn't add same types of cars
* everytime
*/
java.io.File file = new java.io.File("Vehicles.txt");
Scanner in = new Scanner(file).useLocale(Locale.US);
in.useDelimiter(","); //** This is where I get the resource leak error message **//
while (in.hasNext()) {
try {
String vehClass = in.next();
Class veh1 = Class.forName(vehClass);
Vehicle veh = (Vehicle)veh1.
getDeclaredConstructor().newInstance();
arr.add(veh);
veh.readData(in);
} catch (Exception e) {
System.out.print("Exception");
System.exit(0);
}
}
while(true) {
System.out.println("1...................................New car");
System.out.println("2...............................New bicycle");
System.out.println("3......................Find vehicle by name");
System.out.println("4..............Show data about all vehicles");
System.out.println("5.......Change direction of a given vehicle");
System.out.println("6.........................Test clone method");
System.out.println("7..................Test driveable interface");
System.out.println("8..............................Exit program");
System.out.println("...............................Your choice?");
int choice = scan.nextInt();
String name;
switch (choice) {
case 1:
arr.add(new Car());
vehicle = arr.get(arr.size() - 1);
try {
vehicle.setAllFields();
} catch(Exception e) {
System.out.println("Wrong input!");
System.exit(1);
}
break;
case 2:
arr.add(new Bicycle());
vehicle = arr.get(arr.size() - 1);
try {
vehicle.setAllFields();
} catch(Exception e) {
System.out.println("Wrong input!");
System.exit(1);
}
break;
case 3:
System.out.println("Name of vehicle: ");
name = scan.next();
for(Vehicle v : arr) {
if(v.getName() != null &&
(v.getName().compareToIgnoreCase(name) == 0)) {
System.out.println(v);
}
}
break;
case 4:
for(Vehicle v : arr) {
System.out.println(v);
}
break;
case 5:
System.out.println("Name of vehicle: ");
name = scan.next();
char dir;
int degree;
for(Vehicle v : arr) {
if(v.getName() != null &&
(v.getName().compareToIgnoreCase(name) == 0)) {
System.out.print("\nDirection [R/L]: ");
dir = scan.next().charAt(0);
System.out.print("\nDegrees [0-360]: ");
degree = scan.nextInt();
if (dir == 'L') { v.turnLeft(degree); }
if (dir == 'R') {v.turnRight(degree); }
}
}
break;
case 6:
Car car1 = new Car("A bad car","red",100000,1999,"A111",350,0);
Car car2 = (Car)car1.clone();
car2.getBuyingDate().set(2003, 1, 2);
car2.getProductionDate().set(2003, 5, 5);
System.out.println("Date objects are separate, deep copy");
System.out.printf("%n %tF", car1.getBuyingDate());
System.out.printf("%n %tF %n", car2.getBuyingDate());
System.out.printf("Production date car2 edited: "
+ "%n %tF %n", car2.getProductionDate());
break;
case 7:
Car carTest = new Car("Test car","red",100000,1999,
"A111",350,0);
Bicycle bicycleTest =
new Bicycle("Test bicycle","red",100000,
1999,"A111",15,0);
carTest.accelerate(3);
carTest.accelerate(250);
bicycleTest.accelerate(5);
bicycleTest.accelerate(200);
carTest.breaks(100);
bicycleTest.breaks(50);
carTest.stop();
bicycleTest.stop();
break;
case 8:
java.io.PrintWriter output = new java.io.PrintWriter(file);
for(Vehicle v : arr) {
v.writeData(output);
}
scan.close();
in.close(); //* **in.close() method is here**
output.close();
System.exit(0);
default:
System.out.println("Wrong input!");
}
}
}
}
Even when I put in.close() inside the try block, it still shows the same error.
And it still shows the same error even when I put in.close() right after.
Why is it that?
There are code paths where the resource is not closed. Either use a finally block, or a try-with-resources. Like,
try (Scanner in = new Scanner(file).useLocale(Locale.US)) {
in.useDelimiter(",");
while (in.hasNext()) {
try {
String vehClass = in.next();
Class veh1 = Class.forName(vehClass);
Vehicle veh = (Vehicle)veh1.
getDeclaredConstructor().newInstance();
arr.add(veh);
veh.readData(in);
} catch (Exception e) {
System.out.print("Exception");
System.exit(0);
}
}
}
i've got a problem when i use try-catch in the search method. when i input the wrong data, it just skips the catch block and output the code below it
do {
System.out.print(menu[1]);
jumlah = sc1.nextInt();
System.out.print(menu[0]);
tujuan = sc1.nextInt();
for (int i = 0; i < DataRek.length; i++) {
try {
if (tujuan == DataRek[i]) {
index = i;
nasabah = NamaRek[index];
break;
}
} catch (InputMismatchException e) {
System.out.println("DATA NASABAH TIDAK DITEMUKAN, SILAHKAN COBA LAGI");
System.exit(0);
}
}
} while (loop2 == 1);
System.out.println("Nomor rekening tujuan: " + tujuan);
System.out.println("Nama Nasabah: " + nasabah);
System.out.println("Jumlah yang ditransfer: " + jumlah);
System.out.println("Apakah data diatas sudah benar? (Y/N) ");
loop1 = sc1.next().charAt(0);
when i input the wrong data, i expect the output of DATA NASABAH TIDAK DITEMUKAN, but the actual output is the code below it.
The InputMismatchException is potentially thrown by Scanner's methods. You need to include them in the try block:
do {
try {
System.out.print(menu[1]);
jumlah = sc1.nextInt();
System.out.print(menu[0]);
tujuan = sc1.nextInt();
for (int i = 0; i < DataRek.length; i++) {
if (tujuan == DataRek[i]) {
index = i;
nasabah = NamaRek[index];
break;
}
}
} catch (InputMismatchException e) {
System.out.println("DATA NASABAH TIDAK DITEMUKAN, SILAHKAN COBA LAGI");
System.exit(0);
}
} while (loop2 == 1);
I am working in a project with linked list (JAVA) but I am not being able to figure out how to insert the person. How could I get the switch to work? Or should I use something else? I also thought about creating a class outside the main method and just call it but it did not work as well. Any help will be much appreciate
public void listOfPeople() { // Beginning of the method listOfPeople where shows the employees
// *** instance the person object ad loading your variables
Personqueue p1 = new Personqueue(); //saving the employee in a variable???
p1.setFname("John");
p1.setLname("Smith");
p1.setDOA(15);
p1.setPassportN(306589);
p1.setNumber(1);
vectorObj.add(p1); // add the employee in a vector
Personqueue p2 = new Personqueue(); //saving the employee in a variable???
p1.setFname("Paul");
p1.setLname("Clooney");
p1.setDOA(5);
p1.setPassportN(30614584);
p1.setNumber(2);
vectorObj.add(p2); // add the employee in a vector
}
public void ascendingOrder(Vector<Personqueue> vector) { // bubble sort method to order the vector
int j;
boolean flag = true; // set flag to true to begin first pass
Personqueue temp; // holding the variable temporarily
while (flag) {
flag = false; // set flag to false awaiting a possible swap
for (j = 0; j < vector.size() - 1; j++) {
if (vector.get(j).getNumber() > vector.get(j + 1).getNumber()) {
temp = vector.get(j); // swap elements
vector.set(j, vector.get(j + 1));
vector.set(j + 1, temp);
flag = true; // shows a swap occurred
}
}
}
}
public void newPerson(int positionPerson) { // beginning of newPerson method
String Option = null; // declaration of local variables that are used only in this method and don't use too much space
Personqueue p = new Personqueue(); //instead of setting it to null, here we are calling
// a constructor which was declared in Personqueue class.
// switch (positionPerson) {
// case 1: // insert a person at the start of the queue
// // p = new QueueStart();
// break; // executes in order to end the switch in case one of the options is valid
// case 2: // insert a person at a chosen point in the queue
// // p = new ChoosePosition();
// case 3: // insert a person at the end of the queue
// // p = new EndQueue();
// break;
// default:
// System.out.println("Invalid Option!!!"); // in case the option is not one of the cases above, print this...
// return; // return to the do/while loop in Principal method
// }
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.println("Name:"); // user input
try {
Option = br.readLine();
String name = Option;
p.setFname(name);
} catch (IOException e) {
System.out.println(e);
}
System.out.println("Surname:"); // user input
try {
Option = br.readLine();
String lname = Option;
p.setLname(lname);
} catch (IOException e) {
System.out.println(e);
}
System.out.println("Date Of Arrival: "); // user input
try {
Option = br.readLine();
int doa = Integer.parseInt(Option); // use parseInt in order to convert Integer to String to be read by BufferedReader.
p.setDOA(doa);
} catch (IOException e) {
System.out.println(e);
}
System.out.println("Passport Number:"); // user input
try {
Option = br.readLine();
int pn = Integer.parseInt(Option);
p.setPassportN(pn);
} catch (IOException e) {
System.out.println(e);
}
System.out.println("Number:"); // user input
try {
Option = br.readLine();
int no = Integer.parseInt(Option);
p.setNumber(no);
} catch (IOException e) {
System.out.println(e);
}
vectorObj.addElement(p); // save all the data in the vector
System.out.print("Saving Person :" + p.getFname()); // print to the user the name's been saved
try {
for (int i = 0; i < 6; i++) {
System.out.print(".");
Thread.sleep(300); // suspend the "." execution for a specified period.
}
} catch (InterruptedException e) { // exception p o method thread // catch for thread above
e.printStackTrace();
}
System.out.println();
System.out.println("Person: " + p.getFname() + " is saved!!!");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
} // end of the Method newPerson
Check your variables in listOfPeople(...), p2 was not used correctly.
Take a look at Example of LinkedList in Java
I have written the following method to validate an input String and output it as an int array. The method works completely as I need it to but I would like to add some extra validation to it so that it only allows integers and commas in the input so there are no errors.
An example correct input would be:
"7,23,62,8,1130"
The method is:
public static int[] validator (String [] check) {
int [] out = new int[5];
try
{
if (0 < Integer.parseInt(check[0]) && Integer.parseInt(check[0]) < 100)
{
out[0] = Integer.parseInt(check[0]);
}
else
{
throw new InvalidMessageException();
}
}
catch (InvalidMessageException ex)
{
System.err.println("Invalid instruction message");
return null;
}
try
{
if (0 < Integer.parseInt(check[1]))
{
out[1] = Integer.parseInt(check[1]);
}
else
{
throw new InvalidMessageException();
}
}
catch (InvalidMessageException ex)
{
System.err.println("Invalid instruction message");
return null;
}
try
{
if(0 < Integer.parseInt(check[2]))
{
out[2] = Integer.parseInt(check[2]);
}
else
{
throw new InvalidMessageException();
}
}
catch (InvalidMessageException ex)
{
System.err.println("Invalid instruction message");
return null;
}
try
{
if (0 <= Integer.parseInt(check[3]) && Integer.parseInt(check[3]) < 256)
{
out[3] = Integer.parseInt(check[3]);
}
else
{
throw new InvalidMessageException();
}
}
catch (InvalidMessageException ex)
{
System.err.println("Invalid instruction message");
return null;
}
try
{
if(0 < Integer.parseInt(check[4]))
{
out[4] = Integer.parseInt(check[4]);
}
else
{
throw new InvalidMessageException();
}
}
catch (InvalidMessageException ex)
{
System.err.println("Invalid instruction message");
return null;
}
return out;
}
I have considered doing something like:
inputText = inputText.replace(".", "");
inputText = inputText.replace(":", "");
inputText = inputText.replace(";", "");
inputText = inputText.replace("\"", "");
etc... but it does not seem a particularly great solution. If anyone has a better idea, please let me know. Thanks very much for any help!
I'd say something like this should replace your method, without having read your code, just your requirements:
String input = "7,23,62,8,1130";
if (input.matches("(?:\\d+(?:,|$))+")) {
int[] result = Arrays.stream(input.split(",")).mapToInt(Integer::parseInt).toArray();
} else {
throw new InvalidMessageException("");
}
You can use a regex expression to validate your input:
[0-9]+(,[0-9]+)*,?
Check it with the String matches(regex) method as:
if (yourString.matches("[0-9]+(,[0-9]+)*,?")) {
}
This is exactly what regular expressions are for:
return inputText.matches("\\d+(,\\d+)*");
I am currently working on an Android application that allows you to watch streaming video in a VideoView. I have a method for allowing you to select one of four streams via a switch statement. That is working correctly and the code for that is as follows:
public void playStream(int position) {
switch (position) {
case 0:
streamOn = true;
streamPos = 0;
logString = "M";
posSelected = "0";
break;
case 1:
streamOn = true;
streamPos = 1;
logString = "J";
posSelected = "1";
break;
case 2:
streamOn = true;
streamPos = 2;
logString = "B";
posSelected = "2";
break;
case 3:
streamOn = true;
streamPos = 3;
logString = "N";
posSelected = "3";
break;
default:
break;
}
checkStreamLink(position);
Log.wtf(logString, posSelected);
Log.wtf(logString, streamURL);
}
What is not working correctly is that in this method for selecting the stream, I have a call to another method ( checkStreamLink(); ) that runs a thread. Depending on which stream you have selected, the thread will call another method that opens up a webpage, reads a line of text, and then sets that text to a String streamURL. The code for those two methods is as follows:
public void checkStreamLink(final int position) {
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
try {
switch (position) {
case 0:
streamURL = getStreamLink("LINK 0 GOES HERE");
break;
case 1:
streamURL = getStreamLink("LINK 1 GOES HERE");
break;
case 2:
streamURL = getStreamLink("LINK 2 GOES HERE");
break;
case 3:
streamURL = getStreamLink("LINK 3 GOES HERE");
break;
default:
break;
}
}
catch (Exception e) {
e.printStackTrace();
}
}
});
thread.start();
}
public String getStreamLink (String textSource) {
URL streamURL;
String errorParsingURL = "ERROR PARSING URL";
try {
streamURL = new URL(textSource);
BufferedReader bufferReader = new BufferedReader(new InputStreamReader(streamURL.openStream()));
String StringBuffer;
String stringText = "";
while ((StringBuffer = bufferReader.readLine()) != null) {
stringText += StringBuffer;
}
bufferReader.close();
return stringText;
}
catch (MalformedURLException e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
return errorParsingURL;
}
The issue I'm having is that the String streamURL is returning null on its first use as evidenced by the Log statements I have included. Each time you select a stream after that, the String streamURL returns the text that you should have received the previous time you select a stream. I cannot seem to figure out why this is happening and I would appreciate any assistance.
You are getting a null because getStreamLink is returning its value after you have already printed the result. Print the result log messages at the end of the getStreamLink method to see the actual value which is being returned, and call any additional functionality at that point as well.