Java: Calling super.getClass() from subclass - java

I know this question has been already asked here, but I fail to understand the "Why" part.
Let us take the following example:
public class First {
First() {
System.out.println(super.getClass());
}
}
public class Second extends First {
Second() {
System.out.println(super.getClass());
}
}
public class Third extends Second {
Third() {
System.out.println(super.getClass());
}
}
When I instantiate an Object of type Third:
public class Main {
public static void main(String[] args) {
Third third = new Third();
}
}
The output is:
class Third
class Third
class Third
And what I expected was (Thinking that super.getClass() should return the name of parent class):
class java.lang.Object
class First
class Second
Which shows that I don't understand how does Inheritance actually work in Java. Kindly help me in getting the right concept in my head.
EDIT
My actual intention was to understand how inheritance actually works (which has been explained very well by Jeff), instead of getting the expected output.
This doubt arose when I was trying to the understand why the following code worked (More specifically, why does super.equals(point3d) worked as it has been passed an object of type Point3D)
public class Main {
public static void main(String[] args) {
Point3D p1 = new Point3D(1, 2, 3);
Point3D p2 = new Point3D(1, 2, 3);
System.out.println(p1.equals(p2)); // Output: true
}
}
public class Point {
private int x;
private int y;
public Point() {
this.x = 0;
this.y = 0;
}
public Point(int x, int y) {
this.x = x;
this.y = y;
}
#Override
public boolean equals(Object object) {
if (object != null && object.getClass() == this.getClass()) {
Point point = (Point) object;
return point.x == this.x && point.y == this.y;
} else {
return false;
}
}
}
public class Point3D extends Point {
private int z;
public Point3D() {
this.z = 0;
}
public Point3D(int x, int y, int z) {
super(x, y);
this.z = z;
}
#Override
public boolean equals(Object object) {
if (object != null && object.getClass() == this.getClass()) {
Point3D point3D = (Point3D) object;
return super.equals(point3D) && point3D.z == this.z; // Had doubt here
} else {
return false;
}
}
}

It is important to recognize that there is exactly one object here with one reference. It can be tempting to present it as though the superclass is a separate instance of Second residing within your instance of Third, but it is not true; there is no way to refer to that instance because it does not exist.
To be clear: It is not the case that within Third there is a hidden instance of Second to which super refers, and within Second there is a First, and within First there is an Object. Instead, there is a single object that is able to behave as an Object, First, Second, or Third. Regardless of the type of the local variable or reference ("static type"), the instance itself has a "runtime type", which is Third.
The only thing super can do for you is to deliberately invoke a member that belongs to a superclass (JLS 15.11.2) that may be hidden by overriding or naming. This does nothing here, because getClass() is a final method declared on Object. getClass has documentation that it "Returns the runtime class of this Object" (docs). There can be no varying implementation, so you will always receive the type Third as you do in your question.
UPDATE: Unlike getClass, equals is non-final, and can be overridden. Point.equals ensures that the Class returned by getClass is equal, and that x and y are equal. Rather than writing an entirely different implementation of equals, Point3D defers to the Point's definition of equals and additionally checks that the z field is equal, which works because Point checks that object.getClass() == this.getClass(), not that object.getClass() == Point.class. It could not do this simply by calling equals, because that would use the Point3D.equals implementation; instead it has to call super.equals to see how Point would calculate equals.
However, I hope this is an example in a lesson, because polymorphism asserts that a Point3D is-a Point and can do whatever a Point can do (see the Liskov Substitution Principle). For Point and Point3D, this could be misleading: You could write a method double distanceBetween(Point a, Point b) that works as expected using 2D points but gives an incorrect result when using 3D points. In real environments, you'll need to be careful about what your class hierarchies and what they imply.

getClass() is a method on Object. There's not a separate one for each of your subclasses. If you want to go up the chain like that, call getSuperclass() on the result of getClass().

Related

Can anyone give me a solution to my task with Generics and Comparable interface?

I wrote half of it but cannot get it 100% correct. Can anyone help me with it?
Here is my problem:
Write a parameterized class Triple that represents a trio of some type (eg, the Three of String, the Integer , etc.). For Triple class define:
-getElement method that receives an integer number (1,2 or 3) and returns the corresponding member. In the case of an illegal argument, throw an IllegalArgumentExpression exception
-setElement that receives two arguments: an integer number (1, 2 or 3) and the value to be placed as a member of the three in the corresponding position (eg, setElement(2,3) sets 3 to y value of trio)
-a constructor with 3 arguments that set the initial values of the Triple
Then you should write the ComparableTriple class, which represents the triplet. Members of triplet must be comparable (implement Comparable interface). Then expand the ComparableTriple class to implement the Comparable interface, so that triplets can be comparable by positions. For example ,(2,6,1) is in the rank before (3,4,5) but behind (2,6, -4). Same template can be applied to String etc.
Example of main code:
Triple t1 = new ComparableTriple<>(2, 6, 1);
int x = t1.compareTo(t1); // should be 0
//Triple class I wrote
public class Triple<T> {
T x, y, z;
public Triple(T x, T y, T z) {
this.x = x;
this.y = y;
this.z = z;
}
public T getElement(int position) {
if (position == 1) {
return x;
} else if (position == 2) {
return y;
} else if (position == 3) {
return z;
} else throw new IllegalArgumentException();
}
public void setElement(int position, T value) {
if (position == 1) {
x = value;
} else if (position == 2) {
y = value;
} else if (position == 3) {
z = value;
} else throw new IllegalArgumentException(); }
}
I tried writing ComparableTriple overriding CompareTo method but couldn't find the exact solution.
It's not so complicated but I'm new to Generics and can't figure some things out.
Can anyone help me about the rest of code?
public class Triple<T> implements Comparable<Triple<T>> {
... your code here
// functional interface Comparable will force you to override the method
}
But you may want to have some kind of superclass that T extends so you can access fields for the compare.
Example:
public class Triple<T extends Number> implements Comparable<Triple<T>>
There is of course the inline compare with Collections.sort(comparable) if you don't want to commit to what T is.
That should get you started. Post back/edit if you get stuck.
Cheers.
(And this is not a solution by intent). Generics are a pain and need to be slogged through to get good at.

Java: Accessing Subclass Methods from a Array of Parent objects

I'm trying to create a program that starts with a Piece class. For the purpose of the exercise every other class extends Piece. The other classes contain methods for moving the pieces, either one space or n spaces.
All of the pieces are stored in a 2D array which the use to move around.
My problem is that if i make an array of Pieces I cannot access the move methods as they are stored in the subclasses. I also can't just cast the object because i have 4 different types that the user can ask to move.
This is the code that adds a piece to the board
//adds a piece based on given type, but only if the space is clear (null)
public void addpiece(String type, String n, String c, int x, int y){
if(board[x][y] == null){
if(type == "FastFlexible"){
board[x][y] = new FastFlexiblePiece(n,c,x,y);
}
else if(type == "FastPiece"){
board[x][y] = new FastPiece(n,c,x,y);
}
else if(type == "SlowFlexible"){
board[x][y] = new SlowFlexiblePiece(n,c,x,y);
}
else if(type == "SlowPiece"){
board[x][y] = new SlowPiece(n,c,x,y);
}
else{
System.out.println("Invaild type");
}
}
}
And this is the code that tries to move the piece, the error I get is because the parent Piece doesn't have a move method, but I can't figure out a way to get the pieces to cast correctly
//Move a piece, two method one for fast and one for slow
public void movePiece(int x, int y, String direction){
if(board[x][y] != null){
if(board[x][y].getType().equals("SlowPiece")){
board[x][y] = board[x][y].move(direction);
}
else if(board[x][y].getType().equals("SlowFlexible")){
board[x][y] = board[x][y].move(direction);
}
}
}
There is another similar method for fast pieces.
Constructor for the slowPiece:
//Constructor
public SlowPiece(String n, String c, int x, int y){
super(n,c,x,y);
this.setType("SlowPiece");
}
But the code doesn't notice what type any of the Pieces are and so I can't cast them correctly
The very aim of Polymorphism is to avoid writing code like the implementation specified for public void movePiece(int x, int y, String direction){.
board[x][y] can refer to SuperType Piece and any of its SubTypes like the SlowPiece, SlowFlexible, FastPiece, FastFlexible. Piece can have the abstract move behavior specified in the definition of the class, without having to provide the implementation. All the SubTypes of Piece class provide their own implementation for move method.
The method public void movePiece(int x, int y, String direction) would simply boil down to this :
public void movePiece(int x, int y, String direction){
board[x][y].move(direction);
}
At runtime, move method is dynamically dispatched depending upon the SubType of Piece class.
My suggestion is to add an abstract method to the parent Piece class.
public class Piece{
public abstract void move();
}
NOTE: now you can't directly instantiate a Piece. This code is illegal:
Piece p = new Piece();

Super class reference to a sub class object?

Give me a situation where we need to use the super class reference to a subclass object in Java.Please give me a real time example.
Thx
I know this is old but this cropped up on a project I've been working on recently (just a junior developer doing something unexpected - there was no actual reason for it!) and I think some of the answers have missed the point..
This has nothing to do with normal polymorphism; I think the question relates to the case where the code looks like this:
class A {
B b; //odd reference here..
}
class B extends A {
}
Where the sub-class is used in the definition of the super-class. As far a I can tell there is no legitimate reason for coding something like this yourself, however the reason the language allows you to do this is that it's required for some of the core Java classes e.g. Object.
For example, although it doesn't store a reference to it, the code for Object creates and returns a String object in it's default toString method, however, String is a sub-class of Object.
It's interesting to note that although it's technically allowed, it doesn't make sense to have a superclass create a subclass instance in its constructor.
e.g.
class A {
B b;
A(){
b = new B();
}
}
class B extends A {
}
This will just crash due to the fact that it creates an infinite loop, since B's constructor is calling A's constructor, which is calling B's constructor etc..
To Take Full Advantage of polymorphism...You have to understand polymorphism fully for you to really appreciate this... You can actually achieve the same behavior using an Interface as appropriate, so they say...
abstract class Shape {
abstract double getArea();
}
class Rectangle extends Shape{
double h, w;
public Rectangle(double h, double w){
this.h = h;
this.w = w;
}
public double getArea(){
return h*w;
}
}
class Circle extends Shape{
double radius;
public Circle(double radius){
this.radius = radius;
}
public double getArea(){
return Math.PI * Math.sqrt(radius);
}
}
class Triangle extends Shape{
double b, h;
public Triangle(double b, double h){
this.b = b;
this.h = h;
}
public double getArea(){
return (b*h)/2;
}
}
public class ShapeT{
public static void main(String args[]){
//USAGE
//Without polymorphism
Triangle t = new Triangle(3, 2);
Circle c = new Circle(3);
Rectangle r = new Rectangle(2,3);
System.out.println(t.getArea());
System.out.println(c.getArea());
System.out.println(r.getArea());
//USAGE with Polymorphism
Shape s[] = new Shape[3];
s[0] = new Triangle(3, 2);
s[1] = new Circle(3);;
s[2] = new Rectangle(2,3);
for(Shape shape:s){
System.out.println(shape.getArea());
}
}
}
I hope I'm not wrong on this... just a thought!
That question doesn't seem quite right ... putting an explicit reference to a child-class in the parent-class seems like an intent to break the hierarchy and the library.
As soon as the parent-class starts to carry a reference to the child-class, the parent-class is dependant upon knowing it's descendants; that is bad.
Unless the question was misquoted here, I'd say your interviewer was talking through his hat.
class Person
String hairColor = "default_noColor";
-----------------------------
class German extends Person
String hairColor = "brown";
-----------------------------
class Scandinavian extends Person
String hairColor = "red";
-----------------------------
public static void main(String args[]) {
Person p = new Person();
German g = new German();
Scandinavian s = new Scandinavian();
sysout p.hairColor // prints default_noColor
if (cond1) {
p = g;
}
sysout p.hairColor // prints brown
else if (cond2) {
p = s;
}
sysout p.hairColor // prints red
}
now, if germans start having black hair, i recompile class German and the main() is totally agnostic of how the German has changed. The main method continues to work as if nothing ever happened and prints black.
Kindly excuse minimal grammar and syntax
Using this kind of assignment you can not call the overloaded method in the subclass which is not in super class.
public class Reference {
public static void main(String args[]){
A a = new B();
//B b = new A(); // You can not do this, compilation error
a.msg(); // calls the subclass method
((B)a).msg("Custom Message"); // You have to type cast to call this
System.out.println(a.getClass());
if(a instanceof B){//true
System.out.println("a is instance of B");
}
if(a instanceof A){//true
System.out.println("a is instance of A also");
}
}
}
class A{
public void msg(){
System.out.println("Message from A");
}
}
class B extends A{
public void msg(){//override
System.out.println("Message from B");
}
public void msg(String msg){//overload
System.out.println(msg);
}
}
Uh, any time? If you have something like a polymorphic linked list:
class Node {
has 'next' => ( isa => 'Node' );
}
class TextNode extends Node {
has 'text' => ( isa => 'Str' );
}
class ImageNode extends Node {
has 'image' => ( isa => 'Image' );
}
Then you can do:
TextNode->new(
text => 'Here is my cat:',
next => ImageNode->new(
image => 'nibbler.jpg',
next => undef,
),
);
Your specific situation involves Node holding a reference to TextNode or ImageNode, which is probably fine in Java:
Node->new( next => TextNode->new ( ... ) )
Though I would make Node a role in languages with that feature... the idea is largely the same.
The Liskov substitution principle states that subclasses should behave exactly like their superclasses, so you can substitute a subclass anywhere the superclass is used.
Here's an important and most instructive example: java.lang.reflect.Array:
The Array class provides static methods to dynamically create and access Java arrays.
getLength(Object array)
Returns the length of the specified array object, as an int.
get(Object array, int index)
Returns the value of the indexed component in the specified array object.
set(Object array, int index, Object value)
Sets the value of the indexed component of the specified array object to the specified new value.
Arrays are passed around as Object, which is the superclass of all array types. It's necessary because we're doing reflection: we don't always know what the array type will be at compile time.
It's really rather odd because the type of situation where it might be useful (supplying a custom implementation of a singleton object for instance) has better alternatives to that; in particular the service loader mechanism.
And outside the world of globals in disguise you do tend to run into issues with circular references. (Consider that the super reference within your sub-class field points to the enclosing super instance which in turn is a reference from within the sub-class ...)
I think this can happen if the class and its subclass share child parent relationship of some sort and the child has a reference to its parent, something like this
public interface Node
{
String getName();
int getValue();
Container getParentContainer();
}
public interface Container extends Node
{
Set<Node> getChildren();
}
I would be interested to see how this can be designed in a better way to resolve this.

JUnit theory for hashCode/equals contract

The following class serve as generic tester for equals/hashCode contract. It is a part of a home grown testing framework.
What do you think about?
How can I (strong) test this class?
It is a good use of Junit theories?
The class:
#Ignore
#RunWith(Theories.class)
public abstract class ObjectTest {
// For any non-null reference value x, x.equals(x) should return true
#Theory
public void equalsIsReflexive(Object x) {
assumeThat(x, is(not(equalTo(null))));
assertThat(x.equals(x), is(true));
}
// For any non-null reference values x and y, x.equals(y)
// should return true if and only if y.equals(x) returns true.
#Theory
public void equalsIsSymmetric(Object x, Object y) {
assumeThat(x, is(not(equalTo(null))));
assumeThat(y, is(not(equalTo(null))));
assumeThat(y.equals(x), is(true));
assertThat(x.equals(y), is(true));
}
// For any non-null reference values x, y, and z, if x.equals(y)
// returns true and y.equals(z) returns true, then x.equals(z)
// should return true.
#Theory
public void equalsIsTransitive(Object x, Object y, Object z) {
assumeThat(x, is(not(equalTo(null))));
assumeThat(y, is(not(equalTo(null))));
assumeThat(z, is(not(equalTo(null))));
assumeThat(x.equals(y) && y.equals(z), is(true));
assertThat(z.equals(x), is(true));
}
// For any non-null reference values x and y, multiple invocations
// of x.equals(y) consistently return true or consistently return
// false, provided no information used in equals comparisons on
// the objects is modified.
#Theory
public void equalsIsConsistent(Object x, Object y) {
assumeThat(x, is(not(equalTo(null))));
boolean alwaysTheSame = x.equals(y);
for (int i = 0; i < 30; i++) {
assertThat(x.equals(y), is(alwaysTheSame));
}
}
// For any non-null reference value x, x.equals(null) should
// return false.
#Theory
public void equalsReturnFalseOnNull(Object x) {
assumeThat(x, is(not(equalTo(null))));
assertThat(x.equals(null), is(false));
}
// Whenever it is invoked on the same object more than once
// the hashCode() method must consistently return the same
// integer.
#Theory
public void hashCodeIsSelfConsistent(Object x) {
assumeThat(x, is(not(equalTo(null))));
int alwaysTheSame = x.hashCode();
for (int i = 0; i < 30; i++) {
assertThat(x.hashCode(), is(alwaysTheSame));
}
}
// If two objects are equal according to the equals(Object) method,
// then calling the hashCode method on each of the two objects
// must produce the same integer result.
#Theory
public void hashCodeIsConsistentWithEquals(Object x, Object y) {
assumeThat(x, is(not(equalTo(null))));
assumeThat(x.equals(y), is(true));
assertThat(x.hashCode(), is(equalTo(y.hashCode())));
}
// Test that x.equals(y) where x and y are the same datapoint
// instance works. User must provide datapoints that are not equal.
#Theory
public void equalsWorks(Object x, Object y) {
assumeThat(x, is(not(equalTo(null))));
assumeThat(x == y, is(true));
assertThat(x.equals(y), is(true));
}
// Test that x.equals(y) where x and y are the same datapoint instance
// works. User must provide datapoints that are not equal.
#Theory
public void notEqualsWorks(Object x, Object y) {
assumeThat(x, is(not(equalTo(null))));
assumeThat(x != y, is(true));
assertThat(x.equals(y), is(false));
}
}
usage:
import org.junit.experimental.theories.DataPoint;
public class ObjectTestTest extends ObjectTest {
#DataPoint
public static String a = "a";
#DataPoint
public static String b = "b";
#DataPoint
public static String nullString = null;
#DataPoint
public static String emptyString = "";
}
One thing to consider: testing an object's conformance to the equals contract should involve instances of other types. In particular, problems are likely to appear with instances of a subclass or superclass. Joshua Bloch gives an excellent explanation of the related pitfalls in Effective Java (I'm reusing duffymo's link, so he should get credit for it) -- see the section under Transitivity involving the Point and ColorPoint classes.
True, your implementation doesn't prevent someone from writing a test that involves instances of a subclass, but because ObjectTest is a generic class it gives the impression that all data points should come from a single class (the class being tested). It might be better to remove the type parameter altogether. Just food for thought.
Joshua Bloch lays out the contract for hash code and equals in chapter 3 of "Effective Java". Looks like you covered a great deal of it. Check the document to see if I missed anything.
Maybe I'm missing something, but the equalsIsSymmetric test is in fact only correctly tested if you have to DataPoints which have the same values (e.g. String a = "a"; String a2 = "a";)
Otherwise this test is only done when the 2 parameters are one instance (i.e. equalsIsSymmetric(a, a);). In fact you test again if equals obey the 'reflective' requirement instead of the symmetric requirement.
The notEqualsWorks(Object x, Object y) theory is false: two distinct instances may still be logically equal according to their equals method; you're assuming instances are logically different if they're different references.
Using your own example above, the two distinct datapoints below (a != a2) are nevertheless equal but fail the notEqualsWorks test:
#DataPoint
public static String a = "a";
#DataPoint
public static String a2 = new String("a");
The equalsWorks(Object x, Object y) method is doing the very same test as equalsIsReflexive(Object x). It should be removed.
I also think that notEqualsWorks(Object x, Object y) should be removed since it prevents one to do the other theories with data points that are equal even thought the whole testing is about having such objects.
Without such data points the reflexivity is the only thing that is tested.

When overriding equals in Java, why does it not work to use a parameter other than Object?

I ran into an interesting behavior recently. It seems that if I override .equals() to take a parameter other than Object, it doesn't get called. Can anyone explain to me why this is happening? It seems to violate my understanding of polymorphism in OOP, but maybe I'm missing something.
Here's much simpler code that shows what I'm seeing:
public class MyClass {
private int x;
public MyClass(int n) { x = n; }
public boolean equals(Object o) { return false; }
public boolean equals(MyClass mc) { return x == mc.x; }
public static void main(String[] args) {
List<MyClass> list = new ArrayList<MyClass>();
list.add(new MyClass(3));
System.out.println("Contains 3? " + list.contains(new MyClass(3)));
}
}
When this is run, it prints "Contains 3? false". It looks like the equals(Object) function is called, even though there is another that would work. By contrast, if I write equals like this the code works as expected:
public boolean equals(Object o) {
if(!(o instanceof MyClass))
return false;
MyClass mc = (MyClass)o;
return x == mc.x;
}
Why isn't it figuring out which version of the function to call based on the type of the parameter?
You're mixing up "overriding" and "overloading".
Overriding -- adding a replacement definition of an existing method for purposes of polymorphism. The method must have the same signature. The signature consists of the name and argument types. Overridden methods are selected at runtime based on the runtime type of the target object.
Overloading -- adding a method with the same name but a different signature. Overloaded methods are selected at compile time based on the compile time type of the target object.
equals(Object) is overriding a super method; you can not override a super method without using the exact same signature (Well, there are some exceptions like covariant returntypes and exception).
Notice that the method you are calling is defined in the javadoc for ArrayList<E> as
boolean contains(Object o)
Returns true if this list contains the specified element.
instead of
boolean contains(E o)
Returns true if this list contains the specified element.
Implementation of ArrayList.java:
private transient Object elementData[];
public boolean contains(Object elem) {
return indexOf(elem) >= 0;
}
public int indexOf(Object elem) {
if (elem == null) {
for (int i = 0; i < size; i++)
if (elementData[i]==null)
return i;
} else {
for (int i = 0; i < size; i++)
if (elem.equals(elementData[i]))
return i;
}
return -1;
}
It uses the equals method defined in the Object superclass since the equals method is not overridden in ArrayList<E>'s implementation.
When overriding Object equals in java, you should override the Object hashCode method as well.
Anyway you might want to try the following code:
class A{
public int content;
A(){
this(0);
}
A(int value){
content = value;
}
public boolean equals(Object obj){
System.out.println("overriding equals method");
return this.content == ((A) obj).content;
}
public boolean equals(A a){
System.out.println("overloading equals method");
return this.content == a.content;
}
public static void main(String[] args){
A x = new A(1);
A y = new A(2);
Object z = new A(1);
System.out.println(x.equals(y));
System.out.println(x.equals(x));
System.out.println(x.equals(z));
//override as z is declared as Object at compile time
//so it will use methods in class Object instead of class A
System.out.println(x.equals((Object) y));
System.out.println(x.equals((Object) x));
}
}
//rant: they didn't teach me these in javaschool and I had to learn it the hard way.
there are different types of http://en.wikipedia.org/wiki/Polymorphism_(computer_science). java does not do http://en.wikipedia.org/wiki/Double_dispatch.
The ArrayList implementation of the contains(Object) method is bound to use Object.equals(Object) method internally, so it'll never know about your overloading of the equals(MyClass) method. Only an overriding method (with matching signature) will be found.
Ok let me re-phrase.
(1)Because the compiler eliminates all information regarding to Generics (erasure, see here), and (2) because you cannot override a method without the exact same signature (equals(Object)), (3) during runtime all objects inside the List are treated as Objects and not as instances of MyClass. Hence, the method that gets called is equals(Object) since this is the one that is been overwritten by your class.
You're assuming that the contains() method in List knows the type of the object at runtime, which is incorrect.
Because of erasure, List<MyClass> becomes just a regular List at runtime, so the contains() method sees its parameter as an Object, thus invoking Object's equals() instead of the one you defined for MyClass in its execution.

Categories