String为什么要设置成Final类型

---今天面试碰到个这样的问题: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的规则,导致了此类不安全。

posted on 2018-06-02 13:22  OrangeCsong  阅读(203)  评论(0编辑  收藏  举报

导航