initializing ArrayList<>() in methods or constructor - java

import java.util.ArrayList;
public class Team {
private String name;
private ArrayList<Player> team;
public Team(String name) {
this.name = name;
//how come i have to initialize it here in the constructor to see the full list?
this.team = new ArrayList<Player>();
}
public void addPlayer(Player player) {
//why can't i initialize it here in the method, this gives me a list of only recent add?
//this.team = new ArrayList<Player>();
this.team.add(player);
}
public void printPlayers() {
for(Player players : this.team) {
System.out.println(players);
}
}
public String getName() { return this.name; }
}
I'm trying to figure out why this.team = new ArrayList<Player>() have to be in the constructor?
Why can't I have this.team = new ArrayList<Player>() initialized in the method?
I know that when I run it with the code in the constructor it works as intended (it gives me the full list when things are added)
BUT when it's initialized in the method it only list the last given addition to the list. Is it wrong to have it initialized in the method?
Also what's the difference of having it initialized as private ArrayList<Player> team = new ArrayList<Player>(); before the constructor?

Answering just the question:
Also what's the difference of having it initialized as private ArrayList<Player> team = new ArrayList<Player>(); before the constructor?
Nothing, aside from the fact that team would be initialized before name.
Field initializers are syntactic sugar for instance initializers. So this:
private ArrayList<Player> team = new ArrayList<Player>();
is identical to this:
private ArrayList<Player> team;
{
// This is an instance initializer.
team = new ArrayList<Player>();
}
and instance initializers are gathered together and inserted into every constructor which invokes (implicitly or explicily) super, in between the call to super and the rest of the constructor body. So this:
public class Team {
private ArrayList<Player> team = new ArrayList<>();
public Team(String name) {
this.name = name;
}
}
is identical to:
public class Team {
private ArrayList<Player> team;
public Team(String name) {
super();
this.team = new ArrayList<>();
this.name = name;
}
}

Because of the fact that each constructor invocation will result in a new distinct object the line this.team = new ArrayList<Player>(); within the constructor will only be called once per instance so thus you'll only ever have one ArrayList instance per object in this specific case.
On the other hand, the addPlayer method can be called as many times as you want on a given object thus this.team = new ArrayList<Player>(); within the addPlayer method will replace (overwrite) the previous list on each method call.

You can do this in that way (to prevent recreation of ArrayList on every addPlayer method call):
public void addPlayer(Player player) {
if (this.team == null) {
this.team = new ArrayList<Player>();
}
this.team.add(player);
}
but it will be VERY weird code... Better practice is to initialize 'team' list inside constructor or inline in field declaration. Both of them do the same thing. I prefer to initialize fields inside constructor, but this is only my habit. Other programmers may prefer inline version and this is nothing wrong/bad.

Why can't I have this.team = new ArrayList() initialized in the method?
You're creating a new ArrayList each time and assigning it to this.team. So each time you call addPlayer, you're replacing this.team with a new empty ArrayList and then adding a player with this.team.add(player), so only the last added player is in the ArrayList at all times.
What you could do if you really don't want to create the ArrayList in the constructor is check if this.team is null every time you add a player and if the ArrayList is not created or empty, simply create one.
public void addPlayer(Player player) {
if (this.team == null) {
this.team = new ArrayList<Player>();
}
this.team.add(player);
}
Also what's the difference of having it initialized as private ArrayList team = new ArrayList(); before the constructor?
If you're wondering whether the private keyword changes anything, you should read the Java docs on access modifiers: https://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html
Other than that, initializing before the constructor changes nothing in this case.

I'm trying to figure out why this.team = new ArrayList() have to be in the constructor?
It doesn't, it has to be initialized before it is used. You can initialize it anywhere you want as long as you don't call printPlayer() or addPlayer() before.
Why can't I have this.team = new ArrayList() initialized in the method?
You actually can. See this example:
public void addPlayer(Player player) {
if (team == null) {
team = new ArrayList();
}
team.add(player);
}
public void printPlayers() {
if (team != null) {
for (Player p : team) {
System.out.println(p);
}
}
}
BUT when it's initialized in the method it only list the last given addition to the list. Is it wrong to have it initialized in the method?
No, it's not wrong. It's typically referred to as "lazy initialization" or "on demand" if you do it in the way of the example above.
Also what's the difference of having it initialized as private ArrayList team = new ArrayList(); before the constructor?
Not much, the difference lies in when it is initialized.
public class Example {
public static List<T> myList = new ArrayList<T>(); // this is done first
public static List<T> aList;
public List<T> someList;
static {
// this is also done first (on class load)
aList = new ArrayList<T>();
}
{
// this is done right before the constructor (I believe)
// it is called an 'initialization block'
someList = new ArrayList<T>();
}
public Example() {
// this one you already know...
}
}

Related

How to add parent class attributes to sub class

I have a parent class named Set representing a set of a tennis matches.
public class Set {
private String set1;
private String set2;
private String set3;
//private Object[] match;
public Set() {
setSet1(set1);
setSet2(set2);
setSet3(set3);
}
public void setSet1(String set1) {
this.set1 = set1;
}
public String getSet1() {
return set1;
}
public void setSet2(String set2) {
this.set2 = set2;
}
public String getSet2() {
return set2;
}
public void setSet3(String set3) {
this.set3 = set3;
}
public String getSet3() {
return set3;
}
public String toString(){
return String.format("set1: %s, set2: %s, set3: %s", set1, set2, set3);
}
}
and a sub class of Set named SingleSet where I try to add the sets into an array named `game.
public class SingleSet extends Set{
private Object homePlayer;
private Object awayPlayer;
private String[] game;
public SingleSet(Object homePlayer, Object awayPlayer){
super();
game = new String[3];
game[0] = super.getSet1();
game[1] = super.getSet2();
game[2] = super.getSet3();
setHomePlayer(homePlayer);
setAwayPlayer(awayPlayer);
}
public void setHomePlayer(Object homePlayer) {
this.homePlayer = homePlayer;
}
public Object getHomePlayer() {
return homePlayer;
}
public void setAwayPlayer(Object awayPlayer) {
this.awayPlayer = awayPlayer;
}
public Object getAwayPlayer() {
return awayPlayer;
}
public void setGame(String[] game) {
this.game = game;
}
public String[] getGame() {
return game;
}
public String toString(){
return String.format("Player: %s Vs. Player: %s, Single set game: %s, %s, %s", homePlayer, awayPlayer, game[0], game[1], game[2]);
}
}
This is where I am trying to add the Sets from my parents class into my sub class (this is for FXML, so the code is in my controller):
public void submit() {
SingleSet game1 = new SingleSet(homePlayer1Dropdown.getValue(), awayPlayer1Dropdown.getValue());
game1.setSet1(set1Box1.getText());
game1.setSet2(set1Box2.getText());
game1.setSet3(set1Box3.getText());
System.out.println(game1);
}
When I print the result, my array values are null. I tried printing them individually and that worked fine, so I know the set1Box.getText() is working fine.
The reason you are seeing null values when you print is because they are actually null.
SingleSet game1 = new SingleSet(homePlayer1Dropdown.getValue(), awayPlayer1Dropdown.getValue()); is creating a new SingleSet, which extends Set.
SingleSet constructor makes a super() call to Set constructor.
When Set is created for the first time, all its values are null. Then constructor kicks in, but Set constructor actually does nothing, so Set's instance variables remain null.
Ten SingleSet carries on on building your object with parameter given, which do nothing for setting a value for set1, set2, set3.
game1.setSet1(set1Box1.getText());
game1.setSet2(set1Box2.getText());
game1.setSet3(set1Box3.getText());
They actually set a value to set1, set2, set3 (since you are saying that set1Box1.getText() and others are working). So why you are still seeing null when printing?
public String toString(){
return String.format("Player: %s Vs. Player: %s, Single set game: %s, %s, %s", homePlayer, awayPlayer, game[0], game[1], game[2]);
}
That's why: you are printing game[0], and so on, that are actually null because when you set your game array, those values where null!
public SingleSet(Object homePlayer, Object awayPlayer){
super(); //setting null values to set1, set2, set3
game = new String[3];
game[0] = super.getSet1(); //this returns null!
game[1] = super.getSet2(); //this returns null!
game[2] = super.getSet3(); //this returns null!
setHomePlayer(homePlayer);
setAwayPlayer(awayPlayer);
}
Print some values when you build your object and will see :)
To solve, one way is to use a parametrized constructor public Set(String set1, String set2, String set3), use a parametrized child constructor public SingleSet(String set1, String set2, String set3, Object homePlayer, Object awayPlayer) and a parametrized call to super, super(set1, set2, set3)
Then you should set values when creating game1
SingleSet game1 = new SingleSet(set1Box1.getText(), set1Box1.getText(), set1Box1.getText()homePlayer1Dropdown.getValue(), awayPlayer1Dropdown.getValue());
You are not setting anything in Set's default constructor
Should really find a better name for your class as "Set" is confusing with collections Set.
Make use of immutable for both of your classes to save yourself from trouble - remove all the setters and initialize in constructor.
I'm not that good at tennis scoring rules, but to my best knowledge a "set" has number of "games", and "match" consists from a number of sets. What is the logic for this relation "Set <- SingleSet"? What if you change your hierarchy in this way (in pseudo-code, will skip most method bodies for brevity):
class Player{
private String name;
public Player(String name);
}
class Match{
private Player homePlayer;
private Player awayPlayer;
private List<Set> sets;
public Match(Player homePlayer, Public awayPlayer);
public List<Set> getSets(){
if(sets == null){
sets = new ArrayList<>();
}
return sets;
}
}
class Set{
public Set(Game... games);
}
class Game{
// game score details
public Game(int scoreHomePlayer, int scoreAwayPlayer);
}
So that in your Controller, you could use it like this:
Match match = new Match(new Player("Williams"), new Player("Johnson"))
match.getSets().add(new Set(
new Game(6, 1),
new Game(4, 6),
new Game(7, 0)
// etc.
))
You could further refactor #4 hierarchy and spare all these "new ()" constructor calls using Builder Pattern, something along the line:
Match match = new MatchBuilder("Williams","Johnson").addSet()
.addGame(6,1).addGame(4,6).addGame(7,0)
.build()
you should override set method .Instead of in the set after the constructor is instantiated
public SingleSet(Object homePlayer, Object awayPlayer) {
super();
game = new String[3];
// game[0] = super.getSet1();
// game[1] = super.getSet2();
// game[2] = super.getSet3();
setHomePlayer(homePlayer);
setAwayPlayer(awayPlayer);
}
#Override
public void setSet1(String set1) {
this.game[0]=set1;
super.setSet1(set1);
}
#Override
public void setSet2(String set2) {
this.game[1]=set2;
super.setSet2(set2);
}
#Override
public void setSet3(String set3) {
this.game[2]=set3;
super.setSet3(set3);
}

How to add an object to ArrayList

I am creating a UI with object oriented programming.
In the UI I am trying to add a new team. When I add this team, I want the object of the team to be stored into an ArrayList named 'TeamList'.
I am able to store the team just fine as an object from the UI, but I cannot add the team into the TeamList ArrayList, and im not sure what I'm doing wrong.
I am new to programming so I apologise for any bad errors.
This is my TeamList class ('Team' is an object I've already created):
public class TeamList {
private ArrayList<Team> teamList;
public TeamList(){
setTeamList(teamList);
}
public ArrayList<Team> getTeamList() {
return teamList;
}
public void setTeamList(ArrayList<Team> teamList) {
this.teamList = teamList;
}
And this is where Im trying to add 'Team' to 'TeamList':
#FXML private void AddingTeam() {
Team team = new Team(newTeamTextfield.getText());
team.getTeamName();
TeamList teams = new TeamList();
teams.add(team);
}
The error is with:
teams.add(team);
Add add() method in TeamList and your list is null by default and in constructor you are assigning instance which is null to itself
//Do below and remove constructor
private ArrayList<Team> teamList = new ArrayList<>();
//or
public class TeamList {
private ArrayList<Team> teamList;
public TeamList(){
setTeamList(new ArrayList<Team>());
}
public ArrayList<Team> getTeamList() {
return teamList;
}
public void add(Team team){
teamList.add(team);
}
public void setTeamList(ArrayList<Team> teamList) {
this.teamList = teamList;
}
}
The object teams isn't an ArrayList, it's a TeamList object. Therefore, you can't use .add() because it is not of type ArrayList.
Make an ArrayList<Team> instead, and then use .add(team) with your new ArrayList.
Use
ArrayList<TeamList> teams = new ArrayList<TeamList>();
to add the team to teams list

How to put 2 arraylists into one hashmap?

So I'm making a plugin and I want to put two ArrayList (of two different teams) to one Hashmap, so I can get both of the teams in this method:
public static Teams getTeam(Player player) {
if (!hasTeam(player))
return null;
return zombiesTeam.get(player) && survivorsTeam.get(player);
}
Here is the two ArrayList and a Hashmap that I want to have:
public static HashMap<zombiesTeam, survivorsTeam> playerTeams = new HashMap<zombiesTeam, survivorsTeam>();
public static ArrayList<Player> zombiesTeam = new ArrayList<Player>();
public static ArrayList<Player> survivorsTeam = new ArrayList<Player>();
P.S. I know that this code isn't correct
Please ask me for any further additional information
Thanks in advance.
You should do something like this:
public static HashMap<String, ArrayList<Player>> playerTeams = new HashMap<>();
playerTeams.put("zombies", zombiesTeam);
playerTeams.put("survivors", survivorsTeam );
If you want to represent all your "teams" by a hashmap from the team name to the list of team members, I would suggest this:
// In the same class where zombiesTeam and survivorsTeam are declared
public static Map<String, List<Player>> getTeamsByName() {
Map<String, List<Player>> teamsByName = new HashMap<>();
teamsByName.put("zombiesTeam", zombiesTeam);
teamsByName.put("survivors", survivorsTeam);
return teamsByName;
}
However, be sure that you need to use static fields and methods. Your model doesn't suggest this.
For instance, you could rather declare a Team class and a Player class. Since you already have the Player class, here is how I would make the Team class:
public class Team {
private String name;
private Set<Player> teamMembers = new HashSet<>();
public Team(String name) {
this.name = name;
}
public String getName() {
return this.teamName;
}
public Set<Player> getTeamMembers() {
return this.teamMembers;
}
public addPlayer(Player player) {
this.teamMembers.add(player);
}
public removePlayer(Player player) {
this.teamMembers.remove(player);
}
public reset() {
this.teamMembers.clear();
}
}
Be sure to override equals and hashcode for HashSet and HashMap to work correctly. More information about this here:https://www.geeksforgeeks.org/equals-hashcode-methods-java/

Instantiating static object of a Class

I have been coding in Java for about a week now but I am still having issues learning it.
I know that we can create a class and then create instance of it by using the name of a class.
but I have this code which is giving me trouble understanding what is happening here,
This is the file called XMLGettersSetters.java,
public class XMLGettersSetters {
private ArrayList<String> title = new ArrayList<String>();
private ArrayList<String> artist = new ArrayList<String>();
private ArrayList<String> country = new ArrayList<String>();
private ArrayList<String> company = new ArrayList<String>();
private ArrayList<String> price = new ArrayList<String>();
private ArrayList<String> year = new ArrayList<String>();
public ArrayList<String> getCompany() {
return company;
}
public void setCompany(String company) {
this.company.add(company);
Log.i("This is the company:", company);
}
public ArrayList<String> getPrice() {
return price;
}
public void setPrice(String price) {
this.price.add(price);
Log.i("This is the price:", price);
}
public ArrayList<String> getYear() {
return year;
}
public void setYear(String year) {
this.year.add(year);
Log.i("This is the year:", year);
}
public ArrayList<String> getTitle() {
return title;
}
public void setTitle(String title) {
this.title.add(title);
Log.i("This is the title:", title);
}
public ArrayList<String> getArtist() {
return artist;
}
public void setArtist(String artist) {
this.artist.add(artist);
Log.i("This is the artist:", artist);
}
public ArrayList<String> getCountry() {
return country;
}
public void setCountry(String country) {
this.country.add(country);
Log.i("This is the country:", country);
}
}
Now I can create object of this class like this,
XMLGettersSetters myObject = new XMLGettersSetters();
but from the website where I am learning this code, they have created the objects like this,
public static XMLGettersSetters data = null;
How come the object is declared static ? what does the above code even mean.
Shouldn't it just be,
XMLGettersSetters data = null;
From what I know, when we declare a variable as static then we donot need to instantiate a class to use a static variable from that class.
One more question,
public static XMLGettersSetters getXMLData() {
return data;
}
I have no idea what happened in the above code,
first the object is instantiated as static then instead of giving object a name, a function is given instead which is getXMLData().
And the return type is data
Now about the code below,
public static void setXMLData(XMLGettersSetters data) {
XMLHandler.data = data;
}
A method is created with XMLGettersSetters object as an argument, but what about XMLHandler.data ?
What is it ? shouldn't it be this.data ?
They probably created the object static because they want it to be global. For example, anywhere in the code you will be able to call XMLHandler.data. (I'm supposing here the class in which is created the data variable is XMLHandler because it is used in the setter method..
If it would simply be XMLGettersSetters data = null; instead of static... then it could not be accessed from anywhere in the code.
As for the XMLHandler.data used instead of this.data you have to know that by convention, most of the people specify the class name before the object they are accessing when accessing a static variable.
Static is a field, not an object. Static fields are per class, shared by all code that have access to this field. They are initialized only once, when the class is first loaded. Usual fields (without static) are per object instance. They are initialized when the object instance is created.
In Java, you can assign the value in the same sentence where you declare the variable:
int x = 2;
Object y = new Object().
The object is instantiated, but then placed into a static variable. This means that you always access the same instance of the XMLGettersAndSetters.
As the methods are static you have to refer to a static variable rather than this.data which refers to the variable in the current instance.

Changing parent object to child object

I need a bit of help here. so i have this. I was basically wondering when you create an array of object of a parent class, then change that object to a child class, can I access the methods of that child class and if not why. thanks for any help.
public class Racer {
private String name;
private int position;
// Constructor
public Racer()
{}
public Racer(String name)
{
this.name = name;
position = 0;
}
public String getName()
{
return name;
}
public int getPosition()
{
return position;
}
public void setPosition(int n)
{
position = n;
}
public void setName(String n){
this.name=n;
}
}
the child class
public class Spartiates extends Racer{
private int energy;
public Spartiates(){
super();
}
public Spartiates(String name){
setName(name);
setPosition(20);
energy=100;
}
public void setEnergy(int energy){
this.energy=energy;
}
public int getEnergy(){
return energy;
}
}
main class
public class demo{
public static void main(String[] args){
Racer [] player = new player[3];
for(int i=0; i<player.length; i++){
player[i] = new Spartiates();
}
System.out.println(player[1].getEnergy());
}
so here the problem the getEnergy method doesn't work so I was wondering why. If anybody can help it would be very much appreciated. thanks
This is discussed here:
Is it possible to call subclasses' methods on a superclass object?
Along with all the reasons why doing something like this is probably never a good idea :).
You'll have to cast it to an instance of the subclass. If you plan on having a mixed array of object instances you'd need to first check the type:
System.out.println(((Racer)player[1]).getEnergy());
You need either define the function in the superclass or cast the object to the subclass.
If you intend the array to hold ONLY elements of the subclass Spartiates, then declare it as such.
Otherwise, if it needs to hold objects of both type, there only way to do this is to check with instanceof.
if (player[1] instanceof Spartiates)
System.out.println(((Spartiates)player[1]).getEnergy());
else
// handle other types
The reason energy is 0 is because you are calling your empty (no arg) constructor:
player[i] = new Spartiates();
which does not initialize the energy variable (so it will be 0 by default). You only set the variable to 100 in the constructor which takes in a String, namely here:
public Spartiates(String name){
setName(name);
setPosition(20);
energy=100;
}
So either call that constructor in the for loop with some string as an argument, or call your setEnergy() setter with some value after creating the object with the empty constructor.
Also, this is wrong:
Racer [] player = new player[3];
It should read:
Racer [] player = new Racer[3];
or:
Racer [] player = new Spartiates[3];

Categories

Resources