4

我知道堆的 PermGen 区域中字符串池的概念。所以当我们做类似的事情时

String firstString = "Stack";
String secondString = "Stack";

两个引用都firstString指向secondString池中的同一个对象。但是我对int类型的变量尝试了同样的方法。

    int firstInt = 5;
    int secondInt = 5;

    if(firstInt == secondInt) {
        System.out.println("Both point to same allocated memory");
    } else {
        System.out.println("Both point to different allocated memory");
    }

结果是Both point to same object,当我尝试

Integer firstInteger = new Integer(2);
Integer secondInteger = new Integer(2);

    if(firstInteger == secondInteger) {
        System.out.println("Both point to same object");
    } else {
        System.out.println("Both point to different object");
    }

输出是Both point to different object

我对char进行了相同的尝试,结果相似。所以我的问题是我们有所有原始类型的池intcharnew ()当我们实际使用上述第二种情况创建具有相同内容的对象时,该对象是被克隆并存储在同一个池区域中还是在池之外?

4

5 回答 5

11

您的帖子中有很多误解,甚至很难开始解释。找一本像样的书。现在,一些可能对您有所帮助的事实:

  • 字符串不是原始类型,
  • 没有原始类型池,因为不能引用原始类型(说它们只保留在堆栈上的答案是完全错误的!)
  • 如果您使用new,则无论如何都会绕过池;所以执行new String("ala")总是会创建一个新的 String 对象;你不能改变new;的语义
  • 如果您想使用可用的池,对对象使用工厂方法(如Integer.valueOf),它们将在某种程度上池化实例(池化所有可能的值等是不可行或有益的IntegersFloats
于 2013-05-24T14:23:43.077 回答
1

基元不是对象。它们可以直接存储在生成的代码中。

在您的第二个代码块中,您正在测试值的相等性,而不是两个对象相同。

int firstInt = 5;
int secondInt = 5;

if(firstInt == secondInt)
{
    System.out.println("Both point to same object");
    // NO - neither point to an object -- their alues are the same.
}

您可以通过显式使用在多个引用之间共享相同的 Integer 对象Integer.valueOf(int),这可能会为多次调用返回相同的对象。

于 2013-05-24T14:23:11.463 回答
0

如果你试试

if (Integer.valueOf(2) ==Integer.valueOf(2))

你会得到true

使用 .Integer firstInt = new Integer(2)创建一个新的局部变量,该变量!=指向另一个使用 . 创建的局部变量Integer secondInt = new Integer(2)。类型也是如此String

这背后的原因是==检查变量的相等性。变量可能不同(==结果false),即使它们指向两个“相同”的对象。在这种情况下,相同的意思是obj1.equals(obj2)返回true

如果您希望将原始类型的对象表示以及 StringS 存储在PermGen中,则不要使用new关键字,即Integer firstInt = 2;String firstString= "whatevs";因为关键字会在堆上new创建一个对象。

于 2013-05-24T14:24:14.147 回答
0

有时,要回答高级问题,查看源代码就足够了。例如,这里是Integer#valueOf(int i)方法的代码:

public static Integer valueOf(int i) {
    if (i >= IntegerCache.low && i <= IntegerCache.high)
        return IntegerCache.cache[i + (-IntegerCache.low)];
    return new Integer(i);
}

可以通过 vm 选项更改IntegerCache#low值:IntegerCache#high

缓存的大小可以由-XX:AutoBoxCacheMax=<size>选项控制。

于 2017-03-20T09:52:20.343 回答
0

我相信这是一个非常有效的问题,需要回答。对于任何未来的读者, == 操作对 Object 类型和原始类型的工作方式是不同的。

原始类型(int、char、double、long ....)由它们的值评估。而原始包装器(整数、双精度、字符串 ....)实际上是对象而不仅仅是值。

所以当我们使用 Integer 类作为

整数 = 新整数 (10)

在内存中创建了一个新对象,原始数据类型不是这种情况。

== 评估检查内存,以及 Object 类型和原始类型的值,只检查值。

于 2020-07-04T15:48:23.353 回答