Click here to Skip to main content
13,201,940 members (68,692 online)
Click here to Skip to main content
Add your own
alternative version

Tagged as

Stats

2.8K views
2 bookmarked
Posted 2 Oct 2017

How to Call Overridden Function in Java and .NET

, 2 Oct 2017
Rate this:
Please Sign up or sign in to vote.
Technique of calling overridden methods from Java and C#

Introduction

Object-oriented programming is a good thing, but sometimes it drives you crazy. For example, you have overridden some method in the class. How can you call the original method? Well, you can use super in Java or base in .NET to access the overridden method from your class. But what if you’d like to access the original method from another class?

In this case, you usually have to provide an additional method to retrieve the original value.

Call Overridden Function

Let’s investigate some important example: the functionObject.hashCode() in Java or Object.GetHashCode() in .NET play twofold role in both platforms: on the one hand, it allows to put effectively any object in some collection, on the other hand, the original value of the object’s hashcode is an identity of the object itself. When we put the object into a collection, we usually override hashCode()/GetHashCode() to represent the internal state of the object. To extract original hashcode Java and .NET provide special functions: System.identityHashCode and RuntimeHelpers.GetHashCode functions respectively.

We will take hashCode()/GetHashCode() method and examine it in more details.

Let’s MyClass overrides Object’s hashcode to be 1:

In Java:

public class MyClass {
  public int hashCode() {
     return 1;
  };
}

In .NET:

public class MyClass{
  public override int GetHashCode() {
     return 1;
  }
}

If we have an instance of the MyObject, how can we get the hashcode for original Object class not using System.identityHashCode in Java or RuntimeHelpers.GetHashCode in .NET.?

For the first try, the problem looks trivial.

Object obj = new MyObject();
int hc = obj.hashCode();

Well, the hc-value is 1 because public methods in Java are virtual (if not final).

Let’s try to get Object’s hash-code using reflection:

MyObject obj = new MyObject();
Method m = Object.class.getMethod("hashCode");
int hc = (int) m.invoke(obj);

Alas, the hc- value is still 1. It means, that although we took the Method from Object.class, it invokes the Method of MyObject class: virtual methods in action!

Here, we used Java code, the .NET code is essentially the same and produces the same results.

For the second try, the problem looks unsolvable: the method was overridden and it seems impossible to obtain its original value (that’s why System.identityHashCode() function exists). And this is true for JDK-5 and 6.

From JDK-7, we have powerful reflection methods which can solve this enigma.

Let’s look at this function:

private static MethodHandle getMethodHandle(Class<?> objClass) throws ReflectiveOperationException {
  Class<?> parentClass = objClass.getSuperclass();
  Lookup lookup = getLookup(objClass);
  return lookup.findSpecial(parentClass, "hashCode", MethodType.methodType(int.class), objClass);
}

Here, we do the following:

  • Create the appropriate object of Lookup class (see the implementation of getLookup(..) function
  • Call findSpecial method of this class

The MethodHandle object for hashCode function is created. After that, we called its invoke() method and viola, the correct result is received.

The .NET implementation is even more direct:

    private delegate int HashCodeDelegate();

...
    MethodInfo handle = objClass.BaseType.GetMethod("GetHashCode");
    IntPtr ptr = handle.MethodHandle.GetFunctionPointer();
    var hashCodeFun = (HashCodeDelegate)Activator.CreateInstance(typeof(HashCodeDelegate), obj, ptr);
    var hashCode = hashCodeFun();

Results

Java:

Hashcode: 1, Object Hashcode:685325104, Identity Hashcode: 685325104

.NET:

Hashcode: 1, Object Hashcode: 46104728, Identity Hashcode: 46104728

In a different environment, one can see different values for Object Hashcode and Identity Hashcode, but always Object Hashcode is the same as Identity Hashcode.

The idea in .NET was provided in [2], I modified the solution a bit to match GetHashCode function.

Acknowledgements

The author is grateful to Ilia Reznik and Alex Rafalovich for useful comments and recommendations.

Reference

  1. Oracle documentation for MethodHandle
  2. Stack overflow: how to call base.base.method()? (for .NET)

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Vladimir Kolmanovitch
Software Developer (Senior)
Israel Israel
I am a software developer living in Netanya (Israel).
I began to program more than 35 years ago in the times of punch-cards and continue to work in this area specializing in Java, C# and C++

You may also be interested in...

Comments and Discussions

 
QuestionWhat's the objective, here? Pin
John Brett9-Oct-17 6:04
memberJohn Brett9-Oct-17 6:04 
Questionbase.GetHashCode()? Pin
Brian Hetrick3-Oct-17 5:17
memberBrian Hetrick3-Oct-17 5:17 
AnswerRe: base.GetHashCode()? Pin
Vladimir Kolmanovitch3-Oct-17 9:16
memberVladimir Kolmanovitch3-Oct-17 9:16 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.171020.1 | Last Updated 2 Oct 2017
Article Copyright 2017 by Vladimir Kolmanovitch
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid