Java 中String 类特别之处(不可变?+运算符重载?new String("abc")创建了几个对象?)

1. String 为什么是不可变的?

简要说明下:这个可以看JDK源码。String本质是一个char[]数组。而且用final修饰, 在JDK1.7中,String的成员变量主要有两个。

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {

     /** String本质是个char数组. 而且用final关键字修饰.*/
    /** The value is used for character storage. */
    private final char value[];

    /** Cache the hash code for the string */
    private int hash; // Default to 0
    ....
    ....

final修饰的char[]数组,该引用不可改变,虽然引用不可变。挡不住Array数组是可变的事实。Array的数据结构看下图
这里写图片描述

final int[] value={1,2,3}
int[] another={4,5,6};
value=another; //编译器报错,final不可变

value用final修饰,编译器不允许我们把value指向堆区另一个地址。但如果我直接对数组元素动手,分分钟搞定。

final int[] value={1,2,3};
value[2]=100; //这时候数组里已经是{1,2,100}

但是char数组在源码中是定义为private,私有成员,外部不能访问和更改。所以综上所述 String不可变。

详细分析见
① Java中的String为什么是不可变的? – String源码分析
② 知乎 如何理解 String 类型值的不可变?


2. String s=new String(“abc”)创建了几个对象?

① String s=new String(“abc”)创建了几个对象?
② 面试题之String str = new String(“abc”); 创建了几个对象
③ Java里String a = new String(“abc”);这会在堆和栈里面分别创建对象abc吗?
④ 请别再拿“String s = new String(“xyz”);创建了多少个String实例”来面试了吧


3. String类与常量池

① Java常量池理解与总结
② Java 为什么需要常量池
③ Java中的字符串常量池


4. String 字符串的拼接+是运算符重载吗?

① Java细节:字符串的拼接
② 为什么Java不支持操作符重载?
③ JAVA语法糖“+”运算符


5. String,StringBuilder,StringBuffer三者的区别?

① String:String / StringBuffer / StringBuilder 三者的功能区别
② Java中的String,StringBuilder,StringBuffer三者的区别

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
以下是基和派生的长代码: ```c++ #include <iostream> using namespace std; class TransitPerson { protected: int id; public: TransitPerson(int id) : id(id) {} virtual void getInfo() = 0; virtual ~TransitPerson() {} }; class Tourist : public TransitPerson { private: string name; public: Tourist(int id, string name) : TransitPerson(id), name(name) {} void getInfo() { cout << "Tourist " << name << " with ID " << id << endl; } ~Tourist() {} }; class TruckDriver : public TransitPerson { private: string licensePlate; public: TruckDriver(int id, string licensePlate) : TransitPerson(id), licensePlate(licensePlate) {} void getInfo() { cout << "Truck driver with license plate " << licensePlate << " and ID " << id << endl; } ~TruckDriver() {} }; class BusinessTraveler : public TransitPerson { private: string company; public: BusinessTraveler(int id, string company) : TransitPerson(id), company(company) {} void getInfo() { cout << "Business traveler from " << company << " with ID " << id << endl; } ~BusinessTraveler() {} }; int main() { TransitPerson* transitPeople[3]; transitPeople[0] = new Tourist(1, "John"); transitPeople[1] = new TruckDriver(2, "ABC123"); transitPeople[2] = new BusinessTraveler(3, "XYZ Inc."); for (int i = 0; i < 3; i++) { transitPeople[i]->getInfo(); } delete transitPeople[0]; delete transitPeople[1]; delete transitPeople[2]; return 0; } ``` 这段代码创建了一个抽象基 TransitPerson 和三个非抽象派生 Tourist、TruckDriver 和 BusinessTraveler。每个都有一个唯一的数字标识符 id,并且实现了构造函数、必要的设置和获取方法、析构函数。还添加了赋值运算符重载和输入运算符重载。 在 main 函数创建了一个指向基的指针数组 transitPeople,填充并对该数组进行一定的操作,以及统计每个对象个数。最后,释放了动态分配的内存。 这段代码可以通过继续添加字段和方法来扩展基和派生的功能,也可以对数组执行更多的操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Casionx

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值