-1

I have following two questions:

1) Why am I getting a NullPointerException at the line when I am calling t.i.hashCode()?

2) In what all scenarios is hashCode() method called and not called? (Does it gets calls only in cases where we are using objects of Hashing related classes?)

o/p is null.

Exception in thread "main" java.lang.NullPointerException
                    at Test.hashCode(EqualsHashcode.java:65)
                    at java.util.Hashtable.put(Unknown Source)
                    at EqualsHashcode.main(EqualsHashcode.java:20)
import java.util.*;
public class EqualsHashcode 
{

    public static void main(String[] args)
    {
        //System.out.println("Main Method");
        Test s = new Test("bharat",1);
        Test p = new Test("bharat",1);
        //System.out.println(s);
        //System.out.println(p);
        //System.out.println(s.equals(p));
        Test q = new Test("bharat",2);
        //System.out.println(q);
        //System.out.println(s.equals(q));
        Test r = new Test("bhara",1);
        //System.out.println(r);
        //System.out.println(s.equals(r));
        Hashtable ht = new Hashtable();
        ht.put(s,"1");
        ht.put(p,"1");
    }

}

class Test
{   Test t;
    String p;
    int i;
    Test(String s, int j)
    {
        p=s;
        i=j;
    }

    public String toString()
    {   
        System.out.println(p+".."+i);
        return p+" Hashcode is"+p.hashCode();
    }

    public boolean equals(Object o)
    {   
        if (this==o)
        {
            return true;
        }
else if ( o instanceof Test)
        {               
         t = (Test) o;
            if (this.p.equals(t.p) && this.i==t.i)
                            return true;
            else
                return false;
        }
else

        return false;

    }

    public int hashCode()
    {   

        System.out.println(t);
        System.out.println("Calling hashCode" + " "+ t.p.hashCode()+t.i);
        return t.p.hashCode()+t.i;
    }
}
Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
Bharat Data
  • 11
  • 1
  • 7
  • You had an error in your question: the NPE occurs at `t.p.hashCode()`. `i` is a primitive and [methods cannot be called on primitive](https://stackoverflow.com/a/21748381/4906586). In your `hashcode` method, you are supposed to refer to `p.hashCode()` not `t.p.hashCode()`: `t` refers to another Test (maybe you have your reasons) and is not initialised in your constructor and consequently has a `null` value. Which gives for your `hashCode()` something like: `return p.hashCode() + i;` – Al-un Nov 08 '17 at 08:48
  • change to this.p.hashCode(), remove Test t and t = (Test) o; to a local var. – Stefan LoKran Dotti Nov 08 '17 at 08:51
  • @Al1 ok, and p an instance variable can be called in hashCode() method without Test class object as hashCode() method is itself instance method, am i right ? – Bharat Data Nov 08 '17 at 08:52
  • @StefanLoKranDotti why do i need to remove Test t and t = (Test) o, just changing p.hashCode() works fine, want to know the reason behind removing them please? – Bharat Data Nov 08 '17 at 08:55
  • do you need Test to be an instance field? It is not accessed outside of the equals method. – Stefan LoKran Dotti Nov 08 '17 at 08:57
  • @StefanLoKranDotti - i want to type cast object to Test class only and only if o is an instanceof Test not otherwise in order to avoid ClassCastException. So is there any way in which i can meet the above requirement while declaring Test as an instance field ? I can't think of one – Bharat Data Nov 08 '17 at 08:58
  • @Al1 I think the root cause of your question is that you are getting confused between classes, attributes and instance stuff. Maybe you can have a look on this first. `p` cannot really be called an *instance variable*, `p` is an attribute of `Test` which is initialised in your constructor. As `p` is not null, you can safely call method on this attribute. Consider the hashCode() as a signature (like the signature when you sign an autograph). It is common for a Java Class to have its signature depending on its attribute – Al-un Nov 08 '17 at 08:59
  • The variable `Test t`; defined in your code is null. Thus it throws NullPointerException. Instead using `t.p.hashCode()` and `t.i` in your code, use `this.p.hashCode()` and `this.i.hashCode()` – akshaya pandey Nov 08 '17 at 09:00
  • @Al1 - taking your comment constructively i looked for the said terms to check i am not clear about them but I am pretty clear about them, attributes- static variables (only one copy) and instance variable - multiple copies ( one for each object). So can you please point out what exactly am i missing, please – Bharat Data Nov 08 '17 at 09:17
  • @BharatData I see. Then why do you have a `Test` attribute in your `Test` class? The only usage I see is in your `equals()` methods but that does not justify defining `t` as an attribute of `Test`: you can declare locally in your method. Subsequent question: `hashCode()` is supposed to *express the identity* of a Test class: why do you use the reference of another `Test` class? If I take a basic exemple: my car is red. Let's say the `hashCode()` of my car is the color: why would I express the color of my car based on another car? – Al-un Nov 08 '17 at 09:23
  • @Al1 - got your points, i did made a mistake there, thanks for the support :) – Bharat Data Nov 08 '17 at 09:28
  • @BharatData you're welcomed, glad it helped – Al-un Nov 08 '17 at 09:39
  • @Al1- can you please answer 2nd question also 2) In what all scenarios is hashCode() method called and not called? (Does it gets calls only in cases where we are using objects of Hashing related classes?) – Bharat Data Nov 08 '17 at 09:46

1 Answers1

0

I think it's this what you wanted:

public class EqualsHashcode {

    public static void main(String[] args) {
        Test s = new Test("bharat", 1);
        Test p = new Test("bharat", 1);
        Test q = new Test("bharat", 2);
        Test r = new Test("bhara", 1);
        Hashtable ht = new Hashtable();
        ht.put(s, "1");
        ht.put(p, "1");
    }

}

class Test {
    String p;
    int i;

    Test(String s, int j) {
        p = s;
        i = j;
    }

    public String toString() {
        System.out.println(p + ".." + i);
        return p + " Hashcode is" + p.hashCode();
    }

    public boolean equals(Object o) {
        if (this == o) {
            return true;
        } else if (o instanceof Test) {
            Test t = (Test) o;
            if (this.p.equals(t.p) && this.i == t.i) {
                return true;
            } else {
                return false;
            }
        } else {
            return false;
        }
    }

    public int hashCode() {
        System.out.println(this);
        System.out.println("Calling hashCode" + " " + this.p.hashCode() + this.i);
        return this.p.hashCode() + this.i;
    }
}
  • ok, and p an instance variable can be called in hashCode() method without Test class object as hashCode() method is itself instance method, am i right ? – Bharat Data Nov 08 '17 at 08:57
  • you are right - they are all in the same instance - so you can write "this." – Stefan LoKran Dotti Nov 08 '17 at 08:58
  • i want to type cast object to Test class only and only if o is an instanceof Test not otherwise in order to avoid ClassCastException. So is there any way in which i can meet the above requirement while declaring Test as an instance field ? I can't think of one – Bharat Data Nov 08 '17 at 09:03
  • 1
    I don't get it?! The cast is type safe because of the instanceof before. – Stefan LoKran Dotti Nov 08 '17 at 09:06
  • yes exactly it is safe because of instanceof which forces me to declare Test object t as local, so is there any way in which i can declare Test class t as class level instance variable and avoiding the ClassCastException issue. – Bharat Data Nov 08 '17 at 09:10
  • @BharatData There is no '`ClassCastException` issue', because `instanceof` makes it safe, and there is nothing wrong with declaring local variables, and no requirement for an instance member. Unclear what you're asking. – user207421 Nov 08 '17 at 09:15