Você pode implementar um construtor de cópia. Essa técnica é muito usada na collections framework:
public class Ponto {
private int x;
private int y;
public Ponto(int x, int y) {
this.x = x;
this.y = y;
}
//Constrói um novo ponto, idêntico ao passado por parâmetro.
public Ponto(Ponto outroPonto) {
this.x = outroPonto.x;
this.y = outroPonto.y;
}
public int getX() {return x};
public int getY() {return y};
}
Uso:
Ponto p = new Ponto(10,10);
Ponto p2 = new Ponto(p);
O método de cópia também poderia ser estático:
public class Ponto {
private int x;
private int y;
public Ponto (int x, int y) {
this.x = x;
this.y = y;
}
//Constrói um novo ponto, idêntico ao passado por parâmetro.
public static Ponto copy(Ponto outroPonto) {
return new Ponto(outroPonto.x, outroPonto.y);
}
public int getX() {return x};
public int getY() {return y};
}
Uso:
Ponto p = new Ponto(10,10);
Ponto p2 = Ponto.copy(p);
A vantagem de usar essa última abordagem, ao invés do Clone, é que você não é obrigado a retornar uma cópia que seja a mesma classe do ponto original. Você pode retornar uma classe filha ou um wrapper, que tenham uma implementação mais eficiente para o caso da cópia.
Ambas as abordagens tem outra vantagem. Você pode receber qualquer tipo de ponto na hora de fazer a cópia. É o que ocorre na collections framework. Você pode fazer uma cópia de um set numa lista fazendo:
List minhaLista = new ArrayList(meuSet);
Agora é saber se alguma dessas técnicas tem utilidade no seu caso.