I have no idea what immutable class should look like but am pretty sure this one is. Am I right? If I'm not please specify what should be added/removed.
import java.io.Serializable;
public class Triangle implements IShape, Serializable {
private static final long serialVersionUID = 0x100;
private Point[] points;
public Triangle(Point a, Point b, Point c) {
this.points = new Point[]{a, b, c};
}
#Override
public Point[] getPoints() {
return this.points;
}
#Override
public boolean equals(Object obj) {
if (obj == null) return false;
if (this == obj) return true;
if (getClass() != obj.getClass()) return false;
Point[] trianglePoints = ((Triangle) obj).getPoints();
for (int i = 0; i < points.length; i++){
if (!points[i].equals(trianglePoints[i])) return false;
}
return true;
}
}
Will this do the trick?
#Override
public Point[] getPoints() {
Point[] copyPoint = {
new Point(points[0]),
new Point(points[1]),
new Point(points[2]),};
return copyPoint;
}
Point class:
import java.io.Serializable;
public class Point implements Serializable {
private static final long serialVersionUID = 0x100;
public int x;
public int y;
public int z;
public Point(int x, int y, int z) {
this.x = x;
this.y = y;
this.z = z;
}
public Point(Point that) {
this.x = that.x;
this.y = that.y;
this.z = that.z;
}
public boolean equals(Object obj) {
// assume this is a typical, safe .equals implementation
// that compares the coordinates in this instance to the
// other instance
return true;
}
}
No, you can change what's in the Points array. If you want to make it immutable, have the getter hand out a copy of the Points array, not the original.
try this:
Triangle triangle = new Triangle(a, b, c);
triangle.getPoints()[1] = null;
System.out.println(Arrays.toString(triangle.getPoints()));
Also Point needs to be immutable (as Nikita Rybak points out). For how to copy arrays see how to copy an array in Java.
No, it's not. You expose the Point[] and a caller could modify its contents. Also, your class is not final, so someone could subvert it by subclassing it.
No, it's definitely mutable.
Not only do you expose the actual Point[] array, you don't defensive-copy (Bloch 2nd ed., Item 39) the Point objects themselves when taking them in via the constructor.
The Point[] array could have items
removed or added to it, so it's
mutable.
You could pass in Points a,
b, and c, then call setX() or setY()
on them to change their data after
construction.
Close. For one thing, an immutable class should make it's fields final, but that's not a requirement.
However, you are exposing an array through the getter, and that is not immutable. Make a defensive copy using Arrays.copyOf(array, length):
#Override
public Point[] getPoints() {
return Arrays.copyOf(this.points,this.points.length);
}
Here's what I'd do to make this class immutable, with the help of Guava. I see from the #Override in the code you posted that IShape seems to require a Point[] from the getPoints() method, but I'm ignoring that for the sake of example since the use of object arrays is a rather poor idea, especially if you want immutability (since they cannot be immutable and all).
public final class Triangle implements IShape, Serializable {
private final ImmutableList<Point> points;
public Triangle(Point a, Point b, Point c) {
this.points = ImmutableList.of(a, b, c);
}
public ImmutableList<Point> getPoints() {
return this.points;
}
// ...
}
Point should also be more like:
public final class Point implements Serializable {
/*
* Could use public final here really, but I prefer
* consistent use of methods.
*/
private final int x;
private final int y;
private final int z;
public Point(int x, int y, int z) {
this.x = x;
this.y = y;
this.z = z;
}
// getters, etc.
}
In order to be an immutable class, it is not enough that your methods promise not to change the object. In addition to having all fields be private and the methods not allow changing, you must also guarantee that the subclasses have the same promise of immutability. This includes making the class itself final, and ensuring that no references to the fields are ever returned.
A short, but excellent treatment of this can be found in this article:
http://www.javaranch.com/journal/2003/04/immutable.htm
Not only do you need to provide an immutable copy of the internalised array, you also need to make sure that the Point object is immutable.
Consider the following use of the Point class in the standard Java API:
Point a = new Point(1,1);
Point b = new Point(1,1);
Point c = new Point(1,1);
Triangle triangle = new Triangle(a, b, c);
System.out.println(Arrays.toString(triangle.getPoints()));
c.setLocation(99,99);
System.out.println(Arrays.toString(triangle.getPoints()));
It is not immutable because ...
Triangle t1 = new Triangle(new Point(0,0), new Point(0, 10), new Point(10, 10));
Triangle t2 = t1;
System.out.println( t1.getPoints()[0] ); // -> 0
t2.getPoints()[0].x = 10;
System.out.println( t1.getPoints()[0] ); // -> 10
Thus the class is not immutable because you can change the state of an instance (internal Point[] exposed) and this also changes the state of a reference to the same instance.
To make it a true immutable class, you would need methods to separately get X and Y from each point, for example:
public int getPointX(int point) { return points[point].x; }
public int getPointY(int point) { return points[point].y; }
or
public Point getPoint(int point) { return new Point(points[point]); }
or return a copy of the points like you suggested in your edit.
In addition to what others have already noted, you should:
Make your Triangle class final to prevent the creation of mutable Triangles by subclasses.
Declare all the fields final, to catch accidental modification of fields by the class itself.
In "Effective Java," Joshua Bloch provides a list of rules for immutable classes in general, in Item 15: Minimize Mutability.
1) Make members private and final - so
private Point[] points; //should be
private final Point[] points;
2) Make class final so it cannot be sub-classed
3) Exclusive access to mutable members (array) - meaning return copy of and not the reference to mutable members
For the best treatment of this subject refer to Joshua Bloch, Effective Java- item 15
This could be a better Point implementation.
import java.io.Serializable;
public final class Point implements Serializable {
private static final long serialVersionUID = 0x100;
private final int x;
private final int y;
private final int z;
public Point(int x, int y, int z) {
this.x = x;
this.y = y;
this.z = z;
}
public Point(Point that) {
this(that.x, that.y, that.z );
}
public boolean equals(Object obj) {
// assume this is a typical, safe .equals implementation
// that compares the coordinates in this instance to the
// other instance
return true;
}
}
Other than exposing the array (as getters are wont to do) and not being final, being serialisable is "problematic".
As a very nasty man, when deserialising, I can get another reference to the internal array. The obvious fix for this is:
private void readObject(
ObjectInputStream in
) throws ClassNotFoundException, IOException {
ObjectInputStream.GetField fields = in.readFields();
this.points = ((Point[])(fields.get("point", null)).clone();
}
That still leaves the problem of points not being final and exposing the object without points initialised (or worse, but a bit thoeretical, partially initialised). What you really want is a "serial proxy", which you can find out about on the internets...
Note: If you implement equals you should also implement hashCode, probably toString and possible Comparable.
Point itself doesn't have to be immutable for Triangle to be immutable. You just have to do a lot of defensive copies so that nobody has a reference to the Point objects stored in the Triangle.
Also, shouldn't triangle a-b-c equal triange b-c-a (and 4 other permutations)
A immutable class example with mutable field:
public final class ImmutabilityTest {
private final int i;
private final C c1;
ImmutabilityTest(int i, C c1){
this.i = i;
this.c1 = c1;
}
public int getI() {
return i;
}
public C getC1() {
return (C)c1.clone();//If return c1 simply without calling clone then contract of immutable object will break down
}
#Override
public String toString() {
return "ImmutabilityTest [i=" + i + ", c1=" + c1 + "]";
}
public static void main(String[] args) {
ImmutabilityTest i1 = new ImmutabilityTest(10, new C(new D("before")));
System.out.println(i1);
i1.getC1().getD1().name = "changed";
System.out.println(i1);
}
}
class C implements Cloneable{
D d1;
public C(D d1) {
super();
this.d1 = d1;
}
public D getD1() {
return d1;
}
public void setD1(D d1) {
this.d1 = d1;
}
#Override
public String toString() {
return "C [d1=" + d1 + "]";
}
public C clone(){
C c = null;
try {
c = (C) super.clone();
c.setD1(c.getD1().clone());// here deep cloning is handled if it is commented it will become shallow cloning
} catch (CloneNotSupportedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return c;
}
}
class D implements Cloneable{
String name;
public D(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#Override
public String toString() {
return "D [name=" + name + "]";
}
public D clone(){
D d = null;
try {
d = (D) super.clone();
} catch (CloneNotSupportedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return d;
}
}
Related
Let A be an interface which has a method a.
Let B be a class which implements A and has method a and has three fields 1,2,3.
I want to use two instances of A (meaning B), both of which have different values of 1,2,3 (present in cfg file) at two different places.
Can someone provide a simple and elegant solution to this problem using Guice.
You don't tell how the class that uses your dependency references the interface. I assume that you want to reference it with an interface.
What you can use, is annotation that will denote which instance you want to use. Assume that these are your implementations:
interface A {
void a();
}
class B implements A {
private int value;
void a() { ... }
B(int value) { this.value = value; }
}
And these are the classes that use the implementations:
class UserFirst {
private A a;
#Inject
UserFirst(#Named("first") A a) { this.a = a; }
}
class UserSecond {
private A a;
#Inject
UserSecond(#Named("second") A a) { this.a = a; }
}
The thing that decides which implementation is going to be injected is the #Named annotation. You can also define your annotations, but usually it's an overkill.
Now, in order to bind that, you can do something like this:
class MyModule extends AbstractModule {
#Override
protected void configure() {
A first = new B(1);
B second = new B(2);
bind(A.class)
.annotatedWith(Names.named("first")).toInstance(first);
bind(A.class)
.annotatedWith(Names.named("second")).toInstance(second);
}
}
Here's the full documentation: https://github.com/google/guice/wiki/BindingAnnotations
if I do understand you correctly, you might want to make B abstract so that you can override the methods which you want to change, if this is the case.
Now I can only assume that by fields you mean field-varriables. I would then recommend you to make them NON-static and change them in the constructor when you make an object. Then read the values of 1,2,3 in the public static void main method and send them upon creating a new object:
public class B implements A {
private int x,y,z;
/**
* This would now be the constructror
*/
public B(int x, int y, int z){
this.x = x;
this.y = y;
this.z = z;
}
/**
* Then some return functions
*/
public get1() { return this.x; }
public get2() { return this.y; }
public get3() { return this.z; }
/**
* Then whatever methods you get from A
*/
public int someMethodFromA(int x, int y){
return x*y;
}
}
public static void main(String[] args) {
/**
* Some random method to read inn from CFG file
*/
int x1 = readXFromCFG();
int y1 = readYFromCFG();
int z1 = readZFromCFG();
B objectB1 = new B(x1,y1,z1);
int x2 = readXFromCFG();
int y2 = readYFromCFG();
int z2 = readZFromCFG();
B objectB2 = new B(x2,y2,z2);
int x3 = readXFromCFG();
int y3 = readYFromCFG();
int z3 = readZFromCFG();
B objectB3 = new B(x3,y3,z3);
}
I am trying to create a n-body simulator in Java while also learning OOP.
I want to have a file that contains all physical constants and physics formulas and I want to use these in other classes when calculating forces etc
Should this file be a regular class with all variables static, an interface or an abstract class, or something else? I am quite confused with all the definitions.
In your case I would create a class named Physics or something of that nature. Inside this class you can then accomplish all of the things you want to do by creating static methods and static variables, as JayC667 has pointed out. It should look something like this:
public class Physics {
public static final int GRAVITY_ACCELERATION = 9.58;
public static double formula(double x, double y) { ... }
// etc.
}
Then, to utilize this class from a different one, you simply reference the variables and use the methods like so:
System.out.println("Acceleration of Gravity = " + Physics.GRAVITY_ACCELERATION);
double speed = Physics.formula(23.5, 840);
You use interfaces to force classes (implementing those interfaces) to have defined methods (defined in the interface) you can can ensure basic functionality, while all the classes can be totally different in all other regards.
In an interface, you only define the method signature (return value, name, parameter types). These are purely abstract.
Since Java 8, interfaces can also contain default methods, that may contain code, but can be overridden by the implementing classes.
Best example is the Comparable interface. You can use that for Numbers, Strings, and any other classes that should be comparable (usually to their own class instances aka objects).
Abstract classes are a mixture of regular classes and interfaces. They contain code and member variables, but can also contain abstract methods. When a class extends an abstract base class, they need to implement the abstract methods at some point.
The normal classes do not have any abstract methods.
This is a question Java-developers usually fight over. General rules of thumb are the following:
If you use a static field, always make it final and never try to mutate it.
If you need a mutable field, create a non-static field.
If possible, initialise the field in the constructor and mark it final.
Methods are static only if they access no non-static fields (ie. they do not have a context), there is no need to abstract over them
(for example in a test case) and they are completely functional (this should
be implied by the fact that no static field is mutable). A good example is Math.sqrt(), where the square root operation does not have a context, does not mutate the state of your application and you never want to abstract over it. In all other cases use a non-static method. Some people completely avoid static methods.
Interfaces are most useful when your classes interact with one another. You can specify certain common functionalities available in a group of classes in your application. Then if some of your code requires these functionalities, you can use them without knowing the actual implementation. Say, you handle shapes in a method and want to know the area of a shape. You may have many shapes and you can retrieve the area without knowing the exact type (circle, triangle etc.).
In general, try not to overuse inheritance. Follow the substitution principle: only use inheritance if the superclass could always be substituted by the subclass.
For example: in OOP a square with variable slides is not a rectangle with variable slides, because for rectangles you are allowed to call setSide(20, 30), while for squares you are not (the two sides must match). Note: if you use final fields which are initialized in the constructor, as suggested earlier, this problem is automatically solved and you are free to inherit square from rectangle.
In your case, I would create utility classes with static methods/fields for common functionalities that do not have a context, such as calculating a formula with given input parameters. The actual bodies could be objects with common interface or abstract parent class.
This is some simple example of how you could do it.
Please ignore the aerial resistance part, didn't really think about that, some movements may be funny :-)
import java.util.ArrayList;
/**
* Contains constants and convenience methods
* #author JayC667
*/
class Globals {
static public final float GRAVITY_ACC = -9.81f; // meters per second²
static public float getTotalSpeed(final float pSpeedX, final float pSpeedY) {
return (float) Math.sqrt(Math.pow(pSpeedX, 2) + Math.pow(pSpeedY, 2));
}
static public float getDistanceBetweenObjects(final PhysicalObjectInterface pObj1, final PhysicalObjectInterface pObj2) {
final float distX = pObj2.getPosX() - pObj1.getPosX();
final float distY = pObj2.getPosY() - pObj1.getPosY();
return getTotalSpeed(distX, distY); // coincidentally same as average speed :-)
}
static public String toString(final PhysicalObjectInterface pObject) {
return pObject.getClass().getSimpleName() + "\tX=" + pObject.getPosX() + "\tY=" + pObject.getPosY();
}
}
interface PhysicalObjectInterface {
default boolean collidesWith(final PhysicalObjectInterface pOther) {
final float distance = Globals.getDistanceBetweenObjects(this, pOther);
return distance < getRadius() + pOther.getRadius();
}
float getPosX();
float getPosY();
float getSpeedX();
float getSpeedY();
float getMass();
float getRadius();
float getAerialResistanceCofactor();
void calcNextCycle();
}
/**
* Does most of the simple work
* #author JayC667
*/
abstract class PhysicalObjectABC implements PhysicalObjectInterface {
private float mPosX;
private float mPosY;
private float mSpeedX;
private float mSpeedY;
public PhysicalObjectABC(final float pPosX, final float pPosY, final float pSpeedX, final float pSpeedY) {
mPosX = pPosX;
mPosY = pPosY;
mSpeedX = pSpeedX;
mSpeedY = pSpeedY;
}
#Override public float getPosX() {
return mPosX;
}
#Override public float getPosY() {
return mPosY;
}
#Override public float getSpeedX() {
return mSpeedX;
}
#Override public float getSpeedY() {
return mSpeedY;
}
#Override public abstract float getMass();
#Override public abstract float getAerialResistanceCofactor(); // could also derive this from radius
// getRadius is not repeated here, but still is abstract and has to be defined in the implementing subclass
#Override public void calcNextCycle() {
final float gravForceY = getMass() * Globals.GRAVITY_ACC; // F = m * a
final float aerialResistForceX = -Math.signum(mSpeedX) * (float) (Math.pow(mSpeedX, 2) * getAerialResistanceCofactor());
final float aerialResistForceY = -Math.signum(mSpeedY) * (float) (Math.pow(mSpeedY, 2) * getAerialResistanceCofactor());
final float totalForceX = aerialResistForceX;
final float totalForceY = gravForceY + aerialResistForceY;
final float accX = totalForceX / getMass(); // a= F / m;
final float accY = totalForceY / getMass(); // a= F / m;
mSpeedX += accX;
mSpeedY += accY;
mPosX += mSpeedX;
mPosY += mSpeedY;
}
#Override public String toString() {
return Globals.toString(this);
}
}
class Stone extends PhysicalObjectABC {
public Stone(final float pPosX, final float pPosY) {
super(pPosX, pPosY, 0, 0);
}
#Override public float getRadius() {
return 0.1f;
}
#Override public float getMass() {
return 1;
}
#Override public float getAerialResistanceCofactor() {
return 0.2f;
}
}
class Leaf extends PhysicalObjectABC {
public Leaf(final float pPosX, final float pPosY) {
super(pPosX, pPosY, 0, 0);
}
#Override public float getRadius() {
return 0.1f;
}
#Override public float getMass() {
return 0.003f;
}
#Override public float getAerialResistanceCofactor() {
return 0.95f;
}
}
class StaticObject implements PhysicalObjectInterface {
private final int mPosX;
private final int mPosY;
private final int mRadius;
public StaticObject(final int pPosX, final int pPosY, final int pRadius) {
mPosX = pPosX;
mPosY = pPosY;
mRadius = pRadius;
}
#Override public float getPosX() {
return mPosX;
}
#Override public float getPosY() {
return mPosY;
}
#Override public float getSpeedX() {
return 0;
}
#Override public float getSpeedY() {
return 0;
}
#Override public float getMass() {
return 0;
}
#Override public float getRadius() {
return mRadius;
}
#Override public float getAerialResistanceCofactor() {
return 0;
}
#Override public void calcNextCycle() { /* ignore, does not move */}
#Override public String toString() {
return Globals.toString(this);
}
}
public class PhysicsEngine {
static private ArrayList<PhysicalObjectInterface> sObjects = new ArrayList<>();
public static void main(final String[] args) {
sObjects.add(new Leaf(10, 100));
sObjects.add(new Stone(20, 100));
sObjects.add(new Leaf(30, 100));
sObjects.add(new Stone(40, 100));
sObjects.add(new StaticObject(30, 100, 1)); // lantern
sObjects.add(new StaticObject(40, 100, 5)); // tree
for (int cycle = 0; cycle < 1000; cycle++) {
simulateCycle(cycle);
printData(cycle);
checkCollisions(cycle);
try {
Thread.sleep(1000);
} catch (final InterruptedException e) { /* ignore */}
}
}
private static void simulateCycle(final int pCycle) {
System.out.println("Simulating cycle #" + pCycle);
for (final PhysicalObjectInterface o : sObjects) {
o.calcNextCycle();
}
}
private static void printData(final int pCycle) {
System.out.println("Printing cycle #" + pCycle);
for (final PhysicalObjectInterface o : sObjects) {
System.out.println("\t" + o);
}
}
private static void checkCollisions(final int pCycle) {
System.out.println("Checking for collisions in cycle #" + pCycle);
final ArrayList<PhysicalObjectInterface> destroyedItems = new ArrayList<>();
for (final PhysicalObjectInterface o1 : sObjects) {
for (final PhysicalObjectInterface o2 : sObjects) {
if (o1 == o2) continue; // ignore IDENTICAL, not equal, items
if (o1.collidesWith(o2)) {
System.out.println("CRASH!\n\tObject 1 (" + o1 + ") \ncollides with \n\tObject 2 (" + o2 + ")");
destroyedItems.add(o1);
destroyedItems.add(o2);
}
}
}
sObjects.removeAll(destroyedItems); // can't delete within loop, would invalidate iterators or migh also f*** up loop indices
}
}
So I've seen, in many places, calling methods of a class like:
SomeClass obj = new SomeClass();
obj.addX(3).addY(4).setSomething("something").execute();
I don't think I completely understand how that works. Is each method independent of each other, so the above is equal to:
obj.addX(3);
obj.addY(4);
obj.addSomething("something");
obj.execute();
Or are they designing their class structure in some other fashion that allows for this. If they are how are they designing their classes to support this?
Also, does that have a specific name? Or is this just calling methods on a class?
That would be method chaining. It can do one of two things.
Each call to a method returns this which allows you to continue to call methods on the original instance.
public class SomeClass
{
private int _x = 0;
private int _y = 0;
private String _something = "";
public SomeClass addX(int n)
{
_x += n;
return this;
}
public SomeClass addY(int n)
{
_y += n;
return this;
}
public SomeClass setSomething(String something)
{
_something = something;
return this;
}
// And so on, and so on, and so on...
}
Each method call returns a new instance of the class with everything copied/updated appropriately. This makes the class immutable (so you don't accidentally modify something that you didn't mean to).
public class SomeClass
{
private int _x = 0;
private int _y = 0;
private String _something = "";
public SomeClass(int x, int y, String something)
{
_x = x;
_y = y;
_something = something;
}
public SomeClass addX(int n)
{
return new SomeClass(_x + n, _y, _something);
}
public SomeClass addY(int n)
{
return new SomeClass(_x, _y + n, _something);
}
public SomeClass setSomething(String something)
{
return new SomeClass(_x, _y, something);
}
// And so on, and so on, and so on...
}
Some people have also mentioned Fluent Interfaces. Fluent Interfaces utilize method chaining to create an API that provides something along the lines of a Domain Specific Language which can make code read much more clearly. In this case, your example doesn't quite qualify.
they modify object's state and return the same object back mostly
class Number{
int num;
public Number add(int number){
num+=number;
return this;
}
}
you can call it like
new Number().add(1).add(2);
most of the time the use case is to return new Object to support immutability
Each of those methods return an instance. For example, the call to
obj.addX(3)
will return the same instance obj, so the call
obj.addX(3).addY(4)
will be equivalent to
obj.addY(4)
This is called method chaining.
The methods are implemented like this:
public SomeClass addX(int i) {
// ...
return this; // returns the same instance
}
public class Test1 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Test1 abc = new Test1();
abc.add1(10, 20).sub1(40, 30).mul1(23, 12).div1(12, 4);
}
public Test1 add1(int a, int b)
{
int c = a + b;
System.out.println("Freaking Addition output : "+c);
return this;
}
public Test1 sub1(int a, int b)
{
int c = a - b;
System.out.println("Freaking subtraction output : "+c);
return this;
}
public Test1 mul1(int a, int b)
{
int c = a * b;
System.out.println("Freaking multiplication output : "+c);
return this;
}
public Test1 div1(int a, int b)
{
int c = a / b;
System.out.println("Freaking divison output : "+c);
return this;
}
}
Suppose I have a class
public class Test{
Point[] pq = null;
public Test(int Capacity) {
Point[] pq = new Point[Capacity];
}
public static void main(String[] args) {
Point point = new Point(); // suppose it has a given state `state` equal to 0
Test test = new Test(1);
test.pq[0] = point; // here test[0] has a `state` equal to 0
point.state = 1 //Suppose now I change the `state` of the point instance variable to 1
}
...}
public class Point{
public Integer state = 0;
...
}
I changed the state of the point instance variable to 1
then test.pq[0].state is now equal to 1. How can I prevent my code from this behavior ?
Edit 1, in the Point class, I added getter and setters and turned public Integer state into private Integer state = 0, I added this
public void copy(Point point){
this.setState(point.getState())
}
when I call Test test = new Test(1); test.pq[0].copy(point);, I still get te same problem
The clean way to avoid this problem is to make the Point class immutable:
public final class Point
private final int state;
public Point(int state) {
this.state = state;
}
public int getState() {
return state;
}
// no setter !
}
That way, nobody can modify the state of a point, and everything is safe.
If the point needs to be mutable, and you don't want to let callers modify the state of the points of your Test, then you'll have to make copies:
public class Test {
private Point point; // it would be the same with an array or a list
public class Test(Point p) {
// defensive copy
this.point = new Point(p.getState());
}
public Point getPoint() {
// defensive copy
return new Point(p.getState());
}
}
Or course, if your Test has a list or array of points, and if you make the array or list of points accessible from the outside, you can't guarantee anything. That's why every modification should go through a method of the test (that's what encapsulation is all about):
public void addPoint(Point p) {
pointList.add(new Point(p.getState());
}
Consider the following case:
class A {
int x;
int y;
}
class B extends A {
int z;
}
Now, somewhere in the code this classes are used like this:
A objA = getAFromSomewhere();
B objB = null;
And in a certain situation I want to do something like
objB = objA; // can't do this
objB.z = someZ;
Of course the real objects are a bit more complicated, so it's not just about copying two ints. But they aren't overly complex either.
I know I can write a constructor for B like this:
public B(A anA) {
this.a = anA.a;
this.b = anA.b;
this.z = 0;
}
But if that's really the only way, I prefer merging the additional members of B into A.
update considering the answers
My question was not clear enough. I understand that objB = objA; can't work (thus I asked for "something like", meaning something with comparable code complexity) and I know about the issues with shallow vs deep copies.
What I was looking for is a possibility to copy the members of a base class (let's say using clone()). You may understand that copying every member manually is a bad solution as it adds complexity and redundancy to the code. Thanks for your replies anyway!
There's no trivial solution to this because there's no one-size-fits-all solution. Basically you don't have all the information within a B, so you can't guarantee you would have a "sensible" B object.
You probably just want to create a constructor in B which takes an A and copies all the A data into the new B.
If you're not scared of commons-beanutils you can use PropertyUtils
import org.apache.commons.beanutils.PropertyUtils;
class B extends A {
B(final A a) {
try {
PropertyUtils.copyProperties(this, a);
}
catch (Exception e) {
}
}
}
There is a (relatively) trivial solution!
Implement a constructor in class B that takes an instance of class A and copies the fields.
One of the reasons there's no generic solution in the language itself is because of the problem of deep copying.
For example, if the source object contains further Objects, as opposed to plain types, what would the generic copy operator do? Just copy the reference (giving a shallow copy), or make real copies?
What then if one of those objects is a Collection? Should it also copy every element of the collection, too?
The only logical conclusion would be to perform a shallow copy, but then you haven't really got a copy at all.
Perhaps you could do this:
class A {
int x;
int y;
A(A a) {
this.x = a.x;
this.y = a.y;
}
}
class B extends A {
int z;
B(A a) {
super(a);
z = 0;
}
}
You're still listing every field, but only once per class.
I am shocked too. :)
You really cannot do this: objB = objA;.
Because Renault and BMW are cars but not all cars are BMW.
Thank about A as Car, B as BMW.
Now you say:
Car car = new Renault();
BMV bmv = car; // you cannot do this. This is exactly your case.
...not because this is what people should do but more because I felt like a challenge, here is some test code which does a simple copy of the objects (using setter and getter methods):
import java.lang.reflect.Method;
import org.junit.Test;
public class ObjectUtils {
#Test
public void test() {
A a = new A();
B b = new B();
a.setX(1);
a.setY(2);
this.copyProperties(a, b);
}
private void copyProperties(Object obja, Object objb) {
Method m[] = obja.getClass().getDeclaredMethods();
for(int i=0;i<m.length;i++) {
try {
String name = m[i].getName();
if(name.startsWith("get") || name.startsWith("is")) {
Class rtype = m[i].getReturnType();
String setter = name.replaceFirst("^(get|is)","set");
Class s = objb.getClass();
Method method = s.getMethod(setter,rtype);
Object[] args = new Object[1];
args[0] = m[i].invoke(obja);
method.invoke(objb,args[0]);
}
} catch(Exception e) {
e.printStackTrace();
}
}
}
class A {
int x;
int y;
/**
* #return the x
*/
public int getX() {
return x;
}
/**
* #param x the x to set
*/
public void setX(int x) {
this.x = x;
}
/**
* #return the y
*/
public int getY() {
return y;
}
/**
* #param y the y to set
*/
public void setY(int y) {
this.y = y;
}
}
class B extends A {
int z;
/**
* #return the z
*/
public int getZ() {
return z;
}
/**
* #param z the z to set
*/
public void setZ(int z) {
this.z = z;
}
}
}
If you do not need full functionality of A, there is also an option to create class B, holding internal copy of A instance and implementing some minimal subset of methods via C interface by proxying them to instance.
class A implements IC {
int x;
int y;
public C() {
...
}
}
class B implements IC {
private A _a;
public B(A a) {
_a = a;
}
public C() {
_a.C();
}
}
Assuming that your class A has a very neat and clean setter and getter method naming convention like
setXXX(Object xxx) and corrresponding getXXX() which returns the same thing (Object xxx ) as a param passed to setXXX()
I have written a utility method using reflection
public static B createSubclassInstance(A a) throws SecurityException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{
Method[] aMethods = Class.forName("package.A").getDeclaredMethods();
B b = new B();
for (Method aMethod : aMethods) {
String aMethodName = aMethod.getName();
Class param = aMethod.getReturnType();
if (methodName.startsWith("get")){
String setterMethodName = methodName.replaceFirst("get", "set");
Method bMethod = Class.forName("package.B").getMethod(setterMethodName);
Object retValA = aMethod.invoke(a,null);
bMethod.invoke(b,retValA);
}
}
return b;
}
If you change your method to create B objects, you can just do what you want using:
objB = (B) objA;
objB.z = someZ;
This can even be inlined, but you need parentheses:
((B) objA).z = someZ;
If not, you have to go the long way using constructors:
objB = new B(objA);
objB.z = someZ;
In this case I would recommend to copy the fields of the superclass in the superclass. Else, if you add a field to that class later, you may forget to change the copying more easily.
class A {
int x;
int y;
public A(A objA) {
x = objA.x;
y = objA.y;
}
}
class B extends A {
int z;
public B(A objA) {
super(objA);
}
}
I prefer merging the additional members of B into A.
You can do this if your classes A and B share the same package or if the variables in your A class are declared as protected. Then you can just access the fields of the superclass.
class A {
protected int x;
protected int y;
}
class B extends A {
int z;
void merge(A a){
super.x = a.x;
y = a.y; // you do not *need* to use the super keyword, but it is a good hint to
// yourself if you read your program later and might wonder ‘where is
// that y declared?’
}
}
Useage, of course, is:
objB = new B();
objB.merge(objA);
objB.z = someZ;
I think best way is to use a factory method to create B objects from A objects.
class BFactory
{
public static B createB(A a)
{
B b = new B();
copy(a,b);
return b;
}
private static <X,Y> void copy(X src,Y dest) throws Exception
{
List<Field> aFields = getAllFields(src.getClass());
List<Field> bFields = getAllFields(dest.getClass());
for (Field aField : aFields) {
aField.setAccessible(true);
for (Field bField : bFields) {
bField.setAccessible(true);
if (aField.getName().equals(bField.getName()))
{
bField.set(dest, aField.get(src));
}
}
}
}
private static List<Field> getAllFields(Class type)
{
ArrayList<Field> allFields = new ArrayList<Field>();
while (type != Object.class)
{
Collections.addAll(allFields, type.getDeclaredFields());
type = type.getSuperclass();
}
return allFields;
}
}