In my project, in one of the classes (Adventure) I created an ArrayList and worked on it (add elements, delete others...)
This ArrayList is then passed as a parameter when creating an instance of another class (Player) inside Adventure.
Therefore I of course needed to created an ArrayList in Player and constructor, to catch the ArrayList sent from Adventure.
I'm not really sure, that all what i've done is correct. I'm getting the warning in Player Class:
This private field "createdObjects" is never assigned
Should i change smtg, or just ignore the warning ?
Here's the code :
public class Player {
private ArrayList<Objects> createdObjects;
public Player(ArrayList<Objects> createdObjects) {
//Originally i have many other elements in this constructor
// but i let only what concerns this arrayList
}
public ArrayList<Objects> getCreatedObjects() {
return createdObjects;
}
}
public class Adventure {
private ArrayList<Objects> createdObjects = new ArrayList<>();
public ArrayList<Objects> getCreatedObjects() {
return createdObjects;
}
// ...methods that will add/modify... the arraylist
public Player letsStart(){
Player player = new Player(createdObjects);
return player;
}
}
Related
I am trying to add an element to an ArrayList using user input. The problem is when I try add something and ask to list it, it doesn't show it in the list.
I thought it was a problem with the read method, but I am not sure if there is anything wrong with it. The other thing was the fact that the method for adding an element wasn't in a loop, I tried using a loop but it still wasn't working.
There is a movie class with a constructor that has the parameters for title, year, genre, price and a toString method.
Expected result: After adding a movie, it should list the movie added.
Actual result: The add method asks for input but when I use the list method it doesn't list what I added.
Here is the full Kiosk and Catalogue class for more context.
new Catalogue().addMovie();
You are creating a new Catalogue each time you want to add a Movie, and you are never referencing it.
Instead, add all your movies to the same Catalogue:
private void addMovie(Catalogue c) {
c.addMovie();
}
private void listMovie(Catalogue c) {
c.listMovie();
}
that's because of the 'new' keyword. you need to use singleton 'Catalogue' object here.
class Kiosk {
private static Catalogue catalogue;
public Catalogue getCatalogue() {
if(Objects.isNull(catalogue)){
catalogue = new Catalogue();
}
return catalogue; //will return singleton catalogue object
}
private void addMovie() {
getCatalogue().addMovie();
}
private void listMovie() {
getCatalogue().listMovie();
}
}
In Kiosk you must keep an instance of your catalogue.
I don't know where you plan to create the Catalogue instance so added 2 constructors:
public class Kiosk {
private Catalogue cat;
public Kiosk() {
this(new Catalogue());
}
public Kiosk(Catalogue catalogue) {
this.cat=catalogue;
}
private void addMovie() {
cat.addMovie();
}
private void listMovie() {
cat.listMovie();
}
}
Basically, I'm making a yahtzee game in MVC. It works fine, but When I try to save a session of a game, It doesn't save the game object containing and arraylist of players. This without stopping the execution which would certainly clear the arraylist of games.
Basically, an instance of game has the following fields:
public String name;
public int numberOfPlayers;
public ArrayList<Player> players = new ArrayList<>();
int playerListIndex;
ArrayList<Boolean> checkable;
StandardRules yahtzeeRule = new StandardRules();
public int rounds;
public String date;
The Arraylist of players contains instances of the object Player which has it's own fields and gettters/setters.
I've managed to track the problem to not saving when I call the method:
public void saveGame(Game thisGame) {
DB.saveGame(thisGame);
}
Which in turn calls the class:
public class DB {
private static ArrayList<Game> savedGames = new ArrayList<>();
/**
* Saves the passed member into the database.
* #param game, the member to be saved.
*/
public static void saveGame(Game game) {
for (Game g : savedGames) {
if (g.name.equals(game.name)) {
savedGames.remove(g);
savedGames.add(game);
}
else {
savedGames.add(game);
}
}
}
The saveGame method basically checks the Arraylist of saved games if the name already exists, and if it does it removes the old one and adds the new one. If there is no game by that name, It just adds the game to the list. (I might Implement a MYSQL DB later, but for the sake of making sure the program works first, I'd like to use the arraylist to test things)
I'm under the impression that I need to have a static reference to the DB to ensure that I'm trying to access the same DB all the time and not mix up instances of a DB.
What am I doing wrong here?
Try to follow the logic. You are looping over the array to save the game. If the array is empty, what would you expect to happen? If the Array would have six elements what would you expect to be in this list? In addition, you would most likely run into a ConcurentModificationException if this loop would ever get executed with a name that is already in the List. You might want to loop over the List and store a duplicate into a variable. But donĀ“t do the saving and removing in the loop.
So in the end your problem is that you are looping over the empty list to save the Game, which in fact wont work because your List is empty and you will never reach the part where you add something to your List.
You are most likely out for such a solution to store the game in your List.
public static void saveGame(Game game) {
Game dupGame = null;
for (Game g : savedGames) {
if (g.name.equals(game.name)) {
dupGame = g;
}
}
if (dupGame != null) {
savedGames.remove(dupGame );
}
savedGames.add(game);
}
EDIT:
You could also make use of a Map, which would make finding duplicates and so on a bit faster and more easy.
public class DB {
private static Map<String,Game> savedGames = new HashMap<>();
/**
* Saves the passed member into the database.
*
* #param game
* , the member to be saved.
*/
public static void saveGame(Game game) {
savedGames.put(game.name.toLowerCase(), game);
}
}
You want to have these savedGames in memory right. There is no problem having them as static. The only problem you have is you are iterating through the savedGames list and also modifying it adding and removing the few games. This is wrong. It might give you concurrent update exception.
public class DB {
private static ArrayList<Game> savedGames = new ArrayList<>();
/**
* Saves the passed member into the database.
* #param game, the member to be saved.
*/
public static void saveGame(Game game) {
boolean exists=false;
boolean removalObject=null;
for (Game g : savedGames) {
if (g.name.equals(game.name)) {
exists=true;
removalObject=g;
}
}
savedGames.add(removalObject);
savedGames.add(game);
}
}
The first problem is , trying to add a game to the empty ArrayList will fail because the adding operation is done within the loop which will never run if the savedGames is empty. Also the remove(Object obj) method works as expected if the equals(Object obj) of the Object class is properly override in the Game class.
Try this below...
Override the equal() method in the Game Class:
#Override
public boolean equals(Object obj) {
if(obj != null && obj instanceof Game){
Game gameObj = (Game)obj;
if(this.name.equals(gameObj.name)){
return true;
}
}
return false;
}
Do the saveGame() method as follows:
public static void saveGame(Game g){
if(games.contains(g)){
games.remove(g);
}
// Add the game after removing the existing
// or if never existed
games.add(g);
}
You'r method can return a exception becuas you read from the ArrayList and add content to it in loop.
Try this. :)
for(Game g : savedGames) {
if(g.name.equals(game.name)) {
savedGames.remove(g);
savedGames.add(0, game);
} else {
savedGames.add(0, game);
}
}
In an android game i am writing, i have my code organized as follows:
I have a World object, that contains many Area objects. Inside each Area object are Place objects. These are arranged in multidimensional arrays that make it easy for the player to move around in.
I also have Player and Inventory objects that i use as constructors for my World object so that ican access the Player/Inventory and make changes to it as necessary (ex: add "item" to inventory; player -10 health).
public class World
Player player;
Inventory inventory;
public World(Player player, Inventory inventory){
this.player=player;
this.inventory=inventory;
}
public Player returnPlayer(){
return player;
}
public Inventory returnInventory(){
return inventory;
}
to create an Area: i use a World object as a constructor
public class StartingArea extends Area
Player player;
Inventory inventory;
World world;
public StartingArea(World world){
this.world=world;
player=world.returnPlayer;
inventory=world.returnInventory;
}
I also have returnPlayer and returnInventory methods within my Area objects.
And when i create my Place objects within my Area objects, i use an Area as a constructor":
House house = new house(this);
public class House extends Place
Player player;
Inventory inventory;
public House(Area area){
inventory=area.returnInventory;
player=area.returnPlayer
}
however, by the time i pass down these player and inventory objects that i created back when i created my world object, something gets messed up. I am unable to access the inventory object, and my app force closes. I tried making my world instance static:
Player player = new Player();
Inventory inventory = new Inventory();
public static World world;
world = new world(player,inventory);
and when it is static, i can successfully alter the inventory object
by referring to:
MainActivity.world.returnInventory().add(item) //add(Item item) is a method in inventory
So, something that I do not quite understand is going on here. Perhaps it is a problem with inheritance (extends)? Or maybe the way i am passing down objects is illegal or improper? I have just started to learn java, so this could be a simple fix or conceptual thing that I missing.
I would like to avoid creating a static instance of my World object because i am not sure how this will affect supporting multiple save files in my game.
If you have just one player and one inventory you could use singletons to be able to get access to them anywhere. Something like this.
public class Player {
private static Player sPlayer;
// variables etc
public static Player getInstance() {
if (sPlayer == null) {
sPlayer = new Player();
}
return sPlayer;
}
// methods etc
}
public class Inventory {
private static Inventory sInventory;
// variables etc
public static Inventory getInstance() {
if (sInventory == null) {
sInventory = new Inventory();
}
return sInventory;
}
// methods etc
}
Then in other activities and classes you could get reference easily without passing them as parameters
public class StartingArea extends Area {
Player player;
Inventory inventory;
World world;
public StartingArea(World world){
this.world=world;
player=Player.getInstance();
inventory=Inventory.getInstance();
}
}
For my AP CompSci class, we're making a "Contacts" program to simulate using a virtual phonebook. The main class, Contacts is as follows.
public class Contacts extends ArrayList<Contact>
{
private ArrayList<Contact> contacts = new ArrayList<Contact>();
#Override
public boolean add(Contact c)
{
contacts.add(c);
Collections.sort(contacts);
return true;
}
public ArrayList<Contact> search(String name)
{
ArrayList<Contact> temp = new ArrayList<Contact>();
for(int i = 0; i<=contacts.size(); i++)
{
if(contacts.get(i).getName().equals(name))
{
temp.add(new Contact(name));
}
}
return temp;
}
}
As you can see, it extends ArrayList<Contact>. Contact is a simple object, composed of a String name and a 7-integer int num. The problem lies in the class ContactsFactory, where I loop through a text file to create a huge ArrayList of names.
public class ContactsFactory {
public static Contacts getContacts() throws FileNotFoundException {
String path = System.getProperty("user.dir");
Scanner s = new Scanner(new File(path + "\\src\\names.txt"));
Contacts contacts = new Contacts();
do {
contacts.add(new Contact(s.next()));
} while (s.hasNext());
s.close();
//print size to see anything added. It returns 0.
System.out.println(contacts.size());
return contacts;
}
}
However, when I implement the add() method for each name, not only does it seem not to add anything, but it returns no error. Even more interesting is that, as I found out when I put a print statement after every iteration, s.next() is no empty String. But the String(which experiences no issues being transferred from names.txt) is not added to contacts, and as a result, the ArrayList ends up empty with a size() of 0.
I think the error might be in the overridden Contacts.add() method, but I haven't been able to figure anything out. Can someone help me out? Thanks in advance.
I'm wondering why you extend ArrayList and additionally keep another copy of an ArrayList around. Besides the overwritten add (and size from azurefrog's answer), an ArrayList as well as the List interface offers a bunch of other methods - instead of overwriting all of them and delegating to the internal list, I would just rely on those methods and add the functionality I need:
public class Contacts extends ArrayList<Contact>
{
#Override
public boolean add(Contact c)
{
boolean result = super.add(c);
Collections.sort(this);
return result;
}
public ArrayList<Contact> search(String name)
{
// ...
}
}
By that you have a full-blown ArrayList and can extend it with what you need.
The other option is, to just kick out extends and just go for your own implementation of Contacts, utilizing the internal List as storage and not exposing it directly.
I think there is something wrong with your design.
I don't think you should extend ArrayList.
Because when you do it, your class IS an ArrayList, and also, you created an ArrayList object inside your class.
The thing is, when you called size, original ArrayList's size is being returned. Since you added the element to your ArrayList, the original is still empty.
You should use either delegation or inheritance, in this case you are mixing it both up.
Either implement java.util.List<Contact> (instead of extending ArrayList) and delegate every method call to the delegate (the class variable contacts)
OR
Remove the class variable contacts and use super.add() in your add method (instead of contacts.add()) and this instead of every other reference on contacts
I'm not sure how you read your file, but I seem to do just fine. In order to access the size of the contacts object in your factory, you need to call the 'size' method on the internal ArrayList instance variable, as opposed to calling on the 'contacts' object itself. In order to properly apply the 'size' method, it maybe that you need to override this method ('size') too.
Other than that, adding and retrieval seems fine. Check out the console output as well!
public class Contacts extends ArrayList<Contact>
{
private List<Contact> contacts = new ArrayList<Contact>();
#Override
public boolean add(Contact c)
{
contacts.add(c);
//Collections.sort(contacts);
return true;
}
#Override
public String toString()
{
return contacts.toString();
}
public List<Contact> getMyList()
{
return this.contacts;
}
public static void main(String[] args)
{
Contacts test=ContactsFactory.getContacts();
System.out.println(test.toString());
}
}
class ContactsFactory {
public static Contacts getContacts() {
String[] names={"A","B","C","D"};
int i=0;
Contacts contacts = new Contacts();
do {
System.out.println("Adding: "+names[i]);
contacts.add(new Contact(names[i]));
i++;
} while (i<names.length);
//print size to see anything added. It returns 0.
System.out.println(contacts.getMyList().size());
return contacts;
}
}
class Contact
{
String name;
#Override
public String toString()
{
return "Contact: "+this.name;
}
public Contact(String val)
{
this.name=val;
}
}
Output:
Adding: A
Adding: B
Adding: C
Adding: D
4
[Contact: A, Contact: B, Contact: C, Contact: D]
My personal mini project was to learn arrays here, doing a slightly big jump by making an Array of Objects. What I wanted to do was a mini RPG system where I create a class called monster and give it a couple parameters, and create an array of objects of the Monster class. So far I believe I created that Monster class and the Object of Arrays inside the main method class (Exec_Monster) listed below.
It took me a while initially, but I finally got to a point where I can create the array of Monsters and access them inside the Main class. But is there a way for me to create this Array of Objects and access each object from another class (and their individual values)? For Example, I would create a "Battle" class and then I would pull the "Health" value from an object of Monster.
I'm new to Arrays but I have had some experience with classes for the past two weeks here.
Class:
public class Monster
{
public int hp;
public String n;
public Monster(String name,int health){
n=name;
hp=health;
}
public int returnHealth(){
return hp;
}
public String returnName(){
return n;
}
}
Exec_Monster:
public class Exec_Monster{
public static void main(String args[])
{//Define Monsters
Monster[] monsterid=new Monster[]{
new Monster("Goblin",10),
new Monster("Elf", 8),
new Monster("Ant", 3),
new Monster("Worm", 2),
new Monster("Black Widow",6)};
Random chooser;
int chosenmonster=(chooser.nextInt()*5);
//Start
//while (Battle.wonloss==true) {
// Battle.battle();
}
}
You'd need to pass the monsters into the Battle object somehow (or into another object that you pass into the Battle object). You could pass it as an argument to a method, but in an Object Oriented world, if the monsters really belong to a battle, you could pass them in the constructor and make them available in all the methods of the Battle class.
Example:
public class Battle {
private Monster[] monsters;
private boolean wonloss;
public Battle(Monster[] monsters) {
this.monsters = monsters;
}
public boolean isWonloss() {
return wonloss;
}
public void battle() {
// Do something with monsters,
// and then check if there is any life left in the monsters
int totalHp = 0;
for (Monster monster : monsters) {
totalHp += monster.hp;
}
if (totalHp == 0) {
wonloss = false;
}
}
}
The "battle" part of your main method would then look like:
// Start
Battle battle = new Battle(monsterid);
while (battle.isWonloss()) {
battle.battle();
}