After running a Junit test for user-defined object serialization, it was failed and gave me the results
Expected: com.me.Position#7a92922
Actual: com.me.Position#25618e91
I have defined the following class
public class Position {
private double x;
private double y;
/**
* default constructor
*/
public Position() {
}
/**
* paramterized constructor
*
* #param x
* x-coordinate
* #param y
* y-coordinate
*/
public Position(double x, double y) {
this.x = x;
this.y = y;
}
public double getX() {
return x;
}
public void setX(double x) {
this.x = x;
}
public double getY() {
return y;
}
public void setY(double y) {
this.y = y;
}
}
then I defined another class to serialize and deserialize a Position object which is an instance of the previous class as following
public class PositionSerializer {
static void serialize(Position position, OutputStream outputStream) {
OutputStreamUtil.serializeDouble(position.getX(), outputStream);
OutputStreamUtil.serializeDouble(position.getY(), outputStream);
}
static Position deserialize(InputStream inputStream) {
double x = InputStreamUtil.deserializeDouble(inputStream);
double y = InputStreamUtil.deserializeDouble(inputStream);
Position positionObject = new Position();
positionObject.setX(x);
positionObject.setY(y);
return positionObject;
}
}
Finally, I wrote a unit test as follows
public class PositionSerializerTest {
private InputStream iStream;
private ByteArrayOutputStream oStream;
#Before
public void init() {
oStream = new ByteArrayOutputStream();
}
Position serialzeAndDeserializeObject(Position positionObject) {
PositionSerializer.serialize(positionObject, oStream);
iStream = new ByteArrayInputStream(oStream.toByteArray());
return PositionSerializer.deserialize(iStream);
}
#Test
public void equals_equal() {
Position positionObject = new Position(5.5, 10.5);
Position deserializedPosition = serialzeAndDeserializeObject(positionObject);
assertThat(deserializedPosition).isEqualTo(positionObject);
}
}
what was wrong? and how to fix it?
You are checking reference equality which is not equal because your deserialize method returns new instance on every call, use below for comparing values :
assertThat(deserializedPosition.getX()).isEqualTo(positionObject.getX())
assertThat(deserializedPosition.getY()).isEqualTo(positionObject.getY())
There is nothing wrong,but you are creating a new instance in deserialize method:
Position positionObject = new Position();
This will always call new instance of Position Object and hence you can not compare it using == operator
You should override equals method as below:
public boolean equals(Object o) {
if (o == this) {
return true;
}
if (!(o instanceof Position)) {
return false;
}
Position otherObject = (Position)o;
if(this.x == otherObject.x && this.y == otherObject.y)
return true;
else return false;
}
And then call :
assertThat(deserializedPosition).isEqualTo(positionObject);
It looks like your test is comparing the object references and not the object values. Override the equals function or compare each value in the position object separately.
Related
Let's consider the following simple class.
class Point {
private float x;
private float y;
public Point(float x, float y){
this.x=x;
this.y=y;
}
public float getX(){return this.x;}
public float getY(){return this.y;}
public void setX(float x){this.x=x;}
public void setY(float y){this.y=y;}
#Override
public String toString(){
return ("x = "+this.x+", y = "+this.y+";");
}
#Override
public Point clone(){
return new Point(this.x,this.y);
}
#Override
public boolean equals(Object object){
if (object != null && object.getClass()==Point.class){
return object.getX()==this.x && object.getY()==this.y;
}
else{
return false;
}
}
The problem is in the rewrite of method equals: I use the general Object class as attribute to make it more flexible, but netbeans prints error on return line: "Object has no method getX" which is perfectly logical.
But the problem is still here, how can I manage to fix this?
Thanks you in advance
This is pretty simple but you need to cast object:
#Override
public boolean equals(Object object){
if (object != null && object.getClass()==Point.class){
Point p = (Point)object;
return p.getX()==this.x && p.getY()==this.y;
}
else{
return false;
}
}
This is also relevant: Casting in equals method
I've written a custom class Graph for my programming problem. However, the getVertex method seems not to work. It should return the Vertex which is saving the Verschiebung object which is given by parameter. I'm returning null when I'm trying to print a correct Vertex adress in the console. I really can't find the problem in this. The 2D array feld is filled with objects of Planquadrat. That class works fine, so I didn't include code snippets from there.
i and j are integers. The declaration isn't shown here.
private Planquadrat[][] feld;
private Graph verschiebungen;
public void erstelleGraph() {
verschiebungen = new Graph();
Vertex neuerVertex1;
neuerVertex1 = new Vertex(new Verschiebung(-1, feld[i][j], feld[i+1][j]));
verschiebungen.addVertex(neuerVertex1);
System.out.println(verschiebungen.getVertex(
neuerVertex1.getVerschiebung()));
}
Here is the class Graph:
public class Graph{
private List<Vertex> vertices;
private List<Edge> edges;
public Graph(){
vertices = new List<Vertex>();
edges = new List<Edge>();
}
public Vertex getVertex(Verschiebung pVerschiebung){
Vertex result = null;
vertices.toFirst();
while (vertices.hasAccess() && result == null){
if (vertices.getContent().getVerschiebung().getVon().equals(pVerschiebung.getVon()) && vertices.getContent().getVerschiebung().getNach().equals(pVerschiebung.getNach())){
result = vertices.getContent();
}
vertices.next();
}
return result;
}
public void addVertex(Vertex pVertex){
vertices.append(pVertex);
}
}
Here is the class Vertex:
public class Vertex{
private Verschiebung verschiebung;
private boolean mark;
public Vertex(Verschiebung pVerschiebung){
verschiebung = pVerschiebung;
mark = false;
}
public Verschiebung getVerschiebung(){
return verschiebung;
}
Here is the class Verschiebung:
public class Verschiebung {
private int menge;
private Planquadrat von, nach;
public Verschiebung (int pMenge, Planquadrat pVon, Planquadrat pNach) {
menge = pMenge;
von = pVon;
nach = pNach;
}
public Planquadrat getVon() {
return von;
}
public Planquadrat getNach() {
return nach;
}
}
On the List class: It is a custom class as well and I can guarantee that it works fine since I have used it a lot. The method append adds a new object to the end of the list. toFirst sets the first object of the list as the current object, next sets the current object one element further. hasAccess returns if there is still a current object.
Here is the implementation of equals() and hashChode() of Planquadrat:
private int x, y;
#Override
public boolean equals(Object o) {
if (o == this) return true;
if (!(o instanceof Planquadrat)) {
return false;
}
Planquadrat p = (Planquadrat) o;
return p.x == x &&
p.y == y;
}
#Override
public int hashCode() {
int hash = 7;
hash = 31 * hash + this.x;
hash = 31 * hash + this.y;
return hash;
}
My class details attributes of restaurants downtown, said attributes being x/y locations and rank. The problem is, whenever I run the program It throws an error, saying that non-abstract class "Downtown" does not override abstract method "compareTo". I cannot make this class abstract because I need to initialise the object outside this block of code. Where does my program go wrong? Is there a problem with my compareTo implementation? Any suggestions will be much appreciated.
public class Downtown implements Comparable<Downtown> {//Throws error on this line
private int x;
private int y;
private int rank;
public Downtown(int x, int y, int rank) {
this.x = x;
this.y = y;
this.rank = rank;
}
//Appropriate setters and getters for x , y and rank
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public int getRank() {
return rank;
}
public void setRank(int rank) {
this.rank = rank;
}
public int compareTo(Downtown p1, Downtown p2)//Actual comparison
{
// This is so that the sort goes x first, y second and rank last
// First by x- stop if this gives a result.
int xResult = Integer.compare(p1.getX(),p1.getX());
if (xResult != 0)
{
return xResult;
}
// Next by y
int yResult = Integer.compare(p1.getY(),p2.getY());
if (yResult != 0)
{
return yResult;
}
// Finally by rank
return Integer.compare(p1.getRank(),p2.getRank());
}
#Override
public String toString() {
return "["+x+' '+y+' '+rank+' '+"]";
}
Java's Comparable<T> interface defines compareTo method as follows:
int compareTo(T o);
This means that the method must take one parameter; the other parameter is the object itself, i.e. this. You need to implement this one-argument method in place of your two-argument method to fix this problem.
Compiler will help you figure out issues like this by using #Override annotation on your method:
#Override // Issues an error
public int compareTo(Downtown p1, Downtown p2)
#Override // Compiles fine
public int compareTo(Downtown other)
The compareTo method should compare the current object (this) to just one other. It shouldn't have two parameters for comparison. You could write your method like this.
public int compareTo(Downtown p2)//Actual comparison
{
// This is so that the sort goes x first, y second and rank last
// First by x- stop if this gives a result.
int xResult = Integer.compare(getX(),p2.getX());
if (xResult != 0)
{
return xResult;
}
// Next by y
int yResult = Integer.compare(getY(),p2.getY());
if (yResult != 0)
{
return yResult;
}
// Finally by rank
return Integer.compare(getRank(),p2.getRank());
}
Notice how I've replace all the calls on p1 to calls on the current object.
I need to create and populate an object inside a method. The only information is the member field name (passed as a string) and the relevant value for that field (passed as an Object). What is the most appropriate design pattern taking into account performance? - reflection, if comes with a penalty, would not be a preferred approach.
Update:
The value to be set comes from an object that acts as a generator of the values having a set of methods that return the proper value for the specific field. E.g. for member Double x; it would be generator.getX()
A simple function to copy all the getters to all the available setters is as follows. With some more work you can cache this information and speed it up but it is likely to be fast enough as it is.
public static <T> T copyTo(Object from, T to) {
for(Method m : to.getClass().getMethods()) {
if (!m.getName().startsWith("set") || m.getParameterCount() != 1)
continue;
try {
Method getter = from.getClass().getMethod("g" + m.getName().substring(1));
m.invoke(to, getter.invoke(from));
} catch (NoSuchMethodException ignored) {
// ignored
} catch (InvocationTargetException | IllegalAccessException e) {
throw new AssertionError(e);
}
}
return to;
}
Note: Only the fields where there is a matching getter and setter will attempt to copy from one to the other.
public static void main(String[] args) {
One orig = new One(1, "hi", 3);
One to = new One();
One copy = copyTo(orig, to);
System.out.println(to);
}
static class One {
int x;
String y;
double z;
public One() {
}
public One(int x, String y, double z) {
this.x = x;
this.y = y;
this.z = z;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public String getY() {
return y;
}
public void setY(String y) {
this.y = y;
}
public double getZ() {
return z;
}
public void setZ(double z) {
this.z = z;
}
#Override
public String toString() {
return "One{" +
"x=" + x +
", y='" + y + '\'' +
", z=" + z +
'}';
}
}
prints
One{x=1, y='hi', z=3.0}
If you want to create an object generically you need to use reflection.
The only alternative is byte code generation which will be much more complex to implement and only save you a fraction of a micro-second.
How many days is it worth sending to implement this to save a micro-second?
If you know the class name of the object then what you can do is:
public Object populate(String className,String fieldName,Object value) throws Exception{
Class clazz = Class.forName(className);
Object o = null;
for(Field f: clazz.getFields()){
if(f.getName().equals(fieldName)){
o = clazz.getConstructor().newInstance();//default constructor if it exists
f.set(o, value);
break;
}
}
return o;
}
EDIT:
Since you know the class(comment under question) then you can use is the function I wrote just with this change and not className parameter:
Class clazz = Class.forName(YourClass.class.getName());
EDIT2:
If I understand the update you are asking about how to know which method to invoke to get the value.
On your generator class you can get the list of methods it has. Then if your method are named getFieldName() you can once you have the field name find the method with the name getFiledName.
Example:
for(Method m:GeneratorClass.class.getMethods()){
System.out.println(m.getName());
//analyze method name and field name to determine which method to call
//..
boolean callThis = true;//result of analysis
if(callThis){
//Object value = m.invoke(obj);
//obj==generator
}
}
I created a digraph using the jgrapht library, and it takes as vertices Pointobjects I created. These objects take as parameters two coordinates and a type. I made a simple and short example:
public static DirectedGraph<Point, DefaultEdge> directedGraph = new DefaultDirectedGraph<Point, DefaultEdge>(DefaultEdge.class);
public static Point firstPoint = new Point(2, 7, "A");
public static Point secondPoint = new Point(2, 8, "B");
public static Point thirdPoint = new Point(2, 9, "B");
public static Point fourthPoint = new Point(2, 4, "C");
void setup () {
directedGraph.addVertex(firstPoint);
directedGraph.addVertex(secondPoint);
directedGraph.addVertex(thirdPoint);
directedGraph.addVertex(fourthPoint);
directedGraph.addEdge(firstPoint, secondPoint);
directedGraph.addEdge(secondPoint, thirdPoint);
directedGraph.addEdge(secondPoint, fourthPoint);
int degree = directedGraph.outDegreeOf(secondPoint);
if (degree >= 2) {
for (Point successor : Graphs.successorListOf (directedGraph, secondPoint)) {
if (/*the iD is equal to B*/){
for (Point predecessor : Graphs.predecessorListOf (directedGraph, secondPoint )) {
directedGraph.addEdge(predecessor, successor);
}
}
}
}
// --------------------------------------------------------------
public static ArrayList<Point> pointList = new ArrayList<Point>();
public static class Point {
public int x;
public int y;
public String iD;
public Point(int x, int y, String iD)
{
this.x = x;
this.y = y;
this.iD= iD;
}
#Override
public String toString() {
return ("[x="+x+" y="+y+" iD="+iD+ "]");
}
#Override
public int hashCode() {
int hash = 7;
hash = 71 * hash + this.x;
hash = 71 * hash + this.y;
return hash;
}
#Override
public boolean equals(Object other)
{
if (this == other)
return true;
if (!(other instanceof Point))
return false;
Point otherPoint = (Point) other;
return otherPoint.x == x && otherPoint.y == y;
}
}
I'd like to add a condition in the if statement on the iD of the vertices, but not on the two other parameters of my Point objects. Is there a way to do this ?
If I understand your question, then yes it's possible. Use the public iD field. Something like,
for (Point successor : Graphs.successorListOf (directedGraph, secondPoint)) {
// if (/*the iD is equal to B*/){
if (successor.iD.equals("B")){
// ...
}
}
You've defined it as a public field. You can access it by using . Just do:
if (successor.iD.equals("B")) {
See: Oracle Tutorial on Class Members