我是靠谱客的博主 迅速母鸡,最近开发中收集的这篇文章主要介绍Java反射解决方法重载_用于调用重载方法的Java反射Area.equals(Area),觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

你的第二个和第三个项目符号(使用X.equals(Object)或回退到Object.equals(Object))不需要任何努力,因为无论如何在调用可覆盖的方法Object.equals(Object)时会发生什么,它将使用它能找到的最具体的重写方法.

因此,唯一剩下的任务是调用X.equals(X)方法(如果适用).要最小化相关成本,您可以缓存结果.从Java 7开始,有一个类ClassValue允许将信息与类相关联,以线程安全,懒惰评估和高效查找方式,仍然支持密钥类的垃圾收集(如果需要).

因此,Java 7解决方案可能如下所示:

import java.lang.invoke.*;

public final class EqualsOperation extends ClassValue {

public static boolean equals(Object o, Object p) {

if(o == p) return true;

if(o == null || p == null) return false;

Class> t1 = o.getClass(), t2 = p.getClass();

if(t1 != t2) t1 = commonClass(t1, t2);

try {

return (boolean)OPS.get(t1).invokeExact(o, p);

} catch(RuntimeException | Error unchecked) {

throw unchecked;

} catch(Throwable ex) {

throw new IllegalStateException(ex);

}

}

private static Class> commonClass(Class> t1, Class> t2) {

while(t1 != Object.class && !t1.isAssignableFrom(t2)) t1 = t1.getSuperclass();

return t1;

}

static final EqualsOperation OPS = new EqualsOperation();

static final MethodHandle FALLBACK;

static {

try {

FALLBACK = MethodHandles.lookup().findVirtual(Object.class, "equals",

MethodType.methodType(boolean.class, Object.class));

} catch (ReflectiveOperationException ex) {

throw new ExceptionInInitializerError(ex);

}

}

@Override

protected MethodHandle computeValue(Class> type) {

try {

return MethodHandles.lookup()

.findVirtual(type, "equals", MethodType.methodType(boolean.class, type))

.asType(FALLBACK.type());

} catch(ReflectiveOperationException ex) {

return FALLBACK;

}

}

}

你可以测试一下

Object[] examples1 = { 100, "foo",

new Area(new Rectangle(10, 20)), new Area(new Rectangle(20, 20)) };

Object[] examples2 = { new Integer(100), new String("foo"),// enforce a!=b

new Area(new Rectangle(10, 20)) };

for(Object a: examples1) {

for(Object b: examples2) {

System.out.printf("%30s %30s: %b%n", a, b, EqualsOperation.equals(a, b));

}

}

从Java 8开始,我们可以在运行时生成功能接口的实例,这可能会提高性能,因为在第一次遇到类型后,我们不再执行任何反射操作了:

import java.lang.invoke.*;

import java.util.function.BiPredicate;

public final class EqualsOperation extends ClassValue> {

public static boolean equals(Object o, Object p) {

if(o == p) return true;

if(o == null || p == null) return false;

Class> t1 = o.getClass(), t2 = p.getClass();

if(t1 != t2) t1 = commonClass(t1, t2);

return OPS.get(t1).test(o, p); // test(...) is not reflective

}

private static Class> commonClass(Class> t1, Class> t2) {

while(t1 != Object.class && !t1.isAssignableFrom(t2)) t1 = t1.getSuperclass();

return t1;

}

static final EqualsOperation OPS = new EqualsOperation();

static final BiPredicate FALLBACK = Object::equals;

@Override

protected BiPredicate computeValue(Class> type) {

if(type == Object.class) return FALLBACK;

try {

MethodType decl = MethodType.methodType(boolean.class, type);

MethodHandles.Lookup lookup = MethodHandles.lookup();

MethodHandle mh = lookup.findVirtual(type, "equals", decl);

decl = mh.type();

BiPredicate p = (BiPredicate)

LambdaMetafactory.metafactory(lookup, "test",

MethodType.methodType(BiPredicate.class), decl.erase(), mh, decl)

.getTarget().invoke();

return p;

} catch(Throwable ex) {

return FALLBACK;

}

}

}

用法与其他变体一样.

这里的一个关键点是可访问性.我假设,你只想支持公共类声明的公共方法.尽管如此,如果越过模块边界,Java 9可能还需要进行微调.为了支持在应用程序代码中声明的自定义X.equals(X)方法,可能需要将自己打开到库中以进行反射访问.

在您的问题的评论中已经讨论了与其他代码(如集合)的相等逻辑不匹配的等式函数的问题.这里,类似的问题,例如,可能会出现IdentityHashMap;小心轻放…

最后

以上就是迅速母鸡为你收集整理的Java反射解决方法重载_用于调用重载方法的Java反射Area.equals(Area)的全部内容,希望文章能够帮你解决Java反射解决方法重载_用于调用重载方法的Java反射Area.equals(Area)所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(36)

评论列表共有 0 条评论

立即
投稿
返回
顶部