wood burning stoves 2.0*
The moose likes Beginning Java and the fly likes Problem with Cloning... Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Murach's Java Servlets and JSP this week in the Servlets forum!
JavaRanch » Java Forums » Java » Beginning Java
Bookmark "Problem with Cloning..." Watch "Problem with Cloning..." New topic
Author

Problem with Cloning...

Derrick Ritchie
Greenhorn

Joined: Jan 27, 2006
Posts: 6
import java.io.*;
import java.util.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;

public class LeagueWindow extends Observable implements ActionListener
{
TeamLeague CurrentLeague;
TeamLeague BackupLeague;
LeagueViewer CurrentView;
WinWindow WinningScores;
WrongWindow WrongScore;
JButton AddButton;
JButton EditTeam;
JButton SaveLeague;
JButton RollBack;
JButton QuitLeague;
JFrame MainFrame;

public LeagueWindow(TeamLeague ThisLeague)
{
//first, place the ThisLeague object as the current league
CurrentLeague = new TeamLeague(ThisLeague);

//add in a observer for the new league
final ViewOne NewView = new ViewOne();
CurrentLeague.addObserver(NewView);

//now create the league view by creating a league viewer
//with our basic league as it stands with no games played
CurrentView = new LeagueViewer(CurrentLeague);
//now we need to create the GUI to house the information in
//first create the buttons
AddButton = new JButton("Add Games");
EditTeam = new JButton("Edit Team");
RollBack = new JButton("Rollback Results");
SaveLeague = new JButton("Save League");
QuitLeague =new JButton("Quit");
//add an action listener to all objects
AddButton.addActionListener(this);
EditTeam.addActionListener(this);
SaveLeague.addActionListener(this);
RollBack.addActionListener(this);
QuitLeague.addActionListener(this);
//now create a box to house all the buttons
Box OptionsBox = new Box(BoxLayout.X_AXIS);
OptionsBox.add(AddButton);
OptionsBox.add(EditTeam);
OptionsBox.add(SaveLeague);
OptionsBox.add(RollBack);
OptionsBox.add(QuitLeague);
//now get the GUI from our leagueviewer
Component Table = CurrentView.getGUI();
//create our JFrame initiator
MainFrame = new JFrame("League Information");
//now add the Table and options views in together
MainFrame.getContentPane().add(Table, BorderLayout.WEST);
MainFrame.getContentPane().add(OptionsBox, BorderLayout.SOUTH);
MainFrame.setLocation(200, 200);
MainFrame.pack();
MainFrame.setVisible(true);

WinningScores = new WinWindow();
WrongScore = new WrongWindow();
}

public synchronized void actionPerformed(ActionEvent ThisEvent)
{
JButton TestButton = (JButton)ThisEvent.getSource();

if(TestButton == AddButton)
{

BackupLeague = (TeamLeague)CurrentLeague.clone();
//now we want to state the number of results
//that we are going to work with
//the number of games that can be played can only be half
//the size of the league itself so we get the length of the
//league and divide it by 2. If we only have 2 teams we can
//omly have 1 game so test for that first
int NumPlayed = 0;
//start a fixtures window ot be called when required
GamesPlayed Fixtures;

if(CurrentLeague.returnLength() == 2)
{
//if there is only two teams we can only have
//a maximum of 1 fixture so call the window with 1
//and set number of games playes as 1
Fixtures = new GamesPlayed(1);
NumPlayed = 1;
}
else
{
//otherwise we have more than 2 teams which means
//we can have more than 1 fixture at a time so prompt
//to see how many fixtures they want to put in
//this uses option 3 in the league setup to call the
//container with the right GUI inside it
LeagueSetupNew NewFixtureAmount =
new LeagueSetupNew(3, (CurrentLeague.returnLength()/2));

//returns the number of games to be played
String NumGames = NewFixtureAmount.returnSelected();

if(NumGames == null)
{
NumPlayed = 1;
}
else
{
NumPlayed = Integer.parseInt(NumGames);
}
//calls the fixtures window with the required number of games
Fixtures = new GamesPlayed(NumPlayed);
}

//now we have the fixtures we need to update the league
for(int x = 0; x < NumPlayed; x++)
{
//place each of the results in a holder. We will
//test each of these against null as if we have
//a null value then we know that that particular
//entry has been placed in wrongly and we need to
//ignore it
boolean Tester = false;
String Home = Fixtures.getHomeTeam(x);
String Away = Fixtures.getAwayTeam(x);
String HGoals = Fixtures.getHomeScore(x);
String AGoals = Fixtures.getAwayScore(x);

Tester = CurrentLeague.AddWins(Home, Away, HGoals, AGoals);
CurrentLeague.sort();
CurrentView.update(CurrentLeague);

System.out.println("Tester is " + Tester);

if(Tester == true)
{
//if its true then the result has been added correctly
//then we show it in a text area
WinningScores.Update(Home, Away, HGoals, AGoals);
}
else
{
//otherwise the result entered was wrong. This lists all
//the wrong results entered
WrongScore.Update(Home, Away, HGoals, AGoals);
}
}

System.out.println("Backup League is");
String Show = BackupLeague.showLeague();
System.out.println(Show);
}
if(TestButton == EditTeam)
{
//call the edit menu
EditFrame NewMenu = new EditFrame(CurrentLeague);
//sort the league with the update
CurrentLeague.sort();
//display the newly updated league
CurrentView.update(CurrentLeague);
}
if(TestButton == SaveLeague)
{
System.out.println("In Saver League");
try
{
SLeague Saver = new SLeague(CurrentLeague);
}
catch(Exception ThisException)
{
}
}
if(TestButton == RollBack)
{
int LoopValue = BackupLeague.returnLength();

System.out.println("Current League is");
String Show = CurrentLeague.showLeague();
System.out.println(Show);
System.out.println("Backup League is");
Show = BackupLeague.showLeague();
System.out.println(Show);

for(int i = 1; i <= LoopValue; i++)
{
Team FirstTeam = BackupLeague.returnTeam(i);
CurrentLeague.setTeam(i, FirstTeam);
}

CurrentView.update(CurrentLeague);
}
else if(TestButton == QuitLeague)
{
MainFrame.setVisible(false);
MainFrame.dispose();
System.exit(0);
}
}
}

Above is a small GUI that displays a soccer league table. Initially this table is created and populated in another function and passed as ThisLeague.
I then create it as a new object CurrentLeague by calling the constructor Thisleague as an argument.
Everything is ok but what I want to do is create a backup league that sits one operation back from the current one. So when I initilly try to add results by clicking the Add button I want to create a clone of Currentleague called backupleague which will hold the league table before any results are added. Currentleague should then be updated and Backup league should hold the table before the results are added.
However when I call backup table once the reuslts have been added I find that it has also been updated and I cant figure out why, can anyone help?

The clone and Teamleague constructor code looks like this:

public class TeamLeague extends Observable implements League, Cloneable
{
//size of the leage
private int Size;
//a array of teams that comprise a league
private Team[] NewLeague;
public TeamLeague(TeamLeague ThisLeague)
{
System.out.println("In Constructor with league");

final TeamLeague TempLeague = (TeamLeague)ThisLeague;

Size = TempLeague.Size;

NewLeague = new Team[Size + 1];

System.arraycopy(TempLeague.NewLeague, 1, NewLeague, 1, Size);
}

public Object clone()
{
try
{

TeamLeague NewObject = (TeamLeague)super.clone();
NewObject.NewLeague = (Team[])NewLeague.clone();
return NewObject;
}

catch(CloneNotSupportedException ThisClone)
{
throw new InternalError(ThisClone.toString());
}
}
}

If anyone can help it would be much appreciated
Yuriy Zilbergleyt
Ranch Hand

Joined: Dec 13, 2004
Posts: 429
I'm guessing that at some point only a shallow clone is created, when you need a deep clone. The default clone behavior for many classes only does shallow cloning. For example, if you clone an ArrayList, you'll have two ArrayLists holding references to the same exact objects. If the objects are modified, you'll see the modification no matter which array list you use. For example:



In your case, for example, your backup league's NewLeague array is probably pointing to the same exact Team objects as your current league's array. So when the team's stats are updated through the current league, these will be reflected in the backup since they all reference the same Team object instance. If you want a deep copy, depending on the objects you're working with you may have to implement it yourself.

By the way, I strongly recommend that you use the standard Java naming conventions in which variables/attribute names start with lower-case letters (final TeamLeague tempLeague = (TeamLeague)thisLeague instead of final TeamLeague TempLeague = (TeamLeague)ThisLeague.) It would make it a lot easier for other people to understand your code.
[ May 02, 2006: Message edited by: Yuriy Zilbergleyt ]
 
It is sorta covered in the JavaRanch Style Guide.
 
subject: Problem with Cloning...
 
Similar Threads
JTextField.setText Not Working
Changing The ImageIcon Of a JButton With a click
Design a system to manage a sporting league
i want some help in writing the code for the below description
Calculator clear button not working...