• 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的规则,导致了此类不安全。

  • 相关阅读:
    【AHOI2009】 维护序列
    Codeforces Hello 2019 F. Alex and a TV Show[bitset+莫比乌斯反演]
    Codeforces Hello 2019 D. Makoto and a Blackboard[DP+数论+概率期望]
    Codeforces Hello 2019 ABCDF题解
    [BZOJ1042][HAOI2008]硬币购物[容斥原理+背包]
    Codeforces Round #529 (Div. 3)题解
    [BZOJ4311]向量[线段树分治+计算几何+二分/三分]
    [BZOJ1076][SCOI2008]奖励关[状压DP+概率期望]
    [POJ3368][UVA11235] Frequent values[ST表]
    [USACO5.5]矩形周长Picture[扫描线+线段树]
  • 原文地址:https://www.cnblogs.com/csong7876/p/9125173.html
Copyright © 2020-2023  润新知