• 1. String 和new String 

在讲String  和 new String  的区别之前先看一段代码:

String a = "ss"= "ss"=  String("ss"==

  false
  true

还需要知道的String 类型 的声明类型,查看源码可以知道

String 和 new String_String

 

 

 这个时候我们就知道原来String 是被final修饰,代表不可变的字符序列,且创建出来的字符串是存放在常量池里面,也就存在于方法区中。(此处关于字符串常量池存放位置,这个是根据jdk版本不同而不同的,此处举例在方法区中。)

那么每一次执行 String a="aa"; String b = "aa"; “aa”被存放在常量池中,当引用b(位于栈)被创建的时候发现“aa”在常量池已经存在,jvm会把b引用指向"aa",

而new String()可以分类俩个阶段

  1. 在编译阶段JVM先去常量池中查找是否存在“abc”,如果过不存在,则在常量池中开辟一个空间存储“abc”。

  2.  在运行时期,通过String类的构造器在堆内存中new了一个空间,然后将String池中的“abc”复制一份存放到该堆空间中,在栈中开辟名字为str2的空间,存放堆中new出来的这个String对象的地址值。

所以这个时候返回看上面的代码就很简单啦

  a 和 b 指向的是位于常量池中的同一块地址,当然结果是true啦

  a 和 c 相比,c指向是堆内存“aa”存在的地址,a指向常量池的地址,所以是false;

2. 关于String 拼接比较的问题

  先看代码~

public class Test{    public static void main(String[] args){
        String str = "helloworld";
        String str1 = "hello";
        String str2 = "world";
        
        String str3 = "hello" + "world";
        String str4 = "hello" + str2;
        String str5 = str1 + "world";

        System.out.println(str1 == str2); //false
        System.out.println(str == str3); //true
        System.out.println(str == str4); //false
        System.out.println(str == str5); //false
        System.out.println(str4 == str5); //false    }
}

<1、常量与常量的拼接结果在常量池中。且常量池中不会存在相同内容的常量
<2、常量与常量拼接时,只要其中有一个是变量 ,结果就在堆中
<3、使用相同的字符序列而不是使用new关键字创建的两个字符串会创建指向Java字符串常量池中的同一个字符串的指针。

 

根据final 引申出来的一个问题,final修饰的 变量不能被修改,那反射能修改变量么?

这个时候要分俩种情况

  1. 当final修饰的成员变量在定义的时候就初始化了值,那么java反射机制就已经不能动态修改它的值了。

  2. 当final修饰的成员变量在定义的时候并没有初始化值的话,那么就还能通过java反射机制来动态修改它的值。