一个看似很简单的问题:当String s = new String("kevin");后内存中有几个对象?
通常回答分两类,一个对象和两个对象。有关两个对象的错误认识是s 和kevin。但是情况似乎并不是那样简单!我们做个测试。我们知道java中 == 比较的是对象的引用是不是相同,就是比较是不是指向同一个对对象,也就是比较是不是同一个对象。我们据此写一小段测试代码:
package com.ys.String;
public class StringTest {
public static void main(String[] args) {
String s0 = new String ("kevin");
String s1 = "kevin";
String s2 = new String ("kevin");
String s3 = "kevin";
if(s0 == s1 ){
System.out.println("s0和s1指向相同的对象");
} else {
System.out.println("s0和s1指向不同的对象");
}
if(s1 == s2) {
System.out.println("s2和s1指向相同的对象");
} else {
System.out.println("s2和s1指向不同的对象");
}
if(s0 == s2) {
System.out.println("s2和s0指向相同的对象");
} else {
System.out.println("s2和s0指向不同的对象");
}
if(s3 == s1 ){
System.out.println("s3和s1指向相同的对象");
} else {
System.out.println("s3和s1指向不同的对象");
}
System.out.println(s0 == s1); //false
System.out.println(s1 == s2); //false
System.out.println(s0 == s2); //false
System.out.println(s1 == s3); //true
System.out.println(s0.equals(s1)); //true
System.out.println(s0.equals(s2)); //true
System.out.println(s0.equals(s1)); //true
System.out.println(s0.equals(s1)); //true
}
}
输出结果如下:
s0和s1指向不同的对象
s2和s1指向不同的对象
s2和s0指向不同的对象
s3和s1指向相同的对象
false
false
false
true
true
true
true
true
由此我们可以得出结论:上面的s0 s1 s2他们指向了不同的对象,他们是不同的对象引用。而s1 s3是相同的对象引用。但是这仍然没有能够回答我们的问题,到底几个对象生成了?造成s0 s1 s2指向不同对象的原因何在?我们需要大概了解java中有关String的内存分配原理。
当执行String s0 = new String("kevin")的时候,会为其创建一个字符串缓冲池(pool)。当创建一个字符串对象的时候其执行流程是这样的:首先他到pool中去寻找是否有一个叫内容为kevin的这样的一个对象存在。因为String s0 = new String("kevin")是main方法的第一条语句此时还没有pool中是没有对象的。此时他会把括号中的kevin对象放到pool中。接下来执行构造方法在堆(heap)中生成一个内容为kevin的对象。所以这样就造成了pool 和 heap中都有一个内容为kevin的对象。这样就解答了我们的问题。我们知道通过 String s0 = new String("kevin") 后,其实产生了两个对象。通过最后四行的代码我们也可以清楚的知道。就是说java中 == 比较的是对象的引用 equals()方法比较的是对象的内容是不是相同。
我们同时注意到在执行 String s1 = "kevin" 后不会有新的对象产生。他首先会到pool中去寻找是否有一个内容为kevin的对象存在,这里找到这样一个对象。他就把引用s1执行pool中的这个对象。所以不会有新的对象产生。同理我们知道s3 和s1指向pool中的同一对象。而执行 String s2 = new String ("kevin") 时,他首先查看pool,发现有一个这样一个内容为kevin的对象存在,那么就不必在pool中创建这样一个对象了。接着他执行构造方法在堆中创建一个内容为kevin的对象,由s2指向。我们要注意的尽管堆中有两个内容为kevin的对象,他们仅仅是内容相同而已,他们的引用是不想同的。
同样的问题如下:
package com.ys.String;
public class StringTest {
public static void main(String[] args) {
String s1 = "kevin";
String s2 = "ke";
String s3 = "vin";
System.out.println(s1 == "ke" + "vin");
System.out.println(s1 == "ke" + s3);
}
}
输出会是如何呢?
true
false
产生这样的原因是:当 + 两边都是字面值(常量)的时候,其连接成一个字符串。在到pool中看是否存在一个内容为kevin的对象。本例中存在,所以返回true;而当 + 号两边有一边不是字面值的时候其会在堆中分配空间。即是说:s1在pool中而“ke” + s3 在堆中。所以返回false。
分享到:
相关推荐
在Java编程语言中,`String`类是使用最频繁的类之一,它代表不可变的字符序列。在本文中,我们将深入探讨`String`类的一些关键方法,这些方法在日常编程中极为常用,有助于字符串的处理和操作。 1. **构造方法**: ...
关于String类的一些问题 掌握String类的两种实例化方式 掌握String的两种比较操作 深入分析String类两种实例化方式的区别 掌握String的使用特点
根据提供的信息,我们可以总结出这份Java基础String类选择题练习题主要聚焦于String及StringBuffer类的使用。尽管具体的题目内容未给出,但从所展示的信息中可以推断出该练习题集涵盖了以下几方面的知识点: ### 一...
关于string类的自定义,如果你对string不了解,可帮助你理解其功能有助于c++的学习
设计string类 要求: 1、为该类定义构造函数,析构函数和赋值操作。构造函数至少应有三个:无参构造函数、C风格字符串构造函数和复制构造函数 2、为string类提供必要的成员函数,可以参考C++类库的string类提供了...
C++标准库中的`std::string`类是处理字符串的重要工具,它提供了丰富的功能,让程序员可以方便地创建、操作和管理字符串。这个简单的`string`类介绍将带我们回顾基础,深入理解其内部机制和常用方法。 首先,`std::...
在Java编程语言中,String类是一个非常基础且重要的部分,它是不可变的,也就是说一旦创建了一个String对象,就不能更改它的内容。然而,许多初学者在学习过程中可能会尝试自己创建一个类似的字符串类,以便更好地...
标题中的“string类的构造方法”揭示了我们要探讨的核心内容——如何初始化和创建`std::string`对象。`std::string`类不仅在日常编程中频繁使用,而且在很多高级功能如正则表达式、文本处理等方面都有重要应用,因此...
String类的常用方法 String类是Java语言中最基本的类之一,用于处理字符串。字符串是一个字符序列,Java中字符串是不可变的,即创建后不能被修改。下面是String类的常用方法: 1. equals()方法:用于判断两个字符...
在C++编程语言中,`std::string` 类是一个非常重要的数据类型,它用于表示和操作文本字符串。这个文档详细地介绍了`std::string`类的各种函数,旨在帮助程序员理解和熟练使用这一强大的工具。以下是对`std::string`...
在C++编程中,自定义`string`类是一项常见的练习,它可以帮助我们深入理解对象、内存管理和操作符重载等核心概念。以下是对这个主题的详细讲解: 首先,`string`类是C++标准库中的一个关键部分,用于处理字符串。...
本文主要介绍了C++中的字符串类函数原型借鉴,通过自定义的String类来实现字符串的操作。下面将对标题、描述、标签和部分内容进行详细的分析和解释。 标题:C++ String 类函数原型借鉴 C++中的字符串操作是非常...
在C++编程语言中,`String`类是一个非常基础且重要的数据类型,它用于处理字符串。C++标准库提供了一个名为`std::string`的类,但在此案例中,我们讨论的是一个自定义的`String`类。创建自己的`String`类通常是学习...
*String类中包括以下函数:* *默认构造函数,带参数构造函数 , 拷贝构造函数 *取字符串函数GetString(),取字符串长度函数GetLength(),查找字串位置函数Find() *重载,>>,[],=,+,> *析构函数 *String类中包括2个...
在这个"链表string类程序"中,我们可以预想它可能涉及到用C++实现链表结构,并结合`std::string`进行字符串的操作。下面将详细介绍`std::string`类以及如何将其与链表相结合。 1. **`std::string` 类基础** `std::...
设计string类 要求: 1、为该类定义构造函数,析构函数和赋值操作。构造函数至少应有三个:无参构造函数、C风格字符串构造函数和复制构造函数 2、为string类提供必要的成员函数,可以参考C++类库的string类提供了...
C++ String 类常用成员函数汇总 C++ 的 String 类提供了多种成员函数来操作字符串,这些成员函数可以分为构造函数、字符操作、特性描述、输入输出操作和赋值五大类。 首先,String 类的构造函数有多种重载版本,...
Java中的`String`类是编程中最常用的类之一,它在Java的`java.lang`包中,无需显式导入即可使用。`String`类代表不可变的字符序列,这意味着一旦创建了`String`对象,它的值就不能改变。这个特性使得`String`在处理...
5.javaString类.zip5.javaString类.zip5.javaString类.zip5.javaString类.zip5.javaString类.zip5.javaString类.zip5.javaString类.zip5.javaString类.zip5.javaString类.zip5.javaString类.zip5.javaString类.zip5....