2019-11-19-String详解

一、String 能继承吗?为什么?

答案:不能,因为String类有final修饰,而final修饰的类不能被继承的,实现细节不能被改变的。

扩展一:平时我们定义String str = "a";其实和String str = new String("a") 还是有差异的:

前者默认调用的是String.valueOf来返回String实例对象的,至于调用的哪个取决于你的赋值,

比如:String num = 1;

调用的是:

  public static String valueOf(int i){

    return Integer.toString(i);

  }

后者则是调用的下部分:

  public String(String original){

    this.value = original.value;

    this.hash = original.hash;

  }

最后我们的变量都存储在一个Char[] 数组中:

  private fianl char value[];

 

扩展二:创建字符串对象两种方式的区别

  1、直接赋值创建字符串字符串对象

    直接赋值创建字符串创建对象是:在方法区的常量池

String str = "hello"//直接赋值方式

  2、通过构造器方式创建字符串对象

    通过构造器方式创建字符串对象是:在堆内存

String str = new String("hello");//通过构造器方式

  代码比较:

public class TestString {
    public static void main(String[] args) {
        String str1 = "Lance";
        String str2 = new String("Lance");
        String str3 = str2; //引用传递,str3直接指向st2的堆内存地址
        String str4 = "Lance";
        /**
         *  ==:
         * 基本数据类型:比较的是基本数据类型的值是否相同
         * 引用数据类型:比较的是引用数据类型的地址值是否相同
         * 所以在这里的话:String类对象==比较,比较的是地址,而不是内容
         */
         System.out.println(str1==str2);//false
         System.out.println(str1==str3);//false
         System.out.println(str3==str2);//true
         System.out.println(str1==str4);//true
    }

}

  内存图分析:

  

 

   内存图详细分解:

  构造方法实例化方式的内存图:String str = new String("Hello");

  

 

   当我们再一次的new一个String对象时:

  

 

   字符串常量池:

    在字符串中,如果采用直接赋值的方式(String str = "Lance")进行对象实例化,则会将匿名对象放入对象池,每当下一次对不同的对象进行直接赋值的时候直接利用池中原有

  匿名对象;这样,所有直接赋值的String对象,如利用相同的"Lance" ,则String对象 == 返回的true。

  比如对象手工入池:

  

public class TestString {
    public static void main(String args[]){
     String str =new String("Lance").intern();//对匿名对象"hello"进行手工入池操作
     String str1="Lance";
     System.out.println(str==str1);//true
    }
}

  String类对象一旦声明则不可以改变;而改变的只是地址,原来的字符串还是存在的,并且产生垃圾

  

 

 

  避免空指向

  首先了解: == 和public boolean equals()比较字符串的区别

      ==在对字符串比较的时候,对比的是内存地址,而equals比较的是字符串内容,在开发的过程中,equals()通过接受参数,可以避免空指向。

      举例:

  

String str = null;
      if(str.equals("hello")){//此时会出现空指向异常
        ...
      }
      if("hello".equals(str)){//此时equals会处理null值,可以避免空指向异常
         ...
      }

  总结:

    1)直接赋值(String str = "hello"):只开辟一块堆内存空间,并且会自动入池,不会产生垃圾。

    2)构造方法(String str=  new String("hello");):会开辟两块堆内存空间,其中一块堆内存会变成垃圾被系统回收,而且不能够自动入池,

      需要通过public  String intern();方法进行手工入池。在开发的过程中不会采用构造方法进行字符串的实例化。

posted @ 2019-11-19 14:41  小龟一号  阅读(125)  评论(0)    收藏  举报