编辑:规则是我无法修改公式。方法必须是无效的,我必须将预初始化的数组传递给那些方法。这些是未来作业本身的限制因素,这就是为什么我试图以这种方式玩这个名字包计划。
我正在尝试编写一个“名称包”程序,以便为将来的作业带来乐趣和练习。目标是让用户有一个包。在这个包里,他们可以存储25个名字。他们可以一次添加1个名称,一次删除1个名称,对包进行排序以使名称按字母顺序排列等。基本数组练习。我遇到了一些问题,因为我对Java不是很熟悉。我有一个函数,它接受数组,将其转换为列表,尝试添加用户选择的名称,然后尝试将该列表转换回它曾经的数组。然后我有另一个函数试图显示数组中的所有内容。
当我避免使用菜单,开关盒和方法时,此代码可以正常工作。我可以将东西存储到名称包中,我可以毫无问题地显示名称,而不显示空值。但我不明白为什么名称不会显示在下面的代码中。有没有办法在Java中获得一种pass-by-reference效果?有没有更好的方法来做这种程序?我很感激任何建议!
这是我的代码:
import java.util.ArrayList;
import java.util.Scanner;
import java.util.Arrays;
public class nameBag {
public static void main(String[] args) {
String[] nameBag = new String[25];
Scanner input = new Scanner(System.in);
while (true){
System.out.println("Welcome to the bag of names.");
System.out.println("1. Add an item to the bag.");
System.out.println("2. Display items in bag.");
System.out.println("0. Exit program.");
int userChoice = input.nextInt();
switch (userChoice){
case 1:
addName(nameBag);
break;
case 2:
displayNames(nameBag);
break;
case 0:
System.out.println("See ya!");
System.exit(0);
}
}
}
public static void addName(String[] nameBag){
ArrayList<String> nameList = new ArrayList<String>(Arrays.asList(nameBag));
Scanner input = new Scanner(System.in);
System.out.println("What name do you want to add to the pack?");
String userSelection;
userSelection = input.nextLine();
nameList.add(userSelection);
nameBag = nameList.toArray(nameBag);
}
public static void displayNames(String[] nameBag){
for (String s : nameBag) {
if (!(s == null)) {
System.out.println(s);
}
}
}
}
答案 0 :(得分:1)
在处理之前检查输入是否为int类型,或者在处理输入之前执行所需的异常处理。
使用扫描程序hasNextInt()验证输入是否为int。
Scanner input = new Scanner(System.in);
while (!input.hasNextInt()) {
System.out.println("Please enter int values only");
input.nextLine();
}
如果没有提供int,你也可以做一些异常处理以抛出异常
try {
Scanner input = new Scanner(System.in);
int userChoice = input.nextInt();
} catch (Exception e) {
System.out.println("Please re-enter");
}
转换为数组
Arrays.asList(string.toCharArray());
如果你想将作为字符串数组
ArrayList<String> myList = new ArrayList<String>();
myList.add("value1");
myList .add("value2");
String[] myStringArray = new String[myList.size()];
myStringArray = myList.toArray(myStringArray);
答案 1 :(得分:0)
Java始终按值传递,因此没有按引用传递,但在大多数情况下,您的值是对对象的引用。
例如,如果向传递给方法的List添加元素,则可以在调用方法中看到该元素,因为传递给该方法的值实际上是对列表的引用。
您遇到的问题是此方法:
public static void addName(String[] nameBag){
ArrayList<String> nameList = new ArrayList<String>(Arrays.asList(nameBag));
Scanner input = new Scanner(System.in);
System.out.println("What name do you want to add to the pack?");
String userSelection;
userSelection = input.nextLine();
nameList.add(userSelection);
nameBag = nameList.toArray(nameBag);
}
你在主方法中使用名为nameBag的数组,这是引用(1)。
你调用你的addName(nameBag(1))(我将在括号中标记对象的引用)
然后你会做第一行
ArrayList<String> nameList = new ArrayList<String>(Arrays.asList(nameBag(1)));
仍然使用相同的名字包。然后使用ArrayList做很多事情,这完全没问题 但是现在你做了
nameBag = nameList.toArray(nameList); //I assume a typo here
你的nameBag将成为nameBag(2),因为你会将另一个数组引用放入同一个变量中,所以从这一刻起你的方法中没有对nameBag(1)的引用。停止这种编程错误的最简单方法是将方法参数声明为final。
你可以用nameBag做的是你可以为索引分配一个值,这样如果你确实在调用者中看到了nameBag [1] =“foo”,但你无法重新赋值,因为你正在研究一个完全不同的物体。
你可以做的是要么不使用数组而不是使用List但是如果这是一个数组练习,只需返回你在最后一行创建的nameBag并在main方法中重新设置数组
答案 2 :(得分:0)
试试这段代码效果很好。你犯了几个错误,这就是它无法正常工作的原因。我已将您的代码保留为注释,理解起来会很方便。
记住这一点。这将有助于我希望: 1.尝试使用List或Set而不是Arrays,因为Arrays不是动态大小 2.默认情况下,树集将对内容进行排序 3.当不需要时,不要将值传递给方法
import java.util.ArrayList;
import java.util.Scanner;
import java.util.Arrays;
import java.util.Set;
import java.util.TreeSet;
public class nameBag {
static Set<String> nameBagSet = new TreeSet<String>();
public static void main(String[] args) {
//String[] nameBag = new String[25];
Scanner input = new Scanner(System.in);
while (true){
System.out.println("Welcome to the bag of names.");
System.out.println("1. Add an item to the bag.");
System.out.println("2. Display items in bag.");
System.out.println("0. Exit program.");
int userChoice = input.nextInt();
switch (userChoice){
case 1:
addName();
break;
case 2:
displayNames();
break;
case 0:
System.out.println("See ya!");
System.exit(0);
}
}
}
public static void addName(){
// ArrayList<String> nameList = new ArrayList<String>(Arrays.asList(nameBag));
Scanner input = new Scanner(System.in);
System.out.println("What name do you want to add to the pack?");
String userSelection;
userSelection = input.nextLine();
nameBagSet.add(userSelection);
// nameList.add(userSelection);
// nameBag = nameList.toArray(nameBag);
}
public static void displayNames(){
for (String s : nameBagSet) {
if (!(s == null)) {
System.out.println(s);
}
}
} }
答案 3 :(得分:0)
addName方法中的以下行在实际执行中没有任何影响。 nameBag = nameList.toArray(nameBag);
原因是,你真的在改变你的本地变量&#34; nameBag&#34;指向一个新的数组。这对主函数中定义的变量没有影响。
要真正了解正在发生的事情,请将addName的变量名称更改为其他名称。对于例如paramNameBag。您将立即了解正在发生的事情。当您进行这样的更改时,您希望上面的行实际上是指main方法中定义的变量。但是你不能在这里访问它,因为它是main方法的本地方法。由于您使用的是所有静态方法,因此唯一可以实现的方法是将nameBag声明移出并使其静止。
还有另一种快速而肮脏的解决方案。将addName签名更改为下面,并从该方法返回该数组。然后,您可以将返回的数组重新分配给主变量。
public static String[] addName(String[] nameBag, String userSelection){
.....
.....
return nameList.toArray(nameBag);
}
switch (userChoice){
case 1:
namesBag = addName(nameBag);
这应该这样做。
但我真的建议首先使用ArrayList而不是数组,然后来回转换为ArrayList。
祝你好运
答案 4 :(得分:0)
没有进入良好的编码约定,你的程序中有两个错误
1st displayNames(nameBag
您似乎已在编辑中更正了
和第二个错误与理解java中的参数有关。您不能将nameBag作为参数传递,并将值添加到这些参数。每次函数addName()结束执行时,这些值都会丢失。您可以在类变量下声明静态变量nameBag并直接操作它,而不是将其作为参数传递。这样,即使addName()displayName()函数结束执行(只要程序正在运行),您的更改也会反映出来。另外,你不需要任何退货类型。您可以直接访问全局List变量。
import java.util.ArrayList;
import java.util.Scanner;
import java.util.Arrays;
public class HelloWorld{
static String[] nameBag; // NameBag is declared as class variable
static{
nameBag = new String[25]; //initialize nameBag
}
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
while (true){
System.out.println("Welcome to the bag of names.");
System.out.println("1. Add an item to the bag.");
System.out.println("2. Display items in bag.");
System.out.println("3. Exit program.");
int userChoice=0;
try{
userChoice = input.nextInt();
}
catch(Exception e){
e.printStackTrace();
}
switch (userChoice){
case 1:
addName(); //No need to pass nameBag as a parameter
break;
case 2:
displayNames(); //No need to pass nameBag as a parameter
break;
case 3:
System.out.println("See ya!");
System.exit(0);
}
}
}
public static void addName(){
//everything is same here, just accessing nameBag directly
Scanner input = new Scanner(System.in);
System.out.println("What name do you want to add to the pack?");
String userSelection;
userSelection = input.nextLine();
ArrayList<String> nameList = new ArrayList<String>(Arrays.asList(nameBag));
nameList.add(userSelection);
nameBag = nameList.toArray(nameBag);
}
public static void displayNames(){
//everything is same here, just accessing nameBag directly
for (String s : nameBag) {
if (!(s == null)) {
System.out.println(s);
}
}
}
}
答案 5 :(得分:0)
没有通过引用发送基于类的对象的简单方法,所有类都以这样的方式传递,即对它们的引用作为复制为值的参数传递。
为了避免这种情况,你可以使用一个持有指针的Holder对象,那个作为引用发送的是指向Holder对象的指针,但是它内部的对象实际上是指向你想要的对象的指针。操纵。
所以而不是:
public class nameBag
{
public static void main(String[] args)
{
String[] nameBag = new String[25];
你会:
public class ArrayHolder
{
private String[] nameBag;
public ArrayHolder(String[] nameBag)
{
this.setNameBag(nameBag);
}
public String[] getNameBag()
{
return this.nameBag;
}
public void setNameBag(String[] nameBag)
{
this.nameBag = nameBag;
}
//by the way, if these functions break your limitations,
//then it works even if nameBag is just a simple public variable
}
然后你可以:
public class nameBag
{
public static void main(String[] args)
{
String[] nameBag = new String[25];
ArrayHolder arrayHolder = new ArrayHolder(nameBag);
...
但是你必须将ArrayHolder发送到你的函数:
public static void addName(ArrayHolder arrayHolder)
{
//everything is same here, just accessing nameBag directly
Scanner input = new Scanner(System.in);
System.out.println("What name do you want to add to the pack?");
String userSelection = input.nextLine();
ArrayList<String> nameList = new ArrayList<String>(Arrays.asList(arrayHolder.getNameBag()));
nameList.add(userSelection);
nameBag = nameList.toArray(new String[nameList.size()]);
}
但正如您最初所说,Array必须是参数,它不能是您自己的ArrayHolder对象;在这个前提下,我想唯一的解决方案就是你需要把它变成一个静态变量。