String类为什么是final的。

本文探讨了 Java 中 String 类被定义为 final 的原因,主要从提高程序效率和保障安全性两方面进行了深入分析,并解释了这如何影响程序性能。

最佳答案:

主要是为了“效率” 和 “安全性” 的缘故。若 String允许被继承, 由于它的高度被使用率, 可能会降低程序的性能,所以String被定义成final。

其它答案一:

String和其他基本类型不同,他是个对象类型.既然是对象类型,如果是在静态方法下是必须调用静态方法或值的,如果是非静态的方法,就必须要实例化. 
main函数是个static的.所以String要能像其他的基本类型一样直接被调用.这也是为什么在main函数下使用String类型不会报告错误的原因.. 
一下就解释了两个心里的疑问.. 
以前一直觉得奇怪,为什么String是对象类型在main函数下却是不需要实例化的.再次佩服java设计人员想得真周到.

 

其它答案二:

当定义String类型的静态字段(也成类字段),可以用静态变量(非final)代替常量(final)加快程序速度。反之,对于原始数据类型,例如int,也成立。 

例如,你可能创建一个如下的String对象: 

private static final String x = "example"; 

对于这个静态常量(由final关键字标识),你使用常量的每个时候都会创建一个临时的String对象。在字节代码中,编译器去掉”x”,代替它的是字符串“example”,以致每次引用”x”时VM都会进行一次哈希表查询。 

相比之下,度于静态变量(非final关键字),字符串只创建一次。仅当初始化“x”时,VM才进行哈希表查询。 

还有另一个解释: 
带有final修饰符的类是不可派生的。在Java核心API中,有许多应用final的例子,例如java.lang.String。为String类指定final防止了人们覆盖length()方法。 

  另外,如果指定一个类为final,则该类所有的方法都是final。Java编译器会寻找机会内联(inline)所有的final方法(这和具体的编译器实现有关)。此举能够使性能平均提高50%。

示例:

public class Test { 
public static void main(String[] args)  { 
//  



如果String 不是final 那么就可以继承 
public class String2 extends String{ 
   // .. 
   // ... 


那我们的 main也就可以写成 
public class Test { 
public static void main(String2[] args)  { // 注意此处 
//  

}

英文参考:http://forums.sun.com/thread.jspa?threadID=636414

=============================================================

另外补充一点:

引用:http://zhidao.baidu.com/question/94324055.html
作用就是 final的类不能被继承,不能让别人继承有什么好处? 
意义就在于,安全性,如此这般: 
Java自出生那天起就是“为人民服务”,这也就是为什么Java做不了病毒,也不一定非得是病毒,反正总之就是为了安全,人家Java的开发者目的就是不想让Java干这类危险的事儿,Java并不是操作系统本地语言,换句话说Java必须借助操作系统本身的力量才能做事,JDK中提供的好多核心类比如String,这类的类的内部好多方法的实现都不是Java编程语言本身编写的,好多方法都是调用的操作系统本地的API,这就是著名的“本地方法调用”,也只有这样才能做事,这种类是非常底层的,和操作系统交流频繁的,那么如果这种类可以被继承的话,如果我们再把它的方法重写了,往操作系统内部写入一段具有恶意攻击性质的代码什么的,这不就成了核心病毒了么? 
--- 
上面所述是最重要的,另外一个方面,上面2位老兄说的也都很对,就是不希望别人改,这个类就像一个工具一样,类的提供者给我们提供了,就希望我们直接用就完了,不想让我们随便能改,其实说白了还是安全性,如果随便能改了,那么Java编写的程序肯定就很不稳定,你可以保证自己不乱改,但是将来一个项目好多人来做,管不了别人,再说有时候万一疏忽了呢?他也不是估计的,所以这个安全性是很重要的,Java和C++相比,优点之一就包括这一点;
---

原因绝对不只有这么多,因为如果这些个核心的类都能被随便操作的话,那是很恐怖的,会出现好多好多未知的错误,莫名其妙的错误.... 



【转载】http://blog.youkuaiyun.com/fenglibing/article/details/5486449

<think>嗯,用户问为什么Java的Stringfinal的,还有String的存储大小限制。我需要先理解这两个问题,然后根据提供的引用资料来回答。 首先,关于String被设计为final的原因。我记得引用[1]和[2]提到过,Stringfinal的,不能被继承。这样做的好处可能有安全性,比如防止子覆盖方法导致不可预期的行为。比如哈希表之的数据结构依赖String的不可变性,如果String可变,可能会破坏哈希表的键值。另外,不可变性还能让字符串常量池有效工作,多个引用可以共享同一个字符串,节省内存。还有线程安全的问题,因为不可变对象天生是线程安全的,不需要同步。 然后关于存储大小限制。引用[2]提到在JDK1.9之前是char数组,之后改为byte数组加编码标记。不过数组的最大长度应该是Integer.MAX_VALUE,也就是大约2^31-1,但实际可能受虚拟机限制,比如最大数组长度可能稍小一些,比如有的JVM实现可能限制为Integer.MAX_VALUE - 8。另外,String内部使用byte数组,如果使用Latin1编码每个字符占1字节,而UTF-16的话可能占2或4字节,这会影响实际存储的字符数量。不过用户可能想知道的是理论上String能有多长,比如字符数,但实际可能会抛出OutOfMemoryError,或者超过数组长度限制的错误。 需要确认引用中的信息。引用[1]说从JDK9开始用byte数组加编码标记,引用[2]中的代码示例显示char数组,但可能是在JDK8的情况。因此,存储结构的变化可能影响存储大小,但基本还是受数组长度限制。 可能还需要补充一些例子,比如当尝试创建非常大的字符串时,可能会遇到内存不足的问题,或者超过数组长度限制的错误,比如抛出java.lang.OutOfMemoryError: Java heap space或者java.lang.NegativeArraySizeException之的异常。 然后用户的问题可能还涉及到设计决策的原因,比如为什么选择用final,除了安全性、不可变性的好处,还有性能优化,比如字符串常量池的存在,因为字符串不可变,所以可以缓存哈希值,提高效率。 总结下来,回答的结构应该是先解释为什么Stringfinal,列举几个主要原因,每个原因结合引用中的内容。然后解释存储大小限制,包括理论上的数组长度限制和实际中的内存限制,可能还要提到不同JDK版本的变化。</think>### Java String设计为final的原因及存储大小限制分析 #### 一、String设计为final的主要原因 1. **安全性保障** String作为Java核心,广泛用于文件路径、网络连接、哈希表键值等场景。若可被继承,恶意子可能通过覆写方法破坏安全性,例如在`equals()`中注入非法逻辑[^1][^4]。 2. **不可变性的核心实现** final修饰确保String的不可变性: - **线程安全**:无需同步即可多线程共享[^1][^4] - **哈希值缓存**:`hash`字段可预计算并复用,提高哈希表性能[^2] - **字符串常量池优化**:相同字面量共享同一内存,减少重复创建[^1][^4] 3. **性能优化基础** 不可变性使编译器可进行字符串常量折叠(如`"a"+"b"`优化为`"ab"`),同时避免因内容修改引发的意外行为[^1][^4]。 #### 二、字符串存储大小限制 1. **理论限制** String内部使用`byte[]`存储数据(JDK9+),数组最大长度为`Integer.MAX_VALUE - 8`(约21亿),实际限制取决于具体JVM实现[^1][^2]。 2. **实际限制** - **内存约束**:字符串占用内存需满足`byte[]长度 × 元素字节数 + 对象头开销`,超大字符串会触发`OutOfMemoryError` - **编码影响**:Latin1编码时每个字符占1字节,UTF-16编码时基本字符占2字节,扩展字符占4字节[^1] 3. **典型错误示例** ```java // 尝试创建超长字符串 char[] arr = new char[Integer.MAX_VALUE]; // 抛出java.lang.OutOfMemoryError String s = new String(arr); ``` #### 三、设计延伸验证 ```java // 验证字符串不可变性 String s1 = "Hello"; String s2 = s1.concat(" World"); System.out.println(s1); // 输出"Hello"(原值未改变) System.out.println(s2); // 输出"Hello World" ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值