So here is my Superhero class:
public class Superhero {
public int strength;
public int powerUp;
public int defaultStrength = 10;
public String name;
public Superhero(String name) {
this.strength = 10;
System.out.println("The Superheroes available are :" + name);
}
public Superhero(String name, int strength) {
if (strength >= 0) {
this.strength = strength;
System.out.println("The Superheroes available are :" + name);
} else {
System.out.println("Error. Strength cannot be < 0");
}
}
public void setStrength( int strength ) {
this.strength = strength;
}
public int getStrength() {
return strength;
}
public void powerUp(int powerUp) {
this.strength += powerUp;
}
}
Here is my Fight class the problem here is when I run it I get back that the winner result is null and I don't understand why it is doing that.
import java.io.*;
public class Fight {
public static void main (String args[]) {
Superhero gambit = new Superhero( "Gambit" );
Superhero groot = new Superhero( "Groot", 79);
System.out.println( "Gambit's strength is: " + gambit.strength);
System.out.println( "Groot's strength is: " + groot.strength);
System.out.println("The winner of the fight is: " + fight(gambit, groot));
}
static String fight(Superhero a, Superhero b)
{
if (a.strength > b.strength)
{
return a.name;
} else
{
return b.name;
}
}
}
Look at your constructor:
public Superhero(String name) {
this.strength = 10;
System.out.println("The Superheroes available are :" + name);
}
That sets the instance field strength, but doesn't do anything with the name instance field. Your other constructor is the same. You need to include:
this.name = name;
to copy the value from the parameter into the instance variable. Do this in both constructors. Otherwise you just end up with the default value for name, which is a null reference.
As an aside, I'd strongly recommend making your fields private and adding a getName() method to retrieve the name from else your fight method. I'd also throw an exception instead of just printing out an error message if the strength is below 0, and also I'd make the constructor which doesn't take a strength parameter just chain to the one that does:
public Superhero(String name) {
this(name, 10);
}
public Superhero(String name, int strength) {
if (strength < 0) {
throw new IllegalArgumentException("strength cannot be negative");
}
this.strength = strength;
this.name = name;
System.out.println("The Superheroes available are :" + name);
}
(The message displayed by the constructor is a bit odd, given that it's only listing a single name, but that's a different matter.)
The problem is in your constructors:
public Superhero(String name) {
this.strength = 10;
System.out.println("The Superheroes available are :" + name);
}
public Superhero(String name, int strength) {
if (strength >= 0) {
this.strength = strength;
System.out.println("The Superheroes available are :" + name);
} else {
System.out.println("Error. Strength cannot be < 0");
}
}
Your constructors have an argument of a String name, but you never set the instance variable to a value. The default value of an uninitialized variable that contains an object is null.
You never set the name in any of the constructors of Superhero. To fix the first constructor, for example:
public Superhero(String name) {
this.name = name;
this.strength = 10;
System.out.println("The Superheroes available are :" + name);
}
You are never assigning the "incoming" name to the attribute field "name" of your class. So the later one stays null.
Btw: you really want to read those exception traces carefully. They provide all the information that you need to have in order to figure whats going on.
Final note: consider using the keyword final for the attributes of your class. That way you would have not run into this problem; as the compiler would have told you that the field "name" isn't initialized in your code.
Make a getter method that returns the String name in your superhero class, then call that method within your Fight class. I would also suggest changing your global variables in your superhero class from public to private, so they are only accessible within that class.
EDIT: As stated in another answer, your constructor that takes name as an argument is never assigned to a variable.
You are not setting the values of name variable in the constructor, use this
public Superhero(String name) {
this.strength = 10;
this.name = name;
System.out.println("The Superheroes available are :" + name);
}
public Superhero(String name, int strength) {
this.name = name;
if (strength >= 0) {
this.strength = strength;
System.out.println("The Superheroes available are :" + name);
} else {
System.out.println("Error. Strength cannot be < 0");
}
}
Related
I am learning JAVA OOP, I have to compare the age between 2 objects:
In java Procedural, I will have done:
public static int calculateDifferenceAge(int agePlayer1, int agePlayer2){
int differenceAge = agePlayer1 - agePlayer2;
if(differenceAge < 0){
differenceAge = -differenceAge;
}
return differenceAge;
}
Then
public static void displayDifferenceAge(String namePlayer1, String namePlayer2, int agePlayer1, int agePlayer2){
System.out.println("Age difference between " + namePlayer1 + " and " + namePlayer2 + " is of" + calculateDifferenceAge(agePlayer1, agePlayer2) + " year(s).");
}
}
I don't understand how to create my calculateDifferenceAge() method in OOP ?
In my main file I have this:
List<Player> players = new ArrayList <Player>();
players.add(new Player("Eric", 31, true));
players.add(new Player("Juliette", 27, false));
I am stuck into my 2 methods:
How to subtract the age of 2 objects?
public static int calculateAgeDifference(List <Player> players){
Player differenceAge = (players.get(0) - players.get(1));
return differenceAge;
}
public static void displayCalculateAgeDifference(List <Player> players){
System.out.println(calculateAgeDifference().age);
}
Class Player
public class Player {
public String name;
public int age;
public boolean sex;
public Player(String name, int age, boolean sex){
this.name = name;
this.age = age;
this.sex = sex;
}
you're only missing a little step in your code. The steps to extract the ages of the list should be:
1.- Extract the object from the list
2.- Extract the age of that object (or player, in this case)
3.- Substract the ages
There's some ways to do it, but I would do it this way:
public static int calculateAgeDifference(List<Player> players) {
int age1= players.get(0).age;
int age2= players.get(1).age;
int differenceAge = age1 - age2;
if(differenceAge < 0){
differenceAge = -differenceAge;
}
return differenceAge;
}
I hope that helps. What i've done there is extract the objects player from the list: players.get(0) extracts the first object inside the list, which is a Player. Now that I have a player and it has an age variable i have to extract it with player.age. I collapsed those steps, if you have any questions I can explain you further
Display method:
public static int displayCalculateAgeDifference (List<Player> players){
String name1= players.get(0).name;
String name2= players.get(1).name;
//as you know this method return the difference in a number form
int difference= calculateAgeDifference(players);
System.out.println("Age difference between " + name1 + " and " + name2 + " is of" + difference + " year(s).");
}
Let's start with a class Player. Let's give it a name and an age, and a calculateAgeDifference method. It should look something like,
public class Player {
private int age;
private String name;
public Player(String name, int age) {
this.name = name;
this.age = age;
}
public int calculateAgeDifference(Player player2) {
return Math.abs(this.age - player2.age);
}
}
Then you can call it like
Player a = new Player("Eric", 40);
Player b = new Player("Sally", 51);
System.out.println(a.calculateAgeDifference(b));
You must have a similar Player class. Yours appears to also have a boolean field. It isn't clear why. So I can't speak to that.
Why did your method interface change from two parameters to a list? You can still pass two instances of the object. You can still return the integer age value from the method, no need to create a Frankenstein's Player instance only to hold the age.
I am assuming your Player class has a method getAge() to extract the age value which was passed in in the constructor:
public static int calcAgeDiff(final Player player1, final Player player2) {
int age1 = player1.getAge();
int age2 = player2.getAge();
return Math.abs(age2 - age1);
}
Alternatively, you can add an instance method to your Player class itself to calculate the age difference to a different player:
public class Player {
// fields
// constructor
// getters
public int ageDiffTo(final Player otherPlayer) {
return Math.abs(this.age - otherPlayer.age); // <- a class can always access its private fields, even of other instances
}
}
then call as player1.ageDiffTo(player2)
Here is my code. I think the error is coming from the fight() method. It is supposed to use whatever the attack is given EX. "#" and print that for the number of levels like this "attack=#, level=5" and it would print "#####"
public class Dragon
{
private String attack;
private int level;
public Dragon (int level, String attack)
{
this.level = level;
this.attack = attack;
}
public String getAttack()
{
return attack;
}
public int getLevel()
{
return level;
}
// Put other methods here
private void fight(int level, String attack)
{
if (level < 0)
{
System.out.print(attack);
}
}
// String representation of the object
public String toString()
{
return "Dragon is at level " + level + " and attacks with " + attack;
}
}
Grader.java: Line 57: Method is expecting type int, String and type "no arguments" was given.
You are saying you don't have access to the Grader class...
Maybe the fight method doesn't need any arguments?
Looks like the constructor is already setting those variables.
Remove the arguments from your flight method and check for this.level < 0 instead?
I have class PERSON and BOUNCYHOUSE which are combined in main method class PARTNERLAB.
I have to add people to the bouncyhouse based on weight limit and if one bouncy house is full, move on to the next.
I get an error that looks like this:
Exception in thread "main" java.lang.Error: Unresolved compilation problem:
The constructor BouncyHouse() is undefined
at PartnerLab1.main(PartnerLab1.java:17)
How do I define BouncyHouse?
Here's my code:
PARTNER:
public class Person { //encapsulated class the has name and weight
private String name;
private int personWeight;
public Person(String name, int personWeight){ //two argument constructor thta takes in the name and weight and sets both attributes accordingly
this.name= name;
this.personWeight= personWeight;
}
public String getName() //get name
{
return this.name;
}
public int getWeight() //get weight
{
return this.personWeight;
}
public String getInfo(){ //return all info
return "Name: " + this.name +
"\n Person's weight: "+ this.personWeight;
}
BOUNCYHOUSE
import java.util.*;
public class BouncyHouse { //encapsulated class with weight limit and total current weight with all occupants in the bouncy house
private int weightLimit;
private int totalCurrentWeight;
private ArrayList <Person> occupants;
public BouncyHouse(int weightLimit, int totalCurrentWeight, ArrayList<Person> occupants){ //no arguments construction that sets the variable to a default value of 0
this.weightLimit= 0;
this.totalCurrentWeight= 0;
this.occupants = new ArrayList<>();
}
public void setWeightLimit(int weightLimit) //sets weight limit
{
this.weightLimit = weightLimit;
}
public void setTotalCurrentWeight(int totalCurrentWeigth) //sets total current wieght
{
this.totalCurrentWeight = totalCurrentWeigth;
}
public String getInfo() // return all the information about the bouncy house
{
StringBuilder personInfo = new StringBuilder();
for(Person person: occupants)
{
personInfo.append(person.getInfo()+",\n\t");
}
return "BouncyHouse: " +
"\nweightLimit=" + this.weightLimit +
"\ntotalWeight=" + this.totalCurrentWeight +
"\noccupants= " + personInfo.toString(); //can't do it in one sitting !
}
//NEXT: Add a person to the bouncy house
public boolean addPerson(Person person)
{
// check if weight exceeds the limit
if((person.getWeight()+totalCurrentWeight) <= weightLimit)
{
// add person to occupants list
this.occupants.add(person);
// update current total weigh
this.totalCurrentWeight += person.getWeight();
return true;
}
// else, return false
return false;
}
public Person[] addPerson(Person[] persons)
{
Person maxWeightPerson = null;
int maxWeight = 0;
for(int i =0; i < persons.length; i++)
{
// check if weight exceeds the limit
if (!addPerson(persons[i]))
{
if(persons[i].getWeight() < maxWeight)
{
// remove maxWeightPerson from house and add the current person
occupants.remove(maxWeightPerson);
totalCurrentWeight -= maxWeightPerson.getWeight();
// add person to occupants list
this.occupants.add(persons[i]);
maxWeight = 0;
// find next max weight guy
for (Person person : occupants)
{
if (person.getWeight() > maxWeight)
{
maxWeight = person.getWeight();
maxWeightPerson = person;
}
}
}
}
else
{
if(maxWeight < persons[i].getWeight())
{
maxWeight = persons[i].getWeight();
maxWeightPerson = persons[i];
}
}
}
return occupants.toArray(new Person[occupants.size()]);
}
}
PARTNERLAB
import java.util.*;
import java.util.Scanner;
public class PartnerLab1
{
public static void main(String[] args)
{
String choice, name;
int weight;
Scanner in = new Scanner(System.in);
BouncyHouse[] bouncyHouses = new BouncyHouse[2];
for (int i = 0; i < 2; i++)
{
bouncyHouses[i] = new BouncyHouse();
// set weight limits for bouncyHouse
bouncyHouses[i].setWeightLimit(250);
// add persons to houses
do
{
System.out.print("Add person to House " + (i + 1) + " (y/q): ");
choice = in.nextLine();
if (choice.equalsIgnoreCase("y"))
{
System.out.print("Enter name: ");
name = in.nextLine();
System.out.print("Enter weight: ");
weight = Integer.parseInt(in.nextLine());
if (bouncyHouses[i].addPerson(new Person(name, weight)))
{
System.out.println("Person added");
} else
{
System.out.println("Person can't be added. Exceeds weight limit.");
}
}
} while (!choice.equalsIgnoreCase("q"));
}
// display people in houses
for (int i = 0; i < 2; i++)
{
System.out.println("People in House " + i + 1);
System.out.println(bouncyHouses[i].getInfo());
}
}
}
You have defined a parametrized constructor for your BouncyHouse class so you can't call a no-argument constructor without explicitly defining it in your class.
As per the code you have written in main class, You don't required parametrized constructor into BouncyHouse class. You can remove it or in case if you required some where else then add no-argument constructor in BouncyHouse class.
I have three class Homework that has my main(...), GradeArray, which has my methods, and StudentGrade, which has my constructor.
Currently , which is clearly wrong, I have in Homework:
GradeArray grades = new GradeArray();`
In GradeArray at the top I have StudentGrade[] ArrayGrades = new StudentGrade[size]; however this method did not give me both the contructor and the methods. I know I don't need three classes for this but my professor wants three class. How do I declare an array that has attributes from two classes so that I can get the methods from GradeArray and the constructor from StudentGrade?
Thank you for you time and help.
Here is all of my code
package homework1;
public class Homework1
{
public static int pubSize;
public static String pubCourseID;
public static void makeVarsPub(int maxSize, String courseID) //this is to makes the varibles public
{
pubSize = maxSize;
pubCourseID = courseID;
}
public int giveSize()
{
return pubSize;
}
public static void main(String[] args)
{
int maxSize = 100;
String courseID = "CS116";
//this is to makes the varibles public
makeVarsPub(maxSize, courseID);
StudentGrade grades = new StudentGrade();
grades.insert("Evans", 78, courseID);
grades.insert("Smith", 77, courseID);
grades.insert("Yee", 83, courseID);
grades.insert("Adams", 63, courseID);
grades.insert("Hashimoto", 91, courseID);
grades.insert("Stimson", 89, courseID);
grades.insert("Velasquez", 72, courseID);
grades.insert("Lamarque", 74, courseID);
grades.insert("Vang", 52, courseID);
grades.insert("Creswell", 88, courseID);
// print grade summary: course ID, average, how many A, B, C, D and Fs
System.out.println(grades);
String searchKey = "Stimson"; // search for item
String found = grades.find(searchKey);
if (found != null) {
System.out.print("Found ");
System.out.print(found);
}
else
System.out.println("Can't find " + searchKey);
// Find average and standard deviation
System.out.println("Grade Average: " + grades.avg());
System.out.println("Standard dev; " + grades.std());
// Show student grades sorted by name and sorted by grade
grades.reportGrades(); // sorted by name
grades.reportGradesSorted(); // sorted by grade
System.out.println("Deleting Smith, Yee, and Creswell");
grades.delete("Smith"); // delete 3 items
grades.delete("Yee");
grades.delete("Creswell");
System.out.println(grades); // display the course summary again
}//end of Main
}//end of homework1
package homework1;
class GradeArray
{
int nElems = 0; //keeping track of the number of entires in the array.
Homework1 homework1InfoCall = new Homework1(); //this is so I can get the information I need.
int size = homework1InfoCall.giveSize();
StudentGrade[] ArrayGrades = new StudentGrade[size];
public String ToString(String name, int score, String courseID)
{
String res = "Name: " + name + "\n";
res += "Score: " + score + "\n";
res += "CourseID " + courseID + "\n";
return res;
}
public String getName(int num) //returns name based on array location.
{
return ArrayGrades[num].name;
}
public double getScore(int num) //returns score based on array location.
{
return ArrayGrades[num].score;
}
public void insert(String name, double score, String courseID) //part of the insert method is going to be
//taken from lab one and modified to fit the need.
{
if(nElems == size){
System.out.println("Array is full");
System.out.println("Please delete an Item before trying to add more");
System.out.println("");
}
else{
ArrayGrades[nElems].name = name;
ArrayGrades[nElems].score = score;
ArrayGrades[nElems].courseID = courseID;
nElems++; // increment the number of elements
};
}
public void delete(String name) //code partly taken from lab1
{
int j;
for(j=0; j<nElems; j++) // look for it
if( name == ArrayGrades[j].name)
break;
if(j>nElems) // can't find it
{
System.out.println("Item not found");
}
else // found it
{
for(int k=j; k<nElems; k++) // move higher ones down
{
boolean go = true;
if ((k+2)>size)
go = false;
if(go)
ArrayGrades[k] = ArrayGrades[k+1];
}
nElems--; // decrement size
System.out.println("success");
}
}
public String find (String name){ //code partly taken from lab1
int j;
for(j=0; j<nElems; j++) // for each element,
if(ArrayGrades[j].name == name) // found item?
break; // exit loop before end
if(j == nElems) // gone to end?
return null; // yes, can't find it
else
return ArrayGrades[j].toString();
}
public double avg() //this is to get the average
{
double total = 0;
for(int j=0; j<nElems; j++)
total += ArrayGrades[j].score;
total /= nElems;
return total;
}
public double std() //this is to get the standard deviation. Information on Standard deviation derived from
//https://stackoverflow.com/questions/18390548/how-to-calculate-standard-deviation-using-java
{
double mean = 0; //this is to hold the mean
double newSum = 0;
for(int j=0; j < ArrayGrades.length; j++) //this is to get the mean.
mean =+ ArrayGrades[j].score;
for(int i=0; i < ArrayGrades.length; i++) //this is to get the new sum.
newSum =+ (ArrayGrades[i].score - mean);
mean = newSum/ArrayGrades.length; //this is to get the final answer for the mean.
return mean;
}
public StudentGrade[] reportGrades() //this is grade sorted by name
{
int in,out;
char compair; //this is for compairsons.
StudentGrade temp; //this is to hold the orginal variable.
//for the first letter cycle
for(out=1; out<ArrayGrades.length; out++)
{
temp = ArrayGrades[out];
compair= ArrayGrades[out].name.charAt(0);
in=out;
while(in>0 && ArrayGrades[in-1].name.charAt(0) > compair)
{
ArrayGrades[in] = ArrayGrades[in-1];
in--;
}
ArrayGrades[in]=temp;
}
//this is for the second run.
for(out=1; out<ArrayGrades.length; out++)
{
temp = ArrayGrades[out];
compair= ArrayGrades[out].name.charAt(1);
in=out;
while(in>0 && ArrayGrades[in-1].name.charAt(1) > compair)
{
ArrayGrades[in] = ArrayGrades[in-1];
in--;
}
ArrayGrades[in]=temp;
}
return ArrayGrades;
}
public StudentGrade[] reportGradesSorted() //this is grades sorted by grades.
//this is grabbed from lab2 and repurposed.
{
int in,out;
double temp;
for(out=1; out<ArrayGrades.length; out++)
{
temp=ArrayGrades[out].score;
in=out;
while(in>0 && ArrayGrades[in-1].score>=temp)
{
ArrayGrades[in]= ArrayGrades[in-1];
in--;
}
ArrayGrades[in].score=temp;
}
return ArrayGrades;
} //end of GradeArray
package homework1;
public class StudentGrade extends GradeArray
{
public String name;
double score;
public String courseID;
public void StudentGrade (String name, double score, String courseID) //this is the constructor
{
this.name = name;
this.score = score;
this.courseID = courseID;
}
}//end of StudentGrade class.
First, I feel #Alexandr has the best answer. Talk with your professor.
Your question doesn't make it quite clear what you need. However, it sounds like basic understanding of inheritance and class construction would get you going on the right path. Each of the 3 classes will have a constructor that is unique to that type. Each of the 3 classes will have methods and data (members) unique to those types.
Below is just a quick example of what I threw together. I have strong concerns that my answer is actually what your professor is looking for however--it is not an object model I would suggest--just an example.
public class Homework {
private String student;
public Homework(String name) {
student = name;
}
public String getStudent() {
return student;
}
}
public class StudentGrade extends Homework {
private String grade;
public StudentGrade(String grade, String name) {
super(name);
this.grade = grade;
}
public String getGrade() {
return grade;
}
}
public class HomeworkGrades {
public List<StudentGrade> getGrades() {
// this method isnt implemented but should
// be finished to return array of grades
}
}
Take a look and see if that helps you understand something about inheritance and class construction.
Hopefully you can infer a bit about inheritence (StudentGrade inherits -- in java extends -- from HomeWork) and class construction.
Thnx
Matt
I change the array creation in Homework1 to be StudentGrade grades = new StudentGrade(); and I added extends GradeArray to the StudentGrade class. it is now public class StudentGrade extends GradeArray.
Write a class for a video game character. The character should have a
name, a type (scout, soldier, medic, etc.) and current health.
Therefore it needs three attributes:
String name, String type, int health
This class should have the following methods:
GameCharacter( String newName, String newType, newCurHealth )
Constructor that takes three inputs.
changeHealth( int change ) A method that changes the health of the
character. The character’s health will change by change amount, so it
will go down if change is negative, and up if it’s positive. If the
health goes below 0, changeHealth should return the String "Your
character is dead".
Here is my code so far. Is there anything I can do to make it better? & a way to return a string in my second method?
public class GameCharacter {
private String name;
private String type;
private int health;
public GameCharacter(String newName, String newType, int newCurHealth){
name = newName;
type = newType;
health = newCurHealth;
}
public int changeHealth (int change){
if (change < 0){
return health - change;
} else if (change > 0){
return health + change;
} else if (health < 1){
// string that character is dead
}
}
public static void main(String[] args){
GameCharacter Mario = new GameCharacter ("Mario", "Hero", 100);
GameCharacter Luigi = new GameCharacter ("Luigi", "Sidekick", 100);
GameCharacter Bowser = new GameCharacter ("Bowser", "Villian", 100);
}
}
You cannot return either an int or a String. You have to pick one type and you should re-think your design, if you want to output a message. E.g. just check the return value of changeHealth() after calling the method.
Or you could define a custom exception (or use an existing one). Just to get you started:
public int changeHealth(int change) {
int result = health;
if (health < 1) {
throw new IllegalStateException("Cannot change health, character is dead already.");
}
// Calculate health change (if any)
health += change;
// Return new health
return health;
}
Humbly, I think what you want isn't a good way.
Your methods should be so semantics as possible.
A better approach would be return a negative int and your class GameCharacter can have a method isDead or isAlive that will give you this state.
public class GameCharacter {
private String name;
private String type;
private int health;
public boolean isAlive(){ return health>0; }
public boolean isDead(){ !isAlive(); }
}
It would make more sense to always return the same thing, regardless of whether your character is dead or not.
For example:
public class GameCharacter {
private String name;
private String type;
private int health;
public GameCharacter(String newName, String newType, int newCurHealth){
name = newName;
type = newType;
health = newCurHealth;
}
public String changeHealth (int change){
// Adding positive number will increase health.
// Adding negative number will decrease health.
health += change;
if (health > 0){
return "Your character now has " + health + " health.";
} else {
return "Your character is dead.";
}
}
public static void main(String[] args){
GameCharacter Mario = new GameCharacter ("Mario", "Hero", 100);
GameCharacter Luigi = new GameCharacter ("Luigi", "Sidekick", 100);
GameCharacter Bowser = new GameCharacter ("Bowser", "Villain", 100);
}
}
I think you misunderstood the assignment. The method is not supposed to return the new health, but to change the health of that character, i.e. just update this.health "in place" and change the returned type to String.
Also, no need to check whether change is positive or negative; just add it to health!
public String changeHealth (int change) {
this.health += change
if (health < 1) {
return "Your character is dead";
} else {
return null; // or whatever
}
}
Edit: While other answers propose some good alternatives and additions to the Character API, given that this looks like an assignment, I think you should stick to the description of the method, i.e. change the health, and return a string.
If you declare a method to return an int you cannot make it return a String as a "special result".
There are several ways to solve your problem. You can add a method like checkAlive() which returns true if the current health is greater than 0 and false otherwise, or make the caller check the returned value (which should be the health after the change) and print the string if that value is smaller than or equal to 0.
Also I think you have some bugs in your concept: first, your method doesn't change the health value inside your class; second, the code inside the last if, where you want to return the string, will be executed only when 0 is passed as parameter to the method. That's probably not what you want. To follow my suggestion edit the method like this:
public int changeHealth(int change) {
health += change;
return health;
}
Few things,
first, dont worry, your character will never die
if (change < 0){
return health - change;
} else if (change > 0){
return health + change;
}
you are adding positive change value to health and substracting negative value from it. Mathematics 101 x - (-y) == x+y
second, your character might dead, but i dont think any action related to him being dead should be happened inside `GameCharacter' class. i suggest you to return true/false value which indicate is character still alive. or create enum. if you go that way, you culd have multiple states (alive, almost_dead, dead)
I would rethink the design, particularly around the changeHealth method. However, if you really want to have a combined return type of an int and an optional string, you could create a new class, say, HealthStatus, that actually contains an Optional<String>:
public class HealthStatus {
public final int health;
public final Optional<String> message;
public HealthStatus(int health, String message) {
this.health = health;
this.message = Optional.of(message);
}
public HealthStatus(int health) {
this.health = health;
this.message = Optional.empty();
}
public int getHealth() {
return health;
}
public Optional<String> getMessage() {
return message;
}
}
Then, in your changeHealth method, you can optionally return a message:
public HealthStatus changeHealth(int change) {
health += change;
if (health < 1) {
return new HealthStatus(health, "Your character is dead");
} else {
return new HealthStatus(health);
}
}
And at the point where you call it, you can print the message, if there is one (or do whatever else is appropriate with it):
// take 7 points of damage:
HealthStatus status = changeHealth(-7);
hitPoints = status.getHealth();
// print the message, if there is one
status.getMessage().ifPresent(System.out::println);
public String changeHealth(int change) {
health += change;
return health < 0 ? "Your character is dead" : null;
}