Java: returning a string from a method - java

I'd like to point out that I'm very new to Java, which is why I may be making stupid mistakes.
I have a class called "Characters", which consists of 4 variables and multiple methods. All variables are private, so from what I've read, I need to use methods to do anything to them.
One of the methods is supposed to return one of the variables in string form, however I keep getting an error from both eclipse and when I run it. "This method must return a result of type "String". The error occurs on the first line of the method:
public String displayStats(String option) {
switch (option) {
case "charName":
System.out.println(charName);
return charName;
case "charHealth":
System.out.println(charHealth);
String charHealth2 = Integer.toString(charHealth);
return charHealth2;
case "charMana":
System.out.println(charMana);
String charMana2 = Integer.toString(charMana);
return charMana2;
case "charStamina":
System.out.println(charStamina);
String charStamina2 = Integer.toString(charStamina);
return charStamina2;
default:
System.out.println("Error on default");}
}
}
The full class:
package basics;
public class Characters {
private String charName = "";
private int charHealth = 0;
private int charMana = 0;
private int charStamina = 0;
public void summoner(Characters player) {
player.charName = "Summoner";
player.charHealth = 80;
player.charMana = 150;
player.charStamina = 50;}
public void sentinel(Characters player) {
player.charName = "Sentinel";
player.charHealth = 200;
player.charMana = 50;
player.charStamina = 100;}
public void beserker(Characters player) {
player.charName = "Beserker";
player.charHealth = 100;
player.charMana = 0;
player.charStamina = 200;}
public void mage(Characters player) {
player.charName = "Mage";
player.charHealth = 80;
player.charMana = 200;
player.charStamina = 20;}
public String displayStats(String option) {
switch (option) {
case "charName":
System.out.println(charName);
return charName;
case "charHealth":
System.out.println(charHealth);
String charHealth2 = Integer.toString(charHealth);
return charHealth2;
case "charMana":
System.out.println(charMana);
String charMana2 = Integer.toString(charMana);
return charMana2;
case "charStamina":
System.out.println(charStamina);
String charStamina2 = Integer.toString(charStamina);
return charStamina2;
default:
System.out.println("Error on default");}
}
}

You aren't returning anything in the default case of your switch statement, which means that there is a possibility (however small) that the method won't know what to return.

In the displayStats function you don't return a String in all paths of your code.
This is because the default doesn't return at all.
Maybe you wanted to write:
default:
return "Error on default";

Two problems: charName is a string, but charHealth, charMana, and charStamina are ints. Thus, your displayStats function isn't always returning a string.
Also, your default option in your switch statement should return a string as well.
It would be better to create an accessor function for each variable:
public String getCharName() {
return charName;
}
public int getCharHealth() {
return charHealth;
}
etc.

The method displayStats must always return a String or throw an exception. Since the code implies that the default case is an error, then throw an exception. At this point rather than create a new class of exception, just throw an IllegalArgumentException -- new IllegalArgumentException(option). When printed out it will state the type of exception and the value of the invalid option.

Related

How to change from Constructors to Enum in java?

I have these integers and this method which uses constructors but I am supposed to change this into an Enum since thise code is outdated. I do understand how Enums work in theory but no matter what I try to change I do it wrong.
public static final int CHILDRENS = 2;
public static final int REGULAR = 0;
public static final int NEW_RELEASE = 1;
private Price price;
public void setPriceCode(int priceCode) {
switch (priceCode) {
case REGULAR:
price = new RegularPrice();
break;
case CHILDRENS:
price = new ChildrensPrice();
break;
case NEW_RELEASE:
price = new NewReleasePrice();
break;
default:
throw new IllegalArgumentException("Incorrect Price Code");
}
}
I thaught that to change to enums I should first delete the given integers at the top and then add this before the method:
enum cases {
REGULAR, CHILDRENS, NEW_RELEASE;
}
And now I do not know how to change the method's code accordingly.
How do I give the cases the integers, should I not delete these: ?
public static final int CHILDRENS = 2;
How should I change my switch case accordingly?
Would really appreciate some help, I watched a bunch of videos on enums but the cases were very different.
Do it like this:
enum PriceCode {
REGULAR(0), // calls constructor with value 0
NEW_RELEASE(1), // calls constructor with value 1
CHILDREN(2) // calls constructor with value 2
;
private final int priceCode;
private PriceCode(int priceCode) {
this.priceCode = priceCode;
}
int value() {
return priceCode;
}
}
public class Main {
// Usage
public static void setPriceCode(PriceCode priceCode) {
System.out.println("The value of " + priceCode + " is " + priceCode.value());
switch (priceCode) {
case REGULAR:
// Do something
break;
case CHILDREN:
// Do something
break;
case NEW_RELEASE:
// Do something
break;
default:
throw new IllegalArgumentException("Incorrect Price Code");
}
}
public static void main(String[] args) {
// Set price code as CHILDREN
setPriceCode(PriceCode.CHILDREN);
// Another sample usage
System.out.println("Price code of NEW_RELEASE is " + PriceCode.NEW_RELEASE.value());
}
}
Output:
The value of CHILDREN is 2
Price code of NEW_RELEASE is 1
Learn more about enum and enum constructor at Java tutorial by Oracle.
Think of an enum as a class or interface, in other words it is a type. I recommend the following tutorial: Enum Types And according to java coding conventions, names of types should begin with a capital letter. Therefore, in the below code, I changed the name of the enum to Cases.
Hence the parameter to method setPriceCode should be Cases. The rest of the code remains the same.
enum Cases {
REGULAR, CHILDRENS, NEW_RELEASE;
}
private Price price;
public void setPriceCode(Cases priceCode) {
switch (priceCode) {
case REGULAR:
price = new RegularPrice();
break;
case CHILDRENS:
price = new ChildrensPrice();
break;
case NEW_RELEASE:
price = new NewReleasePrice();
break;
default:
throw new IllegalArgumentException("Incorrect Price Code");
}
}
Here is an example call to method setPriceCode()
setPriceCode(Cases.CHILDRENS);

Getting a parameter's value change to persist after function ending in Java [duplicate]

This question already has answers here:
Java : Best way to pass int by reference
(7 answers)
Closed 5 years ago.
I have a program which is meant to be a client/server game question game. I've made it as far as accounting various cases of the client/server sending a termination command for the end of the game.
Now, my issue is that I have a set of primitive int points, attempts, correct which are read by the client from the server in a String as below:
N.B. I do know that Java functions pass parameters by value, not reference, and that assigning the value inside of the function will not change the value of the original.
int points = accepted = correct = 0;
String inbound = check (inbound, points, accepted, correct);
System.out.println(points); // Displays value of 0, when expecting > 0
private static String check (String str, int points, int attempts, int correct) {
// Expect Q QuestionString
if (str.substring(0,1).equals("Q")) {
//System.out.println("This is the question.");
return str.substring(2, str.length());
}
String[] input = str.split(" ");
// Expect EX # # #
if (input[0].contains("EX")) {
points = Integer.parseInt(input[1]);
attempts = Integer.parseInt(input[2]);
correct = Integer.parseInt(input[3]);
return "EX";
}
// Expected strings: Correct..., Incorrect.
return str;
}
I am unsure how to workaround this issue without jeopardizing encapsulation or hindering other concepts.
Create a wrapper class to contain those three integer parameters then simply pass an instance of that wrapper to the check method and then modify its contents within the method.
example:
public class Wrapper
{
private int points;
private int attempts;
private int correct;
public int getPoints() {
return points;
}
public void setPoints(int points) {
this.points = points;
}
public int getAttempts() {
return attempts;
}
public void setAttempts(int attempts) {
this.attempts = attempts;
}
public int getCorrect() {
return correct;
}
public void setCorrect(int correct) {
this.correct = correct;
}
}
thus the first part of your code will become:
Wrapper wrapper = new Wrapper();
String inbound = check (inbound, wrapper);
System.out.println(wrapper.getPoints());
and your check method becomes:
private static String check (String str, Wrapper wrapper) {
...
...
if (input[0].contains("EX")) {
wrapper.setPoints(Integer.parseInt(input[1]));
wrapper.setAttempts(Integer.parseInt(input[2]));
wrapper.setCorrect(Integer.parseInt(input[3]));
return "EX";
}
...
...
}

How can I replace a switch in Java with a list that references a variable for each case?

I was unable to find a prior question like this here (which surprises me), so..
I have a working Java program where part of it analyzes typed input. Some input 'options' are the strings in the cases below.
switch (varName.toLowerCase()) {
case "steps":
common.steps = true;
break;
case "scale":
common.scale = true;
break;
case "float":
common.fracts = false;
break;
case "fraction":
common.fracts = true;
break;
case "spaces":
common.spaces = false;
break;
... etc.
}
In C or C++, I could shorten this code by making a list (which is a structure containing a string name and a variable pointer) such as
LIST varAction[] = { { "steps", &common.steps },
{ "scale", &common.scale },
.. etc.
};
and then simply checking in a loop with i = 0 thru size of the list
if ( strcmp(varAction[i].name, input) == 0) {
*varAction[i].pointer = condition;
}
The Java switch occurs more than once and is a maintenance problem, which is why I want a better way.
I could use a hashed index into an array using the hash of the string, but that would prevent me from using the specific variable names thru the code as needed, making that code less clear... i.e. I don't want to do (pseudo-code)
hashTable[varName] instead of (for example)
if ( common.fracts )
{ do something }
There must be a better way? Is there? Thanks in advance.
From your question, it's fairly clear that you know you can't do what you've said you'd do in C/C++, but just for others coming to the question: Java doesn't have references to variables.
It's tempting to push the question out a level: Look at why you have varName in the first place and see if you can avoid it.
The Java switch occurs more than once and is a maintenance problem, which is why I want a better way.
That suggests that common should have accessor function(s) for this information, so the switch exists only in one place (the getter) or two places (the getter and the setter).
void setThingy(String name, boolean value) {
switch (name.toLowerCase()) {
case "steps":
this.steps = value;
break;
case "scale":
this.scale = value;
break;
case "float":
this.fracts = value;
break;
case "fraction":
this.fracts = value;
break;
case "spaces":
this.spaces = value;
break;
// ... etc.
}
}
boolean getThingy(String name) {
switch (name.toLowerCase()) {
case "steps":
return common.steps;
case "scale":
return common.scale;
case "float":
return this.fracts;
case "fraction":
return this.fracts;
case "spaces":
return this.spaces;
// ... etc.
}
}
If common's class isn't something you can change, a static utility function somewhere would also work, but better if it's in the class if possible.
With Java 8+ you could use something like:
Map<String, Runnable> actions = new HashMap<> ();
actions.put("steps", () -> common.steps = true);
actions.put("scale", () -> common.scales = true);
//etc.
then in your code:
actions.get(varName.toLowerCase()).run(); //need null check
You could do it with Java 7- too using anonymous classes but it would be more verbose.
Here’s an option, developing my idea from the comment just a little bit. Not sure whether you will like it, I’d like to offer it in case.
public class Common {
private Map<String, Boolean> options = new HashMap<>();
public void setOption(String varName, boolean condition) {
options.put(varName.toLowerCase(), condition);
}
public boolean isSteps() { return options.get("steps"); }
public boolean isFracts() { return options.get("fractions"); }
public boolean isScale() { return options.get("scale"); }
}
You may want to put in some defense, for instance to avoid setting non-existing options.
Edit: Drawing on David Foerster’s comments on enums, here’s a solution using them:
public enum Option {
steps, scale, fraction;
private boolean option = false;
public static void setOption(String varName, boolean condition) {
valueOf(varName.toLowerCase()).option = condition;
}
public boolean isSet() {
return option;
}
}
Now the lookup happens in the setter, not in the getter. Defence against setting non-existing options is built-in: you will get an exception if you try, this behaviour can of course be modified if you prefer. The solution is quite extensible, it’s easy to add more enum constants if the need arises.
Warning: It's been a while since I last wrote some Java, and this is probably against best practices, so continue with care! Also it's just a quick and dirty example, I wrote this on a (not up to date) mobile phone...
You could try to use reflection:
class Common {
public boolean a;
public boolean b;
public boolean tryToSet(String field, boolean value) throws java.lang.Exception {
Class<?> cl = this.getClass();
try {
Field f = cl.getDeclaredField(field);
f.setBoolean(this, value);
return true;
} catch(NoSuchFieldException e) {
return false;
}
}
}
Returning a boolean gives you the possibility to implement a "default case":
if (! c.tryToSet("x", false)) {
System.out.println("some default case");
}
Try this:
import java.util.Scanner;
public class TestCases
{
static boolean steps = false;
static boolean fracts;
static boolean scale;
public static void main( String[] args )
{
Scanner input = new Scanner( System.in );
System.out.println( "Type the input" );
String typedInput = input.nextLine();
Object[][] tests = { { "steps", steps }, { "float", fracts }, { "scale", scale } };
for( int i = 0; i < tests.length; i++ )
{
if( typedInput.equals( tests[ i ][ 0 ] ) )
{
tests[ i ][ 1 ] = true;
break;
}
}
for( int i = 0; i < tests.length; i++ )
{
for( int j = 0; j < tests[ i ].length; j++ )
{
System.out.print( tests[ i ][ j ] + " " );
}
System.out.println();
}
}
}
All necessary conversions are automatically done.

Need help getting my Java Rock-Paper-Scissors game to compile [closed]

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 8 years ago.
Improve this question
I've been trying to get this code to work for the past week now, and every time I make one change I end up with more bugs. Can anyone help figure out where I've gone wrong?
The code is split up into two files: a runner class, and a class with all the methods.
import java.util.Scanner;
import static java.lang.System.*;
public class RPSRunner
{
public static void main(String args[])
{
Scanner keyboard = new Scanner(System.in);
String response = "";
String player = "";
RockPaperScissors game = new RockPaperScissors();
System.out.print("What is your name? : ");
player = keyboard.next();
out.print("type in your prompt [R,P,S] :: ");
response = keyboard.next();
game.setPlayers();
game.convertUserInput(response);
game.setPlayerChoice(response);
game.computerThink();
game.determineWinner();
}
}
The method class:
import java.util.Scanner;
import static java.lang.System.*;
import java.util.Random;
public class RockPaperScissors
{
private String playerName; //used to set player's name
private int playChoice; //player's choice as a number
private int compChoice; //computer's choice as a number
private int playerNumber;
Random rand = new Random(); //allows useage of random methods
public RockPaperScissors()
{
//sets everything to null, prepare for incoming calculations
playerName = "";
}
public RockPaperScissors(String player)
{
playerName = player;
}
public void setPlayers(String player)
{
//good ol mutator method
playerName = player;
}
public String convertUserInput(String response)
{
//Convert R, P, S to integer using switch case
//If invalid input, set to -1
switch(response) {
case "R": playChoice = 0;
break;
case "P": playChoice = 1;
break;
case "S": playChoice = 2;
break;
default: playChoice = -1;
}
}
public boolean setPlayerChoice(String response)
{
//TODO set playChoice to convertUserInput
//return (playChoice != -1)
playChoice = convertUserInput(response);
return(playChoice != -1);
}
public int computerThink()
{
//Use Math.random from 0-2 inclusive
//return it all in one statement so
//return Math.random(whatever);
return rand.nextint(2);
}
public String determineWinner()
{
String winner="";
compChoice = computerThink();
switch(compChoice) {
case 0:
if(playChoice == 1){
winner = playerName;
} else if(playChoice == 2) {
winner = "Computer";
} else if(playChoice == 0) {
winner = "Tie";
}
case 1:
if(playChoice == 1) {
winner = "Tie";
} else if(playChoice == 2) {
winner = playerName;
} else if(playChoice == 0) {
winner = "Computer";
}
case 2:
if(playChoice == 1) {
winner = "Computer";
} else if(playChoice == 2) {
winner = "Tie";
} else if(playChoice == 0){
winner = playerName;
}
} //closes the switch
return winner;
}
}
This is my first major program, so I apologize for any glaring errors or incorrectly-interpreted concepts. I think my major issue lies in the return types, but I'm not positive.
Looking through your code, it is a bit of a mess, so I'll go through step by step.
game.setPlayers();
game.convertUserInput(response);
game.setPlayerChoice(response);
game.computerThink();
game.determineWinner();
You call ALL of these, yet some have return types and are called in previous functions already. For example, convertUserInput.
Your convertUserInput function sets the playChoice variable, declares it returns a String but actually returns nothing. This is called with your clump of functions above, but is then also called by setPlayerChoice, which replaces the playChoice set in the call with, well, nothing. Because nothing is returned you get a compile error.
computerThink returns an int, but you call it above without setting the returned value to anything, then determineWinner is called, which WOULD work had it not been for the above problems.
There is quite a bit wrong with your code. A few obvious ones: you have parameterized your setPlayers method of the RockPaperScissors class to accept a string, but when you invoke it, you dont provide any value, thats a compile time issue. In the RockPaperScissors class you have a method convertUserInput whose method signature says it will return a string, but there are no code paths which return a value in that method. I would do a few more simple tutorials to try to wrap your head around basic OOP concepts then come back to this once you understand basic stuff like, What is an Object? What is a method signature? and most importantly, read and interpret the compile time errors.
It's a little strange that you know your problem lies with the return types but don't know how to fix it. Are you just reading the error message but don't know what its actually saying?
The return type is declared in the first line of a method, the method declaration. The method is expected to return the return type or you will receive a compile-time error.
Some Examples
//these are method declarations
// the return type is before the name of the method
public void setPlayers(String player) {} //return type "void" - this method should not return anything
public String convertUserInput(String response) { // return type "String" - this method NEEDS to return a String
return "A String";
}
Matching method calls
//You need to match the return type with how you call the method
String myPlayers = setPlayers("player"); //WON'T COMPILE - setPlayers returns void, not String
setPlayers("player"); // this is okay, nothing is returned, return type void
String convertedInput = convertUserInput("response"); // this is okay, return type String, which is what convertedInput will be.
convertUserInput("response"); // this is also okay, even though it returns a String we don't have to assign it to a variable. Though in this example calling the method like this is pretty much useless.
int convertedInput = convertUserInput("response"); //WON'T COMPILE - convertUserInput returns String, not an int.

Java NullPointerException

I tried printStackTrace and I have coverted everything to static (I think)... however, lines 17 and line 38 are the problem... because of this error:
You picked up: Pickaxe
java.lang.NullPointerException
at item.addInv(item.java:38)
at item.main(item.java:17)
Description: Can be used to mine with.
Press any key to continue . . .
Line 17: anItem.addInv(1);
Line 38: arr.add("Dan");
And here is my code:
import java.io.*;
import java.util.*;
import javax.swing.*;
public class item
{
public static int attack, defense;
public static ArrayList<String> arr;
public static String name, desc, typeOf, attackAdd, defenseAdd, canSell, canEat,earnedCoins,canEquip;
String stats[];
public static void main(String args[])
{
item anItem = new item();
ArrayList<String> arr = new ArrayList<String>();
anItem.addInv(1);
}
public static void addInv(int e) {
String iname = getItem(1)[0];
String idesc = getItem(1)[1];
int itypeOf = Integer.parseInt(getItem(1)[2]);
int iattackAdd = Integer.parseInt(getItem(1)[3]);
int idefenseAdd = Integer.parseInt(getItem(1)[4]);
boolean icanSell = Boolean.parseBoolean(getItem(1)[5]);
boolean icanEat = Boolean.parseBoolean(getItem(1)[6]);
int iearnedCoins = Integer.parseInt(getItem(1)[7]);
attack = attack + iattackAdd;
defense = defense + idefenseAdd;
System.out.println("You picked up: " + iname);
try {
arr.add("Dan");
} catch(NullPointerException ex) {
ex.printStackTrace();
}
System.out.println("Description: " + idesc);
}
public static String[] getItem(int e) {
String[] stats = new String[7];
String name = "Null";
String desc = "None";
String typeOf = "0";
String attackAdd = "0";
String defenseAdd = "0";
String canSell = "true";
String canEat = "false";
String earnedCoins = "0";
if (e == 1) {
name = "Pickaxe";
desc = "Can be used to mine with.";
typeOf = "2";
attackAdd = "2";
earnedCoins = "5";
}
return new String[] { name, desc, typeOf, attackAdd, defenseAdd, canSell, canEat, earnedCoins};
}
}
As you can see, it's those lines and I don't know what to do... :\
When you call the add() method on arr, it's not been initialized yet, hence, the NullPointerException.
Since you'll probably use the ArrayList in other methods as well, you should have that initialized in the constructor; ie:
public item() {
arr = new ArrayList<String>();
}
Variable arr is not initialized.
Variable arr in main() is not the same arr in function addInv()
Just initialize it in addInv to fix it.
String canEat = "false"; Why are you converting to and from strings?
You seem to have muddled an item class an inventory class.
Perhaps an Enum would be better:
public enum InventoryItem
{
PICKAXE("Pickaxe", "Can be used to mine with", ItemType.Tool,
5, 2, 0)
EPIC_PICKAXE("Super mega awesome Pickaxe", "Can be used to mine with, but epically", ItemType.Tool,
1000000, 100, 0)
public static enum ItemType {
TOOL,
WEAPON
}
public final String name, description;
public final ItemType type;
public final boolean canSell, canEat, canEquip;
public final int earnedCoins, attackAdd, defenseAdd;
private InventoryItem(String name, String description, ItemType type
int earnedCoins, int attackAdd, int defenseAdd,
boolean canSell, boolean canEat, boolean canEquip)
{
this.name = name;
this.description = description;
this.type = type
this.canSell = canSell;
this.canEat = canEat;
this.canEquip = canEquip;
this.earnedCoins = earnedCoins;
}
private InventoryItem(String name, String description, ItemType type
int earnedCoins, int attackAdd, int defenseAdd)
{
this(name, description, type,
earnedCoins, attackAdd, defenseAdd,
true, false, true);
}
}
Then you can just have List<InventoryItem> inventory = new ArrayList<InventoryItem>() within your player's class, and directly interface with that.
A few tips (one that does directly solve the problem):
1) wherever possible declare variables as private, or at most protected. I personally never use the "default" which is package level access (anything in the same package can see it).
2) Only use public for immutable values. An immutable value is something that cannot be changed (all members are final is the best way to ensure that, or no method modifies any values after the object is constructed and the variables are all private).
3) whenever possible always declare variables to be final (class variables, instance variables, parameters, local variables).
The one tip that directly helps you here is #3. Since you never assigned a value to "arr" it is null. If you declared it as final the compiler would force you do actually assign it a value, if you do not the code won't compile.
Doing that little thing will save you hours of time as you start programming. In my case I did something similar, not exactly the same (really I violated #2 sort of in a round about way) and it cost me about a week. I have been programming in Java for over 15 years now... if I can waste a week because of something like this think of how much time you can waste :-)

Categories

Resources