【问题标题】:Why do reference data types point?为什么引用数据类型指向?
【发布时间】:2015-03-26 16:54:37
【问题描述】:

考虑:

我知道对于原始数据类型,分配的内存(橙色矩形)包含您想要的东西,但对于引用数据类型,分配的内存包含指向您想要的东西的引用/指针。

为什么要这样设计?对于通常是引用数据类型(对象、数组等)的东西,为什么不把你想要的东西放在橙色矩形中呢?

【问题讨论】:

  • 如果事物存储在橙色矩形内而不是指向它的指针,则不可能在多个对象之间共享同一个橙色矩形。只有副本可以过去。
  • 这当然是一种设计选项(C++ 为堆栈上的值做这件事),但它不是 Java 采用的。人们可以争论这是否是最好的选择,但他们就是这样做的。

标签: java pointers types reference reference-type


【解决方案1】:

那个橙色矩形有多大?

对于基元,您已经知道大小。但是对象呢?对于具体的最终类,您已经知道将使用多少内存......但是其他情况呢?

例如:

InputStream x = new FileInputStream("foo");

如果变量x 必须包含所有对象的字段(并且知道它是什么类型),那么它必须足够大以容纳所有FileInputStream 字段。好的,在这种情况下,我们可以做到这一点,尽管 InputStream 变量的大小由其用法定义有点奇怪。这个呢:

InputStream x = getInputStream("foo");

编译器不知道getInputStream 会返回什么类型的对象——那么它怎么知道x 会有多大呢?当x 的值是一个引用时,它就简单多了——不管它所引用的对象的实际类型如何,它的大小都是一样的。

当然,您希望能够在该对象的各个“用户”之间共享对象,这就是使用引用变得非常有效的地方。 (我们不必在每次传递值时都复制所有字段——我们只需复制引用。)将对象视为值而不是引用会极大地改变语义。例如:

// A simple mutable type with get/setValue doing the obvious thing
MutableType x = new MutableType();
x.setValue(5);
MutableType y = x;
x.setValue(10);
System.out.println(y.getValue());

对于引用,这会打印 10,因为 xy 只是对同一个对象的引用。使用值类型语义,大概它会打印 5 。并非不合理 - 但语言的工作方式发生了很大变化。

除此之外还有其他问题,但我认为这已经足够开始了:)

当然,C++ 可以解决所有这些问题,但 Java 的设计者认为只对所有非原始类型使用引用会更简单。

【讨论】:

  • 这是正确的,因为它暗示了 OOP 最重要的方面之一,即类型替换。
  • InputStream 的例子是有道理的,但是您通常不知道要为一个对象分配多少空间吗?就像我做String name一样,它不知道要分配多少空间,因为类型是String
  • 您能否详细说明何时要共享对象?我有一个模糊的想法,但我有点困惑。
  • @AdamZerner String 就是一个很好的例子。你为它分配了多少空间? 10个字? 100? 1000?
  • @AdamZerner:这就是为什么我说它对于具体的最终类是可行的——但根据我的经验,这只是变量的一小部分。让语言始终如一地处理所有内容会导致设计更加简洁。
【解决方案2】:

如果我们将对象直接存储在内存盒中,那么就不可能有多个引用指向同一个对象。如果我想做一些事情,比如将它作为参数传递给方法,这是有问题的。这会创建一个对该对象的新引用,并将其传入,从而允许该方法对其进行操作。如果对象实际上在内存盒中,则必须传入一个副本,这 a) 会占用比所需更多的内存空间,并且 b) 意味着函数中所做的更改不会影响原始对象,只会影响原始对象。复制。

例如,如果对象实际上在内存盒中而不是引用中,则以下代码将不起作用。

public class blah{
    private ArrayList<String> array = new ArrayList<String>();

    // if the object resided directly in memory, this method would do nothing of use
    // as it would only make changes to the copy it was passed, rather than the original.
    public void add Value(ArrayList<String> array, String value){
        array.add(value);
    }

}

【讨论】:

    猜你喜欢
    • 2012-05-19
    • 1970-01-01
    • 1970-01-01
    • 2020-12-22
    • 1970-01-01
    • 1970-01-01
    • 2010-10-02
    • 2017-12-20
    相关资源
    最近更新 更多