【问题标题】:Change default return of an object in Java在Java中更改对象的默认返回
【发布时间】:2015-03-11 02:17:02
【问题描述】:

Java 中对象的默认返回是返回 toString 方法,有没有办法改变这种行为,例如返回数字或其他类型,或者这只是语言中不可更改的核心组件?

Test test = new Test();
blankMethod(test);

我不确定为什么人们说我的假设是错误的...如果我重写对象的 toString 方法,它将输出新的 toString 方法...

@Override
public String toString() {
    System.out.println("This method is run when the object is used as a parameter");
    return "test";
}

【问题讨论】:

  • 你的假设是错误的。引用类型的值是对对象的引用的值。另外,有一个重载的println 方法,它接受Object 类型的参数并调用其toString 方法。
  • "The default return of an object in Java is to return the toString method" -- 你在哪里找到这些信息的?
  • 您对PrintStream#println(...) 的作用感到困惑,即在对象上调用toString(),具有对象的固有属性。这是两个完全不同的东西。
  • 可以通过摆脱不好的前提来改进它,并提供有关 CodeCamper 试图实现的更多信息。
  • 在我的评论中,应该是"You're ..."。呃。

标签: java


【解决方案1】:

Java中对象的默认返回是返回toString方法

PrintStream.println 就是这样工作的。 java 中的任何对象都扩展了java.lang.Object,因此继承了Object 的行为。特别是,任何以Object 为参数的方法,也可以接受其他类型的任何对象。但是,您可以覆盖在Object 中定义的任何publicprotected 方法。在您的情况下,您应该覆盖Test 类中的toString() 方法,否则如果您将Test 对象传递给PrintWriter.println(),它将使用超类中的toString(在您的情况下为Object)。所以,如果我正确理解了您的问题,答案是

更新:您的术语是错误的。 java中没有对象的默认返回。返回Object.toString 是仅PrintStream.println(Object) 的默认行为。

Update2:更广泛地说,Java 不支持隐式类型转换,但 upcasting 除外。在您的情况下,Test 扩展了 Object,但它没有扩展 String(实际上,String 是最终的,因此您不能扩展它)。因此,如果您尝试将Test 对象传递给只接受String 的方法,则会出现编译错误,因为StringTest 属于类层次结构的不同分支。

【讨论】:

  • 如果你创建一个空白方法并传入对象,我很确定它仍然运行 toString 方法。
  • 如果你将Test 对象传递给只接受String 的方法,你会得到编译错误。没有隐式的toString() 调用。
  • 你是对的,这真的很奇怪......当你传递一个对象参数时,每个对象的默认行为是通过toString返回一个字符串......但你不能隐式返回一个对象即使我无法更改它,也需要一个字符串,并且每个对象在请求对象时都必须返回一个字符串......对我来说不是很合乎逻辑......
  • 没什么奇怪的。你说的是automatic type convertion。所以,答案很简单:java 不支持隐式类型转换,除了向上转换。
【解决方案2】:

你真的在打电话

PrintStream.println(Object x)

而不是

public void println(String x)

PrintStream.println(Object x) 的实现如下:

public void println(Object x) {
     String s = String.valueOf(x);
     synchronized (this) {
        print(s);
        newLine();
    }
}

该方法调用String.valueOf(x),其实现如下:

public static String valueOf(Object obj) {
   return (obj == null) ? "null" : obj.toString();
}

注意Object.toString() 方法正在被调用。

隐式转换注意事项

仅在调用字符串连接运算符 (+) 时,使用 toString 方法将 Object 隐式转换为 String。更确切地说,转换工作如下:

原始类型 T 的值 x 首先被转换为引用值...

然后通过字符串转换将这个引用值转换为String类型。 现在只需要考虑参考值。

如果引用为null,则转换为字符串“null”(四个 ASCII 字符 n、u、l、l)。否则,执行转换 好像通过调用被引用对象的 toString 方法 没有论据;但是如果调用 toString 方法的结果 为null,则使用字符串“null”。

toString 方法由原始类 Object 定义

Java Language Specification 15.18.1

扩展隐式转换概念的一种(多种语言)是 Scala,它允许将转换(例如,A -> B)带入作用域,然后每当某种类型(A)作为需要不同类型 (B) 时的参数。

【讨论】:

  • 我不认为这是正确的,因为在我更新的问题中使用了我的覆盖方法。您将看到 toString 方法始终在运行。当您将对象用作任何参数时。
  • 这个答案也与文档相矛盾。最终,转换由String.valueOf(Object) 完成:“如果参数为null,则返回一个等于”null”的字符串;否则,返回obj.toString() 的值。”。在这种情况下,它不为空。
  • 我在解释,但由于它造成混乱,我会更新答案。
  • @CodeCamper 我更新了我的答案,希望能澄清一下。我扩展了 Java 和其他语言的隐式转换。
【解决方案3】:

这回答了“为什么人们说我的假设是错误的”。

这是一个简单的程序:

public class Test {
  public String toString(){
    return "I am a Test object.";
  }

  public int add(int a, int b){
    return a+b;
  }
  public static void main(String[] args) {
    Test object = new Test();
    System.out.println(object);
    System.out.println(object.add(2,2));
    System.out.println(adder(object));
  }

  public static int adder(Test test){
    return test.add(3,5);
  }
}

输出:

I am a Test object.
4
8

System.out.println 方法必须以一种或另一种方式将其参数转换为字符串。如果它被传递一个对象引用,它使用它的 toString() 方法。如果它被传递一个原语,例如int 表达式,它会以适当的方式对其进行转换。

这与返回的内容无关。

它也与将引用作为参数传递时的任何自动转换无关。请参阅输出的第三行,这取决于使用我传递给adderTest 引用作为Test,而不是String

如果您想更改 println 打印的内容,请执行我在上面所做的操作,然后传递一些不同的内容。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-04-05
    • 2019-08-28
    • 1970-01-01
    • 1970-01-01
    • 2022-11-03
    • 2011-10-22
    • 2013-10-11
    • 1970-01-01
    相关资源
    最近更新 更多