【问题标题】:Java_why print member variable give actual value?Java_为什么打印成员变量给出实际值?
【发布时间】:2017-11-08 17:25:26
【问题描述】:
class Customer {
    public String name;

    public Customer(String name) {
        this.name = name;
    }
}

public class Main {
    public static void main(String[] args) {
        Customer c = new Customer("Sally");
        System.out.println(c);
        System.out.println(c.name);
    }
}
  • 这是一个简单的问题,我们都知道输出结果,但有一个问题
  • 请看上面的代码和这里的图片Passing Value

  • 问题:

    1. 如果我打印出这样一个对象的引用:System.out.println(c);,IDE 将为我生成一个内存地址:Customer@60e53b93
    2. 但是,在视频教程中(截图见图片链接Passing Value

,该对象有一个成员变量,它是一个字符串的 reference -> "Sally",为什么当我执行 System.out.println(c.name) 时,试图打印出一个 reference(name),它给出了一个真正的字符串对象t("Sally")。 不应该打印一个真正的Object("Sally")的内存地址吗???

【问题讨论】:

  • 这个Customer@60e53b93和内存无关,只是对象的hashcode
  • 没有。它在哪里说应该?视频教程的图片不足以证明您的信念,或者可以作为此处帖子的一部分。
  • 不,如果您的 Customer 类有一个 toString() 方法,它会使用它。
  • 我知道兄弟,但是,我想说的是我正在打印一个对真实对象的 reference,为什么它会给出一个字符串对象“Sally”,只是比如,打印一个对象客户的reference,它会给出一个内存地址...
  • @EJP 对不起兄弟,我只是想弄清楚堆栈和堆的实际工作原理,这就是我在 YTB 上搜索视频的原因

标签: java object memory memory-management heap-memory


【解决方案1】:

第一个问题答案:- 1.out是System Class中PrintStream的静态变量。 在 System 类中声明为

   public final static PrintStream out = null;

当你打电话给System.out.println((Object)c); 它在内部调用PrintStrem 类的println 方法。 PrintStream类中println方法的实现如下:-

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

通过这段代码,很明显 out 将调用 String ValueOf 方法。 和 String 类中 ValueOf() 方法的实现如下:-

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

2.String 类有 Override Object 类的 toString 方法如下:-

    /**
     * This object (which is already a string!) is itself returned.
     *
     * @return  the string itself.
     */
    public String toString() {
       return this;
     }

对象类中的toString() 方法:-

  /**
   * Returns a string representation of the object. In general, the
   */
public String toString() {
    return getClass().getName() + "@" + Integer.toHexString(hashCode());
}

您的类Customer 没有覆盖Object 类的toString() 方法,因此当您调用System.out.println(c); 时,它将调用Object 类的toString 方法。那就是你将得到Customer@60e53b93 作为输出。

【讨论】:

    【解决方案2】:

    System.out 是类PrintStream 的对象。 PrintStream.println() 调用 String.valueOf() 获取对象。而String.ValueOf(object) 调用 object.toString()。 对于字符串,PrintStream.println() 打印出字符串。至于 Customer 类,您默认使用 Object.toString() 导致打印 Customer@ 字符串。

    【讨论】:

      【解决方案3】:

      注意:println()System 类中的重载方法。当你打电话时

          Customer c = new Customer("Sally");
          System.out.println(c);
      

      这将调用以对象为参数的println() 方法。如果您参考documentation,您将看到:

      public void println(Object x)
      

      打印Object,然后终止该行。此方法调用 首先String.valueOf(x) 获取打印对象的字符串值,然后 表现得好像它调用了print(String),然后是println()

      参数: x - 要打印的对象。

      当你调用println(c.name)时,name是一个String变量,这将调用以String为参数的println()方法:

      System.out.println(c.name);
      

      documentation:

      println

      public void println(String x)
      

      打印String,然后终止该行。该方法表现为 虽然它调用print(String),然后调用println()

      参数: x - 要打印的字符串。

      另请参阅:q1this q2

      【讨论】:

        猜你喜欢
        • 2014-08-29
        • 1970-01-01
        • 2021-03-10
        • 2011-11-25
        • 1970-01-01
        • 2014-01-08
        • 1970-01-01
        • 1970-01-01
        • 2022-08-18
        相关资源
        最近更新 更多