精华内容
下载资源
问答
  • String是引用类型,String变量储存一个地址地址指向内存堆中的String对象。当我们说变量不可变,有两种不可变性:变量储存的地址不可变;地址指向的对象内容不可变。String的不可变指的是哪一种?下面用例子来。...

    String经常在一个语言中或多或少都有些特殊地位。在Java亦不例外。今天先来讨论,String是不可变的。

    String是引用类型,String变量储存一个地址,地址指向内存堆中的String对象。当我们说变量不可变,有两种不可变性:

    变量储存的地址不可变;

    地址指向的对象内容不可变。

    String的不可变指的是哪一种?下面用例子来看。

    通常有人在疑问String不可变时,会举这样的例子:我们平时不都像下面这样在“修改”String字符串吗:

    String s = "hello,world";

    s = "Hello,coder";

    System.out.println(s); //Hello,coder

    我认为这只是一个语义上的误导。赋值操作符=通常作用于基本数据类型时,确是修改变量的值。所以在这里让人误以为也是修改了变量的内容。但是对于引用类型String,s="Hello,coder"的实际作用是将变量s指向另一个内容为Hello,coder的新的对象。

    所以,对于String不可变性的结论显而易见了:String变量指向的地址是可变的,他的不可变性当然说的是第二种——地址指向的对象内容不可变。

    纵览String的方法,String类确实没有提供能从String外部修改对象的方法。我们熟悉的replace,substring等等方法都要返回一个String,其实都是在返回一个新的对象,而没有修改原有的对象。

    为什么要设计成对象内容不可变?

    String常量池

    一个说法是便于实现String常量池。String存在于常量池中,当新创建一个字符串变量,如果字符串在内存中已经存在,那么就会把这个已经存在于常量池对象的地址赋给变量。这样可节省内存开销。

    但这不完全对。

    只有两种情况下创建的String变量,他们才会指向常量池中的同一对象:

    String是字面直接量赋值创建。字面直接量是编译期常量,变量会指向常量池中的对象。所有字面量赋值创建的String变量都会指向常量池中的对象。

    通过String类的intern()方法得到String变量也是指向常量池中的对象。

    但是通过构造函数new String()的并不是。通过构造函数创建的String变量在机制上与其他对象一致,都是在heap上创建新的对象,然后把引用赋给变量。

    简单例子验证。

    String a = "hello,world";

    String b = "hello,world";

    boolean c = (a == b); //true

    String d = new String("hello,world");

    String e = new String("hello,world");;

    boolean f = (d == e); //false

    String g = d.intern();

    boolean h = (a == g); //true

    此外,String的方法substring,relpace和split等方法实现均是调用了构造函数创建了新的对象,所以他们返回的String也都是存在于heap上的新对象。

    综上来看似乎节省不了多少内存,毕竟程序中编译常量是少数,大多数String都是在运行时产生。

    线程安全

    这一点显而易见,对象内容都不可变了,自然不会有线程安全问题。

    代码安全

    String经常被用来存储server connection, database connection或者file path等等。如果String可变,一旦代码某处改动了字符串,会对系统有安全和稳定性威胁。发生在其他普通字符串,则是不可预料的bug。尤其是代码复杂度很高的时候,一个字符串对象被多个变量引用,直接修改对象内容,引起所有引用该对象的变量都发生变化,容易引起bug。

    当然这一点主要是降低程序员的错误和bug的可能。

    其实,话说回来,在JAVA里,String不可变也并非特殊,所有包装类Interger,Boolean等都是不可变类。

    展开全文
  • 2.普通的对象几乎都是在堆中生成(当然也有一些比较特殊的比如Class类的对象可能在方法区生成,这个不同的虚拟机实现,虚拟机规范并没有强制)3.==这个判定的时候,对于引用类型,说到底都是比对内存地址。...

    迷茫2017-04-18 10:52:361楼

    帮助你理解这个过程。java中有几个点你可以记住下

    1.所有的字符串都会在常量池生成,对应的是CONSTANT_String_info,不可变。

    2.普通的对象几乎都是在堆中生成(当然也有一些比较特殊的比如Class类的对象可能在方法区生成,这个看不同的虚拟机实现,虚拟机规范并没有强制)

    3.==这个判定的时候,对于引用类型,说到底都是比对内存地址。

    好了,有了上述的观念。第一个问题中,

    String s1 = new String("aaa"); 当你new一个对象,jvm就会在堆上帮你开辟一个对象空间,而s1是存在你的本地变量表的,s1指向这个对象空间(可以暂时理解为s1存着对象空间的地址)。所以你new了两个,是两个不同的对象空间。==判断当然不同啦,因为,s1和s2指向不同的空间。

    第二个问题,上述第一点,每个字符串都只会在常量池中存在一份,所以str2指向这个常量池字符串的地址,str3也是指向这个常量池字符串的地址。==判断自然是相同的。

    展开全文
  • javaString数据类型对于字符串对象来说,虽然在参数传递的时候也是引用传递,但是java虚拟机在函数内部对字符串对象进行了特殊处理–视String对象为常量(final)所以对传进来的引用地址所引用的string对象比能直接...

    Java中的String数据类型实例讲解使用方法:

    java中String数据类型

    对于字符串对象来说,虽然在参数传递的时候也是引用传递,但是java虚拟机在函数内部对字符串对象进行了特殊处理–视String对象为常量(final) 所以对传进来的引用地址所引用的string对象比能直接进行修改,而是产生一个副本对其进行操作,对其进行的操作不会影响原来的值。

    下面我们看一例子(sun认证试题)来证明这一点:

    1. public class X {

    2. public static void main (String[]args) {

    3. string s = new string (“Hello”);

    4. modify(s);

    5. System.out.printIn(s);

    6. }

    7.

    8. public static void modify (String s) {

    9. s += “world!”;

    10. }

    11. }

    你说它会打印出什么结果?是Helloworld?可能大部分人会说是这个答案吧,哈哈结果却是Hello,为什么呢?再仔细分析一下上边所说的吧—–“视String对象为常量(final)” 这是问题的关键!在modify()方法中传进了string对象,虽然是引用传递,上边我们说了视String对象为常量(final),它不会修改原来地址所引用的值,而是生成一个副本对其进行操作,所以打印结果应该为Hello!下面再讲一讲java中对常量(final)是怎样处理优化的,以便更深入的理解上面的问题:

    java中的final变量,java编译器是进行了优化的。每个使用了final修饰的变量的地方都不会通过连接而进行访问。比如说Test类中使用了Data类中一个final的int数字fNumber=77,这时候,java编译器会将77这个常数编译到Test类的指令码或者常量池中。这样,每次Test类用到fNumber的时候,不会通过引用连接到Data类中进行读取,而是直接使 用

    我们再来举个例子说明这一点:

    public class TestFinal(){

    public static void main(string s[]){

    System.out.println(FinalData.date);

    }

    public class FinalData(){

    public static final data=8;

    }

    }

    运行上面的TestFinal类结果为:8

    但是你把FinalData类中的data=88,编译后再运行TestFinal类结果还是8,这是因为编译器把data的副本保存TestFinal类中,所以在重新编译TestFinal类之前,TestFinal类一直把data认为是8而不是88,是不是证明了上面所讲述的每个使用了final修饰的变量的地方都不会通过连接而进行访问!结合这个例子,再深入的想一想第一个问题是不是就理解的更加清晰了

    本文链接地址: Java中的String数据类型实例讲解使用方法

    展开全文
  • 我们继续来 String 类常用的方法,如下代码所示:运行结果:那么,“==” 和 equals() 有什么区别呢?==: 判断两个字符串在内存中首地址是否相同,即判断是否是同一个字符串对象equals(): 比较存储在两个字符串...

    我们继续来看 String 类常用的方法,如下代码所示:

    d3fe8fc4469c7481d45b112f5101e908.png

    运行结果:

    b7de0f1339cbe016ca019cac82f8a4af.png

    那么,“==” 和 equals() 有什么区别呢?

    ==: 判断两个字符串在内存中首地址是否相同,即判断是否是同一个字符串对象

    equals(): 比较存储在两个字符串对象中的内容是否一致

    PS:字节是计算机存储信息的基本单位,1 个字节等于 8 位, gbk 编码中 1 个汉字字符存储需要 2 个字节,1 个英文字符存储需要 1 个字节。所以我们看到上面的程序运行结果中,每个汉字对应两个字节值,如“学”对应 “-47 -89” ,而英文字母 “J” 对应 “74” 。同时,我们还发现汉字对应的字节值为负数,原因在于每个字节是 8 位,最大值不能超过 127,而汉字转换为字节后超过 127,如果超过就会溢出,以负数的形式显示。(关于编码,我们在后面课程中会详细介绍,小小期待哦~~)

    示例:

    public class HelloWorld {

    public static void main(String[] args) {

    // 定义一个字符串

    String s = "aljlkdsflkjsadjfklhasdkjlflkajdflwoiudsafhaasdasd";

    // 出现次数

    int num = 0;

    // 循环遍历每个字符,判断是否是字符 a ,如果是,累加次数

    for ( int i=0; i< s.length();i++ )

    {

    // 获取每个字符,判断是否是字符a

    if ( s.charAt(i) == ‘a‘ ) {

    // 累加统计次数

    num++;

    }

    }

    System.out.println("字符a出现的次数:" + num);

    }

    }

    输出:

    字符a出现的次数:8

    认识 Java 中的 StringBuilder 类

    在Java中,除了可以使用 String 类来存储字符串,还可以使用 StringBuilder 类或 StringBuffer 类存储字符串,那么它们之间有什么区别呢?

    String 类具有是不可变性。如

    25928d5f63f264de8ee8734016f11230.png

    运行结果:  886534bb55b51ce7736a27ec300e5c81.png

    从运行结果中我们可以看到,程序运行时会额外创建一个对象,保存 "helloworld"。当频繁操作字符串时,就会额外产生很多临时变量。使用 StringBuilder 或 StringBuffer 就可以避免这个问题。至于 StringBuilder 和StringBuffer ,它们基本相似,不同之处,StringBuffer 是线程安全的,而 StringBuilder 则没有实现线程安全功能,所以性能略高。因此一般情况下,如果需要创建一个内容可变的字符串对象,应优先考虑使用 StringBuilder 类。

    那么如何定义 StringBuilder 类的对象呢? 我们来看下面的代码:

    53beab376d6389ab8fa2b076cc6317f8.png

    运行结果:imooc

    Java 中的 StringBuilder 类的常用方法

    StringBuilder 类提供了很多方法来操作字符串:

    0aed18932a341a4fdd37939e5e652d42.png

    例如:在下面的示例代码中,创建了 StringBuilder 对象,用来存储字符串,并对其做了追加和插入操作。这些操作修改了 str 对象的值,而没有创建新的对象,这就是 StringBuilder 和 String 最大的区别。

    bc3e6ed0bbd8c8927553a038e7ad09e9.png

    运行结果: 0a72c62470427e40fa662e760315266d.png

    示例:

    public class HelloWorld {

    public static void main(String[] args) {

    // 创建一个空的StringBuilder对象

    StringBuilder str = new StringBuilder();

    // 追加字符串

    str.append("jaewkjldfxmopzdm");

    // 从后往前每隔三位插入逗号

    for(int i =(str.length()-3); i > 0 ;i-=3){

    str.insert(i,",");

    }

    // 将StringBuilder对象转换为String对象并输出

    System.out.print(str.toString());

    }

    }

    输出:

    j,aew,kjl,dfx,mop,zdm

    展开全文
  • Java String

    2017-10-13 11:00:08
    Java数据类型通常(分类方法多种多样)从整体上可以分为两大类:基础类型和引用类型,基础类型的变量持有原始值,引用类型的变量通常表示的是对实际对象的引用,其值通常为对象的内存地址。对于基础类型和引用类型的...
  • 展开全部了你的描述:转换后成'[C@1b8ee96'这个不是乱码,是Java的hashCode值,即对象的内存地址62616964757a686964616fe59b9ee7ad9431333335313861,产生原因是:Stringsql1="'"+id+"'";做字符串拼接时,id是一个...
  • 用new String() 创建的字符串不是常量,不能在编译期就确定,所以new String() 创建的字符串不放入常量池中,它们有自己的地址空间。例2:String s0=”kvill”;String s1=new String(”kvill”);String s2=”kv” ...
  • java String

    2013-07-24 11:40:35
    今天回顾了一下java基础,发现原理性问题,以前不太了解的地方,刚刚String类型,发现string类型的变量每次赋值时这个变量在内存中的地址都会改变。而不像数据类型一样。
  • javaString类型,可以有两种实例化方式; 一种是这样的String a = “hello”; 另一种是这样的String b = new String(“hello”); 如果直接用“==”比较他俩个是否想相等,System.out.println(a == b); 输出的...
  • 首先明确一点,在Java中==比较的是两个对象的地址,equals()比较的是两个对象的值,如果使用equals()来替换==,则两个输出结果都为true。言归正传,为什么第一个返回为false?先一下intern()这个方法的描述:大意...
  •  今天erlang,看到一个最基本的问题,就是方法调用或函数调用时,参数传递的方式,大家都知道在Java中,基本类型是通过按值传递的方式,来实现参数传递,而对象类型则是通过按引用地址传递的,但是这个里面有一个...
  • 在回答这个问题之前,我们先来String类的一些相关知识,这是我们常见的String用法: String str = "knowledge"; 这段代码的逻辑如下,创建一个字符串常量 knowledge , ,然后字符串地址赋给一个字串引用str...
  • 了下源码,说下个人看法:1、String的不可变 String a="hello"; a="hello world";a 指向内存中常量池中"hello";后又被赋值为"hello world"。有人说这不是变化了吗?其实...
  • 今天看到有线程同步的代码直接使用了String对象作为...但是String类有个本地方法intern,可以让不同对象地址的字符串,使用==时返回true,来下定义:方法返回字符串对象的标准表示。重点在When段落。当字符串池中...
  • 1、equals 和 ====在java中是比较引用的,即在内存中的地址。而String的equals()是比较字符串的内容先这几句代码Strings1="String";Strings2="String";System.out.println(s1==s2);System.out.println(s1.equals...
  •  对于字符串对象来说,虽然在参数传递的时候也是引用传递,但是java虚拟机在函数内部对字符串对象进行了特殊处理–视String对象为常量(final) 所以对传进来的引用地址所引用的string对象比能直接进行修改,而是...
  • 今天不知道怎么了下string的==的问题,本身我觉得我这个水平去判断几个字符串相等还能出问题?呵呵,真的出了大问题,根本原因在于对java字节码的不了解。首先,==运算符比较的是两个变量所指向的对象内存地址是否...
  • javaString的==与equals

    2019-12-06 08:57:48
    ==比较的是字符串引用的内存地址,equals比较的是字符数的内容 具体例子: String s1 = new String("a"); String s2 = new String("a"); String s3 = "a"; String s4 = "a"; System.out.println(s1 =...
  • java: String的==与equals

    2019-08-08 10:11:52
    string 是对象,所以==对于string来说,是对比的内存地址; 解释第一个:a==c//为true。 因为b被final修饰,那么它本身是一个常量,如果你原意的话,你可去看看编译后的class文件。里面变量c = "hello2",底层原理是...
  • Java String注意点

    2020-12-06 09:37:09
    以下都是了黑马程序员javase之后的感想,若有错误,请帮助我指出,谢谢。 String注意事项 同一个字符串常量使用的是同一个内存区域 String x = "abc"; String y = "abc"; 那么x和y的地址值***相同*** 同一个...
  • javaString对象作为参数传递问题

    千次阅读 2020-06-03 15:24:04
    java中将对象作为参数传递究竟是值传递还是引用传递? 1、基本类型作为参数传递时,是传递值的拷贝,无论你怎么改变这个拷贝,原值是不会改变的。 2、对象作为参数传递时,是把对象在内存中的地址拷贝了一份传给了...
  • javaString、StringBuffer、StringBuilder是编程中经常使用的字符串类,他们之间的区别也是经常在面试中会问到的问题。现在总结一下,看看他们的不同与相同。 1.可变与不可变  String类中使用字符数组保存字符...
  • 对intern方法的学习来源于之前偶然看到的一篇博客:【请别...这篇博客写的很好,从各方面详细的讲解了Java底层的一些东西,不搞底层的看着可能会觉得很涩,很难懂,有兴趣的可以看看,当然本篇重点不在这边,而是对i...
  • 我们继续来 String 类常用的方法,如下代码所示:运行结果:那么,“==” 和 equals() 有什么区别呢?==: 判断两个字符串在内存中首地址是否相同,即判断是否是同一个字符串对象equals(): 比较存储在两个字符串...
  • 我们继续来 String 类常用的方法,如下代码所示:运行结果:那么,“==” 和 equals() 有什么区别呢?==: 判断两个字符串在内存中首地址是否相同,即判断是否是同一个字符串对象equals(): 比较存储在两个字符串...
  • 对于上面的题,完下面的几个例子,你就会有所感悟:String str = new String(“good”);是在编译时在堆栈中创建对象和分配内容,而在传参的时候,传递的是地址,把外面的str引用地址复制了一份给方法内的str而不
  • String s2="hehe"; 首先会在字符串池中找,有没有“hehe”这个字符串,有的话,直接让s2指向它,没有的话,创建“hehe”,再指向。...字符串比较的时候用“=” , 则是比较它们的地址,那么代码: String s1 = "hehe
  • javaString类为什么要设计成final? 2.string为什么不可变? private final char value[]; 首先String类是用final关键字修饰,这说明string不可被继承。再下面,stirng类的主力成员字段value是个char[]数组...
  • javaString之常量池与对象

    千次阅读 2018-06-01 14:19:59
    最近一直在研究源码,今天把String类给完了,基本上是把源码了一遍(JDK1.8),所获得的收获还是可以的,但是了归了,俗话说的好好记性不如烂笔头,今天就写一写自己的心得体会。首先在String类型在开发项目...
  •  当我们创建两个Integer对象的时候,有可能会出现它们指向的内存地址一致的情况,下面就来详细的讲一下什么时候会出现这个情况。首先来一下程序实例: public static void main(String[] args) { Integer a...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 902
精华内容 360
关键字:

java看string地址

java 订阅