14. maj 2002 - 13:51Der er
12 kommentarer og 1 løsning
skabe en clone?
Er der lige en der kan gøre mig klogere og fortælle mig hvorfor min cloning af barn ikke virker?
class Fritidshjem implements Cloneable {
Fritidshjem() {
Børn barn = new Børn("Mette",8);
System.out.println(barn);
Børn klonBarn = (Børn) barn.clone();
System.out.println(klonBarn);
}
public static void main(String[] aslan) { new Fritidshjem(); } }
class Børn { String navn; int alder;
Børn(String n,int a) { navn = n; alder = a; } public String toString() { return navn+" "+alder; } }
fejlen er:
C:\Documents and Settings\aslan\Skrivebord\clone\Fritidshjem.java:12: clone() has protected access in java.lang.Object Børn klonBarn = (Børn) barn.clone(); ^ 1 error
Denne side indeholder artikler med forskellige perspektiver på Identity & Access Management i private og offentlige organisationer. Artiklerne behandler aktuelle IAM-emner og leveres af producenter, rådgivere og implementeringspartnere.
Fordi clone metoden nedarvet fra Object er erklæret protected, dvs. man ikke kan kalde den udenfor klassen eller i en underklasse. Du er i Fritidshjem der ikke er en subklasse til Børn.
Erklær en public metode i Børn: public Børn getClone() { return (Børn)clone(); } men husk at det er Børn og ikke Fritidshjem som skal have implements Cloneable!
Du skal skrive public Børn getClone() throws CloneNotSupportedException { ... } eller fange exception'en inde i getClone metoden, det går altid godt i dit tilfælde: public Børn getClone() { try { return (Børn)clone(); } catch(CloneNotSupportedException e){} return null; // bliver aldrig udført }
Det gør getClone metoden, den kalder clone der gør arbejdet for dig, sålænge du ikke bruger arrays men kun simple objekter som du gør i ovenstående. Du kalder metoden fra Fritidshjem klassen hvor du før forsøgte at kalde clone direkte.
Du skal huske på at det er dig der definerer nye klasser og objekter og derfor kun dig der ved hvordan man kloner dem fornuftigt. Jeg vil gerne smide en klasse op du kan bruge der udnytter serialisering istedet for clone der ligger bare en statisk metode der laver en kopi af et objekt der kan serialiseres, dvs implementerer Serializable istedet for Cloneable. Det vil bare sige at objektet kan sendes gennem streams (til og fra filer og over et netværk). Sig til så smider jeg den op.
/** * The class Serialization provides methods for * saving objects to files and loading objects from files. * The implementation is based on code from <I>Java Examples in a nutshell</I>. * <BR><B>Examples of use:</B><BR> * <PRE> * try { * Serializable o = ...; * Serialization.save( o, "object.ser" ); * ... * Serializable u = Serialization.load( "object.ser" ); * ... * Serializable v = Serialization.load( Serialization.loadFile() ); // interactive loading * ... * Serializable copy = Serialization.deepclone( u ); // bit for bit copy of u * } * catch ( IOException ioe ) {} // load and save may throw IOExceptions. * <PRE> * @author Carsten Knudsen * @version 1.0 **/ public class Serialization { /** * The class Serialization only has a private constructor * to prevent instantiation. * Use the class through its static methods. **/ private Serialization() { } // constructor
/** * Saves the serializable object o to the named file. **/ public static void save( Serializable o, String name ) throws IOException { save( o, new File( name ) ); } // save
/** * Saves the serializable object o to the File object. **/ public static void save( Serializable o, File file ) throws IOException { ObjectOutputStream out = new ObjectOutputStream( new FileOutputStream( file ) ); out.writeObject( o ); out.close(); } // save
/** * Loads a serializable object from the named file. **/ public static Serializable load( String name ) throws IOException, ClassNotFoundException { return load( new File( name ) ); } // save
/** * Loads a serializable object from the File object. **/ public static Serializable load( File file ) throws IOException, ClassNotFoundException { ObjectInputStream in = new ObjectInputStream( new FileInputStream( file ) ); Serializable o = (Serializable)in.readObject(); in.close(); return o; } // load
/** * The method makes a deep clone of the serializable object o by * sending it through piped streams. **/ public static Serializable deepclone( final Serializable o ) throws IOException, ClassNotFoundException { final PipedOutputStream pipeout = new PipedOutputStream(); PipedInputStream pipein = new PipedInputStream( pipeout ); Thread writer = new Thread() { public void run() { ObjectOutputStream out = null; try { out = new ObjectOutputStream( pipeout ); out.writeObject( o ); } // try catch( IOException e ) { } // catch finally { try { out.close(); } // try catch( Exception e ) { } // catch } // finally } // run }; writer.start(); ObjectInputStream in = new ObjectInputStream( pipein ); Serializable a = (Serializable)in.readObject(); in.close(); return a; } // deepclone
/** * **/ public static File loadFile() { final String ext = "ser"; JFileChooser fileChooser = new JFileChooser( new File( System.getProperty( "user.dir" ) ) ); fileChooser.setApproveButtonText( "Load" ); fileChooser.setFileFilter( new javax.swing.filechooser.FileFilter () { public boolean accept( File file ) { String fileName = file.getName(); if ( fileName.endsWith( "." + ext ) ) return true; else return false; } // accept public String getDescription() { return "Serialized. (*.ser)"; } // getDescription }); int result = fileChooser.showOpenDialog( null ); if ( result == JFileChooser.APPROVE_OPTION ) { return fileChooser.getSelectedFile(); } // if else { return null; } // else } // loadFile
/** * **/ public static File saveFile() { final String ext = "ser"; JFileChooser fileChooser = new JFileChooser( new File( System.getProperty( "user.dir" ) ) ); fileChooser.setApproveButtonText( "Save" ); fileChooser.setFileFilter( new javax.swing.filechooser.FileFilter () { public boolean accept( File file ) { String fileName = file.getName(); if ( fileName.endsWith( "." + ext ) ) return true; else return false; } // accept public String getDescription() { return "Serialized. (*.ser)"; } // getDescription }); int result = fileChooser.showSaveDialog( null ); if ( result == JFileChooser.APPROVE_OPTION ) { return fileChooser.getSelectedFile(); } // if else { return null; } // else } // saveFile
Fandt lige følgende der dog også kræver at du ikke bruger arrays etc. Du kan ændre access fra protected to private og så får du en mere elegant løsning for simple kloningsproblemer, men bemærk at du selv i dette eksempel står for al initialisering!
class MyClass implements Cloneable { public MyClass() { } public Object clone() { Cloneable theClone = new MyClass(); // Initialize theClone. return theClone; } }
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.