---今天面试碰到个这样的问题:String在设计的时候为什么要设计成final的 当时回答的是String功能已经很丰富了,不需要对其进行扩展,所有巴拉巴拉。
现在来正确看看为什么定义成final的吧
首先,Final来修饰一个类,只有一个作用,就是不让此类被继承。
好,那么String为什么不让其他类继承呢,网上看来看去,最靠谱的说法就是保证安全性,(其实也就是因为String的不可变性。)
先看String内部结构:
public final class String implements java.io.Serializable, Comparable<String>, CharSequence { /** The value is used for character storage. */ private final char value[]; /** The offset is the first index of the storage that is used. */ private final int offset; /** The count is the number of characters in the String. */ private final int count; /** Cache the hash code for the string */ private int hash; // Default to 0 /** use serialVersionUID from JDK 1.0.2 for interoperability */ private static final long serialVersionUID = -6849794470754667710L; 。。。。。。。。。。。。。。。。。。
String里有个成员变量value字符型数组。修饰是private ,final
private保证变量不会被外部和子类直接访问。
final保证变量的值不会变化。
但是这样是没办法保证value不可变,因为value是指向数组的地址,我们可以通过修改数组内容从而达到修改value的目的。
也就是这个原因,String内的value就成了一个不可变的值,所以String不可变的原因就在这里。假如String去掉Final,会导致value变化吗,这问题 ,事实证明,父类的value是不会变化的,那假如子类有个名称一样的成员变量会如何呢?代码如下
package com.zxy.test; import java.awt.*; /** * Created by Roderick on 2017/5/12. */ public class Test2 { /** * 父类要设计成安全的模式 */ static class Base{ private final char[] value = {‘a‘}; public String getString(){ return this.toString(); } public void setString(String str){ System.out.println("数组不能被修改"); } public String toString(){ StringBuilder tmp = new StringBuilder(); for(char c: this.value){ tmp.append(c); } return tmp.toString(); } } static class Child extends Base{ public char[] value; @Override public String getString(){ return this.toString(); } @Override public void setString(String str){ this.value = str.toCharArray(); } @Override public String toString(){ StringBuilder tmp = new StringBuilder(); for(char c: this.value){ tmp.append(c); } return tmp.toString(); } } public static void main(String[] arge){ Base base = new Base(); base.setString("aaaa"); System.out.println(base.getString()); Child child = new Child(); child.setString("aaaa"); System.out.println(child.getString()); } }
上面的代码,已经回答了这个答案,假如子类有个成员变量的名称和value一致,那么value从效果上看,就是被修改了。所以这就导致了子类可变。违背了String的规则,导致了此类不安全。
原文地址:https://www.cnblogs.com/csong7876/p/9125173.html
时间: 2024-11-09 00:34:52