【问题标题】:Detect if object has overriden toString() [duplicate]检测对象是否已覆盖 toString() [重复]
【发布时间】:2014-05-17 00:15:25
【问题描述】:

我收到一个对象并需要记录它。其中一些有 cusom toString(),然后我想使用它,但有些没有,我得到类似 mightypork.rogue.bus.events.MouseMotionEvent@2d19587d 的东西。

我正在寻找一种方法来动态(可能使用反射?)检查传入对象是否已覆盖 toString()

String objToString(Object o)
{
    if(???) {
        return o.toString();
    } else {
        // fallback method
        return o.getClass().getSimpleName();
    }

}

旁注:

它是一个事件总线系统,一些类可以根据实现的接口订阅然后接收事件。我不可能要求所有客户端都拥有 toString(),而且我想将此方法用于不止一个目的。

【问题讨论】:

  • 如果他们没有自定义实现,你会怎么做?你真的不应该做这样的事情,它围绕多态的目的工作。
  • 我不关心多态性原理,我想要好的日志输出。
  • 然后自己覆盖toString,这就是它的用途!你不控制你的对象吗?
  • 我不想将 toString 添加到所有内容中;我没有时间做那个。它们并不都是数据类。
  • @MightyPork 好吧,这就是我问“你不控制你的对象吗?”的原因。所以,既然答案是否定的,那么我不明白为什么你需要的不仅仅是你得到的对象的类名(如果它们确实有toString),因为你不知道@987654327 是什么@ 无论如何都会代表。

标签: java reflection overriding


【解决方案1】:

如果您使用Object getClass() 方法,您可以使用该类并调用getMethod().getDeclaringClass() 方法。如果它是Object,那么它不会被覆盖。否则,沿线的某处被覆盖。 Source

【讨论】:

  • 目前正在尝试这种方法。
  • 我还没有实际测试过它,所以它必须工作,对@MightyPork?
  • 是的,效果很好。基本上(o.getClass().getMethod("toString").getDeclaringClass() != Object.class) 是我需要的东西。
  • getDeclaredMethods() 只返回在类中声明并且继承的方法。那不是更容易使用吗?
  • @GermannArlington 不,如果我们有类A 覆盖toString 并且我们有类B extends A。如果我们检查B 是否覆盖toString,它会说false 的目标是检查它是否不是来自ObjecttoString
【解决方案2】:

也许有点傻,但你可以试试:

    String objToString(Object o)
{
    if(!(o.toString().contains("@" + o.hashCode()))) {
        return o.toString();
    } else {
        // fallback method
        return o.getClass().getSimpleName();
    }

}

或者只是类似的简化版本:

String objToString(Object o) {
  if (o.toString().equals(
      o.getClass().getName() + "@" + Integer.toHexString(o.hashCode()))) {
    // fallback method
    return o.getClass().getSimpleName();
  } else {
    return o.toString();
  }
}

【讨论】:

  • 可以工作,也许使用更精确的正则表达式,但必须有一种更清洁的反射方式。
  • 是的,这很愚蠢。您将排除任何产生输出的toString() 方法,在您建议的情况下包括“@”以及与任何其他子字符串的任何其他组合
  • @GermannArlington 根据文档可轻松扩展到o.getClass().getName() + '@' + Integer.toHexString(o.hashCode())
  • @GermannArlington 我直接从我的脑海中写作
  • @GermannArlington 如果只检查o.getClass().getName() + '@' + Integer.toHexString(o.hashCode()) 而没有更多,那么问题就没有意义了。要么没有发生覆盖,要么覆盖选择呈现完全相同的信息。
【解决方案3】:

在这里检查你的对象中是否有 toString 方法:

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class TemplateHelper {

    public static void main(String [] args){
        int a = 3;
        try {
            objToString(a);
        } catch (InvocationTargetException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

    public static void objToString(Object object) throws InvocationTargetException, IllegalArgumentException, IllegalAccessException{
        Class c = object.getClass();
        Method[] methods = c.getMethods();
        for (Method method : methods) {
            if(method.getName().equals("toString")){
                System.out.println(method.getName()); //THERE IS toString in object
                break;
            }
        }
    }

}

【讨论】:

【解决方案4】:

以下是您可以使用反射来解决问题的方法。在您使用反射收到的对象中找到toString 方法。如果它是在java.lang.Object 中声明的,则使用您自己的方法。

import java.lang.reflect.Method;
import java.util.Random;

public class ToStringUtils {
    public static String myToString(Object o) {
        if (o == null)
            return "null";
        if (overridesToString(o.getClass()))
            return o.toString();
        // Replacement for Object.toString()
        return o.getClass().getSimpleName() + "@" + System.identityHashCode(o);
    }

    public static boolean overridesToString(Class<?> clazz) {
        Method m;
        try {
            m = clazz.getMethod("toString");
        } catch (NoSuchMethodException e) {
            // Can't be thrown since every class has a toString method through Object
            return false;
        }
        return (m.getDeclaringClass() != Object.class);
    }

    // Small demo
    public static void main(String[] args) {
        System.out.println(myToString(new Integer(5)));
        System.out.println(myToString(new Random()));
    }
}

【讨论】:

    猜你喜欢
    • 2015-08-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-07
    • 1970-01-01
    相关资源
    最近更新 更多