使用Scanner对象的Close方法后,程序报错:NoSuchElementException

使用Scanner对象的Close方法后,程序报错:NoSuchElementException

package com.imooc2.course.Course5_1_Shopping;

// 商品类 属性:商品ID,商品名称,商品价格,商品描述
public class Goods {
	private String goodsId;// 商品ID
	private String goodsName;// 商品名称
	private double price;// 商品价格
	private String goodsDesp;// 商品描述

	public Goods(String goodsId, String goodsName, double price, String goodsDesp) {
		super();
		this.setGoodsId(goodsId);
		this.setGoodsName(goodsName);
		this.setPrice(price);
		this.setGoodsDesp(goodsDesp);
	}

	public String getGoodsId() {
		return goodsId;
	}

	public void setGoodsId(String goodsId) {
		this.goodsId = goodsId;
	}

	public String getGoodsName() {
		return goodsName;
	}

	public void setGoodsName(String goodsName) {
		this.goodsName = goodsName;
	}

	public double getPrice() {
		return price;
	}

	public void setPrice(double price) {
		this.price = price;
	}

	public String getGoodsDesp() {
		return goodsDesp;
	}

	public void setGoodsDesp(String goodsDesp) {
		this.goodsDesp = goodsDesp;
	}

	@Override
	public String toString() {
		return "商品信息 [编号:" + goodsId + ", 名称:" + goodsName + ", 价格:" + price + ", 描述:" + goodsDesp + "]";
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((goodsId == null) ? 0 : goodsId.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (Goods.class == obj.getClass()) {
			Goods goods = (Goods) obj;
			return this.getGoodsId().equals(goods.getGoodsId());
		}
		return false;
	}
}
//购物车中的商品类:属性:商品,数量 
package com.imooc2.course.Course5_1_Shopping;
public class GoodsInCart {
	private Goods goods;
	private int num;

	public GoodsInCart() {

	}

	public GoodsInCart(Goods goods, int num) {
		super();
		this.setGoods(goods);
		this.setNum(num);
	}

	public Goods getGoods() {
		return goods;
	}

	public void setGoods(Goods goods) {
		this.goods = goods;
	}

	public int getNum() {
		return num;
	}

	public void setNum(int num) {
		this.num = num;
	}

	@Override
	public String toString() {
		return "商品编号:" + goods.getGoodsId() + ", 商品名称:" + goods.getGoodsName() + ", 商品价格:" + goods.getPrice()
				+ ", 商品描述:" + goods.getGoodsDesp() + ", 数量:" + this.getNum();
	}

}
//商品管理类
package com.imooc2.course.Course5_1_Shopping;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

public class GoodsManager {
	private Set<Goods> goodsSet;
	
	public GoodsManager() {

	}

	public GoodsManager(Set<Goods> goodsSet) {
		super();
		this.goodsSet = goodsSet;
	}

	public Set<Goods> getGoodsSet() {
		if (goodsSet == null)
			goodsSet = new HashSet<Goods>();
		return goodsSet;
	}

	public void setGoodsSet(Set<Goods> goodsSet) {
		this.goodsSet = goodsSet;
	}

	//导入商品
	public void importGoods() {
		Goods good1 = new Goods("goods004", "手机", 2300.0, "android手机");
		Goods good2 = new Goods("goods002", "饮水机", 299.0, "带净化功能的饮水机");
		Goods good3 = new Goods("goods003", "笔记本电脑", 4999.0, "15寸笔记本电脑");
		Goods good4 = new Goods("goods001", "水杯", 56.0, "不锈钢水杯");
		this.getGoodsSet().add(good1);
		this.getGoodsSet().add(good2);
		this.getGoodsSet().add(good3);
		this.getGoodsSet().add(good4);
		System.out.println("商品信息导入成功");
	}

	//展示商品
	public void showGoods() {
		if (this.getGoodsSet().isEmpty()) {
			System.out.println("还没有商品,记得导入商品信息哟");
			return;
		}
		System.out.println("所有商品信息为:");
		Iterator<Goods> it = this.getGoodsSet().iterator();
		while (it.hasNext()) {
			System.out.println(it.next());
		}
	}
}
//购物车管理类
package com.imooc2.course.Course5_1_Shopping;
import java.util.HashMap;
import java.util.InputMismatchException;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Scanner;
import java.util.Set;

public class ShoppingCart {
	private Map<String, GoodsInCart> shoppingCart;

	public ShoppingCart() {

	}
	
	public Map<String, GoodsInCart> getShoppingCart() {
		if (shoppingCart == null)
			shoppingCart = new HashMap<String, GoodsInCart>();
		return shoppingCart;
	}
	public void setShoppingCart(Map<String, GoodsInCart> shoppingCart) {
		this.shoppingCart = shoppingCart;
	}

	//添加商品到购物车
	public void addGoodsToShoppingCart(GoodsManager goodsManager) {
		if (goodsManager.getGoodsSet().isEmpty()) {
			System.out.println("商城中还没有商品,请先导入系统预定商品!");
			return;
		}
		goodsManager.showGoods();
		String goodNum = "";//接收加入购物车的商品编号
		int shopNum = 0;//接收将商品加入购物车的数量
		GoodsInCart goodsInCart = new GoodsInCart();// 购物车中商品信息,含有商品名称和商品数量
		Scanner sc = new Scanner(System.in);
		boolean iDIsexit = false;//判断输入的ID是否已经添加到了购物车
		do {	
			System.out.println("请输入商品编号:");
			goodNum = sc.next();					
				
			if (this.getShoppingCart().containsKey(goodNum)) {
				System.out.println("该商品已添加至购物车中,如需修改,请选择修改购物车中的商品数量");
				return;// 如果使用continue要求重新输入编号的话,当购物车中添加了所有编号的商品时,会进入死循环;
			}
			for (Goods it : goodsManager.getGoodsSet()) {
				if (it.getGoodsId().equals(goodNum)) {
					goodsInCart.setGoods(it);// 将对应编号的商品,添加到购物车
					iDIsexit = true;
					break;
				}
			}
			if (!iDIsexit) {
				System.out.println("你输入的商品编号不存在,请重新输入:");
				continue;
			} else {
				while (true) {
					try {
						System.out.println("请输入购买数量:");
						shopNum = sc.nextInt();
						break;
					} catch (InputMismatchException e) {
						System.out.println("请输入整数:");
						sc.next();
						continue;
					} catch (Exception e) {
						e.printStackTrace();
						break;
					}
				}
				goodsInCart.setNum(shopNum);// 将输入的商品数量,保存到购物车
				break;
			}
		} while (true);

		this.getShoppingCart().put(goodNum, goodsInCart);// 将商品编号和对应的购买信息存入当前集合map;
		// sc.close();此处不能使用close()方法,否则执行此方法后,再次遇到sc.next()会报错,为什么呢?我明明只关闭的是当前方法的Scanner对象呀!
		System.out.println("商品添加购物车成功!");
	}

	//修改购物车中的商品数量
	public void editNumInShopping() {
		String goodsId = "";
		int shoppingNum = 0;
		if (this.getShoppingCart().isEmpty()) {
			System.out.println("当前购物车是空的,请先添加商品到购物车");
			return;
		}
		Scanner sc = new Scanner(System.in);
		do {
			this.showGoodsInShooping();
			System.out.println("请输入要修改的商品编号:");
			goodsId = sc.next();
			
			if (!this.shoppingCart.containsKey(goodsId)) {
				System.out.println("在购物车中找不到你输入的商品编号,请重新输入:");
				continue;
			} else {
				while (true) {
					try {
						System.out.println("请输入新的购买数量");
						shoppingNum = sc.nextInt();
						break;
					} catch (InputMismatchException e) {
						System.out.println("请输入整数:");
						sc.nextLine();
						continue;
					} catch (Exception e) {
						e.printStackTrace();
						break;
					}
				}
				if (shoppingNum == 0) {
					System.out.println("购物车中的" + shoppingCart.get(goodsId).getGoods().getGoodsName() + "已清空");
					shoppingCart.remove(goodsId);
				} else
					shoppingCart.get(goodsId).setNum(shoppingNum);
				break;
			}
		} while (true);
		// sc.close();
	}

	//显示购物车中的商品信息
	public void showGoodsInShooping() {
		System.out.println("显示购物车中的所有商品信息");
		if (this.getShoppingCart().isEmpty()) {
			System.out.println("还没有商品加入到购物车");
			return;
		}
		Iterator<GoodsInCart> it = shoppingCart.values().iterator();
		while (it.hasNext()) {
			System.out.println(it.next());
		}

	}

	//结算购物车中的商品总价
	public void countPrice() {
		System.out.println("结算");
		if (this.getShoppingCart().isEmpty()) {
			System.out.println("还没有商品加入到购物车");
			return;
		}
		int sumPrice = 0;//购物车中的商品总价
		for (GoodsInCart goodsInCart : shoppingCart.values()) {
			sumPrice += goodsInCart.getNum() * goodsInCart.getGoods().getPrice();
		}
		System.out.println("商品的总价为:" + sumPrice);
		showGoodsInShooping();

		// 方法1:通过便利得到key值,再使用HashMap的remove(key)的方法清空该集合,这样在删除多个元素的场景会报错:concurrentmodificationexception
		/**
		 * for (String key : this.getShoppingCart().keySet()) {
		 * 		this.getShoppingCart().remove(key); 
		 * }
		 **/
		
		//方法二,将HashMao转化为Set集合,再使用Set集合中的removeAll方法可以清空集合
		Set<Entry<String, GoodsInCart>> set = this.getShoppingCart().entrySet();
		set.removeAll(set);
	}
}

//主方法:
package com.imooc2.course.Course5_1_Shopping;

import java.util.InputMismatchException;
import java.util.Scanner;

public class Test {

	//展示主菜单
	static void showMasterMeau() {
		System.out.println("*******************************");
		System.out.println("           **主菜单**");
		System.out.println("           1--商品管理");
		System.out.println("           2--购物车");
		System.out.println("           0--退出");
		System.out.println("*******************************");
		System.out.println("请选择对应数字进行操作:");
	}

	//展示商品管理菜单
	static void showGoodsManagerMeau() {
		System.out.println("*******************************");
		System.out.println("           **商品管理**");
		System.out.println("           1--商品信息导入");
		System.out.println("           2--显示所有商品信息");
		System.out.println("           9--返回上一级菜单");
		System.out.println("*******************************");
		System.out.println("请选择对应数字对商品进行管理:");
	}

	//展示购物车菜单
	static void showShoppingManagerMeau() {
		System.out.println("*******************************");
		System.out.println("           **购物车管理**");
		System.out.println("           1--添加商品到购物车");
		System.out.println("           2--修改购物车中的商品数量");
		System.out.println("           3--显示购物车中的所有商品信息");
		System.out.println("           4--结算");
		System.out.println("           9--返回上一级菜单");
		System.out.println("*******************************");
		System.out.println("请输入对应的数字对购物车进行管理:");
	}

	GoodsManager goodsManager = new GoodsManager();//实例化商品管理类
	ShoppingCart shoppingCart = new ShoppingCart();//实例化购物车管理类
	Scanner sc = new Scanner(System.in);

	//商品管理相关功能
	void goodsManager() {
		int goodsManagerSelector = 0;//存放商品管理菜单输入的指令
		do {
			while (true) {
				try {
					showGoodsManagerMeau();
					goodsManagerSelector = sc.nextInt();
					break;
				} catch (InputMismatchException e) {
					System.out.println("请输入整数:");
					sc.nextLine();
					continue;
				} catch (Exception e) {
					e.printStackTrace();
					break;
				}
			}
			if (goodsManagerSelector == 1) {
				goodsManager.importGoods();
			} else if (goodsManagerSelector == 2) {
				goodsManager.showGoods();
			} else if (goodsManagerSelector == 9) {
				return;
			} else {
				System.out.println("你输入的指令不存在请重新输入:");
				continue;
			}
		} while (true);

	}

	//购物车相关功能
	void shopManager() {
		int shoppingManagerSelector = 0;//存放购物车菜单相关指令
		do {
			while (true) {
				try {
					showShoppingManagerMeau();
					shoppingManagerSelector = sc.nextInt();//如果添加商品的方法中又sc.close(),当购物车中添加商品的方法执行后,再次执行到此处会报错:NoSuchElementException
					break;
				} catch (InputMismatchException e) {
					System.out.println("请输入整数:");
					sc.nextLine();
					continue;
				} catch (Exception e) {
					e.printStackTrace();
					break;
				}
			}
			switch (shoppingManagerSelector) {
			case 1:
				shoppingCart.addGoodsToShoppingCart(goodsManager);
				break;
			case 2:
				shoppingCart.editNumInShopping();
				break;
			case 3:
				shoppingCart.showGoodsInShooping();
				break;
			case 4:
				shoppingCart.countPrice();
				break;
			case 9:
				return;
			default:
				System.out.println("你输入的指令不存在请重新输入:");
				continue;
			}
		} while (true);

	}

	public static void main(String[] args) {
		int masterMeauSelector = 0;//存放主菜单选择的指令
		Test test = new Test();
		Scanner sc = new Scanner(System.in);
		do {
			while (true) {
				try {
					showMasterMeau();
					masterMeauSelector = sc.nextInt();
					break;
				} catch (InputMismatchException e) {
					System.out.println("请输入整数:");
					sc.nextLine();
					continue;
				} catch (Exception e) {
					e.printStackTrace();
					break;
				}
			}
			if (masterMeauSelector == 1) {
				test.goodsManager();
			} else if (masterMeauSelector == 2) {
				test.shopManager();
			} else if (masterMeauSelector == 0) {
				break;

			} else {
				System.out.println("没有该指令对应的操作,请重新选择:");
				continue;
			}
		} while (true);
		sc.close();

	}

}

=====================================================

各位大侠,通过这个作业,

我一共有三个疑问:

问题1:为什么使用Scanner对象的Close方法后,再次遇到其他Scanner对象的next()方法时程序会报错?

问题2:为了保证输入的数字是整数,我使用了很多的TryCatch语句块,感觉太繁琐了,有没有更加简洁的办法?

问题3:当输入的字符被定义为字符串时,是不是就不会有什么异常,不需要TryCatch语句块去处理了?

关于本题实现,如果有其他建议,希望大家指正~

======================

新手上路,多多关照~

正在回答

登陆购买课程后可参与讨论,去登陆

2回答

1、NoSuchElementException是没有元素可以迭代异常。sc.close();进行关闭处理,会把System.in也关闭了,System.in是InputStream的对象,并且关掉之后不能再打开。所以建议不要关闭Scanner对象

,一般是不关闭Scanner对象的。如果一定要关,建议你在停止整个程序的时候,再关掉。


好帮手慕阿莹 2018-07-28 23:57:15

1、因为你把Scanner对象关掉之后,再次使用的时候,这个对象就被销毁了,再次使用的时候自然就会抛异常。

2、对于要输入数字的时候,输入非数字,本题中不做作业要求,如果同学想处理一下,只能try catch处理一下了。

3、同学的想法是可以的,当switch判断时,可以用字符来代替数字。继续加油!

如果我的回答解决了你的问题,请采纳,祝学习愉快.

  • 提问者 杨勤_cd #1
    第一个问题:可是我关掉的只是购物车管理类中Scanner对象的方法: shoppingCart.addGoodsToShoppingCart(goodsManager); 没有关掉测试类中的Scanner对象,而且在程序调试的时候我看主方法的Scanner对象也是开着的; 最后我还单独测试了下,如果是因为Scanner对象被关闭的话,应该会报: java.lang.IllegalStateException: Scanner closed 而不是现在的:NoSuchElementException
    2018-07-29 11:18:35
问题已解决,确定采纳
还有疑问,暂不采纳

恭喜解决一个难题,获得1积分~

来为老师/同学的回答评分吧

0 星
请稍等 ...
意见反馈 帮助中心 APP下载
官方微信

在线咨询

领取优惠

免费试听

领取大纲

扫描二维码,添加
你的专属老师