String构造方法初始化和常量赋值初始化区别

下面的代码是一个String对象的两种不同的初始化方式,关于这两种不同初始化方式的区别,本文通过画内存图来进行解释,首先代码如下:

public class Test {
public static void main(String[] args) {
String s1 = new String("hello");
String s2 = "hello";
System.out.println(s1 == s2);
System.out.println(s1.equals(s2)); } }

s1是通过String类的构造方法进行初始化的,s2是通过字符串常量进行赋值初始化的,该程序在内存中的图如下:

字符串常量都是存储在方法区的字符串常量池中,所以第一种方式的初始化是先在堆中建立一个对象,然后该对象的值来自方法区的“hello”,所以方式1的初始化方式最多会创建2个对象,最少创建1个;方式2的初始化由于是字符串常量直接赋值,所以直接去方法区里面查找,最后返回已有对象,所以方式2的初始化方式最多创建1个对象,最少创建0个,例如本例中,由于方法区中已有“hello”,所以创建0个。

String常量值不可以变,但引用可以变

直接上代码来解释了:

public class Test {
public static void main(String[] args) {
String s = "hello";
String s1 = s;
System.out.println("s: " + s);
System.out.println("s1: " + s1);
System.out.println("---------------");
s = "world";
System.out.println("s: " + s);
System.out.println("s1: " + s1);
}
}

结果:

s: hello
s1: hello
---------------
s: world
s1: hello Process finished with exit code 0

可以看出,对s进行重新复制,并没有改变原来的hello,只是将s指向了新的“world”。

String中常量拼接和变量拼接效果不同

首先看下面这段代码中的helloworld的不同拼接方式:

public class Test {
public static void main(String[] args) {
String s1 = "hello";
String s2 = "world";
String s3 = "helloworld";
System.out.println(s3 == s1 + s2);
System.out.println(s3.equals(s1 + s2));
System.out.println("-------------------");
System.out.println(s3 == "hello" + "world");
System.out.println(s3.equals("hello" + "world"));
}
}

程序运行的结果是:

false
true
-------------------
true
true Process finished with exit code 0

equals的比较由于内容相同,为true并不奇怪,但是变量拼接和s3比较的结果为false,而常量拼接结果却为true。这就是String中常量拼接和变量拼接的区别了。

  • 变量拼接:先开辟空间,再去拼接;
    所以s1+s2结果存储在新开辟的空间中,地址自然和s3不一样。反编译的代码是:

    System.out.println(s3 == (new StringBuffer(String.valueOf(s1)).append(String.valueOf(s2))).toString());
  • 常量拼接:先拼接,再在常量池中查找,如果有,则返回找到的地址,否则创建新的常量。
    所以”hello“+”world“拼接后再常量池中找到了s3,所以返回s3的地址,所以结果为true。反编译的代码是:
    System.out.println(s3 == "helloworld");//所以可以看出,编译器对变量的拼接直接做了优化
    
    

内容为空和null的区别

直接上代码看结果解释:

public class Test {
public static void main(String[] args) {
String s1 = "";
String s2 = null;
System.out.println(s1.isEmpty());
System.out.println(s2.isEmpty());
}
}
true
Exception in thread "main" java.lang.NullPointerException
at Test.main(Test.java:6)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140) Process finished with exit code 1

很明显,s1是可以调用String对象的方法的,而s2由于是null的,所以s2没有指向任何字符串对象,所以调用对象的方法会报空指针错误。

【Java基础】关于String的总结的更多相关文章

  1. Java基础之String、StringBuffer、StringBuilder浅析

    Java基础之String.StringBuffer.StringBuilder浅析 一.前言: 位于java.lang包下的String.StringBuilder.StringBuffer一般都是 ...

  2. 【Java基础】String 相关知识点总结

    String 相关知识点总结 字符串的不可变性 概述 String 被声明为 final,因此它不可继承 在 Java8 中,String 内部使用 char 数组存储数据 public final ...

  3. Java基础之String中equals,声明方式,等大总结

    无论你是一个编程新手还是老手,提到String你肯定感觉特别熟悉,因为String类我们在学习java基础的时候就已经学过,但是String类型有我们想象的那么简单吗?其实不然,String类型的知识 ...

  4. Java 基础之 String 类

    String String 被声明为 final,因此不能被继承.(Integer 等包装类也不能被继承) 在 java8 中,String 内部使用 char 数组 来存储数据 public fin ...

  5. java基础(六)-----String性质深入解析

    本文将讲解String的几个性质. 一.String的不可变性 对于初学者来说,很容易误认为String对象是可以改变的,特别是+链接时,对象似乎真的改变了.然而,String对象一经创建就不可以修改 ...

  6. Java基础之String、StringBuffer、StringBuilder

    1:String类:字符串(重点) (1)多个字符组成的一个序列,叫字符串. 生活中很多数据的描述都采用的是字符串的.而且我们还会对其进行操作. 所以,java就提供了这样的一个类供我们使用. (2) ...

  7. Java基础-关键字-String

    1.String的本质 线程安全 打开String的源码,类注释中有这么一段话“Strings are constant; their values cannot be changed after t ...

  8. Java基础(36):String与基本数据类型之间的双向转换(Wrapper类)

    Java 中基本类型和字符串之间的转换 在程序开发中,我们经常需要在基本数据类型和字符串之间进行转换. 其中,基本类型转换为字符串有三种方法: 1. 使用包装类的 toString() 方法 2. 使 ...

  9. Java基础(32):String与StringBuilder、StringBuffer的区别(String类)

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

  10. Java基础(30):String对象的常用方法与实例(String类)

    Java 中 String 类的常用方法 Ⅰ String 类提供了许多用来处理字符串的方法,例如,获取字符串长度.对字符串进行截取.将字符串转换为大写或小写.字符串分割等,下面我们就来领略它的强大之 ...

随机推荐

  1. C语言之指针

    以32为系统为例. 1.指针与地址指针是一种变量,保存了所指向对象的地址.1.1 定义int i = 10;int *p = &i; //定义了一个指针p,它指向一个int型的变量&是 ...

  2. 【Druid】 阿里巴巴推出的国产数据库连接池com.alibaba.druid.pool.DruidDataSource

    阿里巴巴推出的国产数据库连接池,据网上测试对比,比目前的DBCP或C3P0数据库连接池性能更好   简单使用介绍 Druid与其他数据库连接池使用方法基本一样(与DBCP非常相似),将数据库的连接信息 ...

  3. ASP.NET MVC Spring.NET 整合

    请注明转载地址:http://www.cnblogs.com/arhat 在整合这三个技术之前,首先得说明一下整合的步骤,俗话说汗要一口一口吃,事要一件一件做.同理这个三个技术也是.那么在整合之前,需 ...

  4. vue-cli + webpack

    vue-cli + webpack 关于vue.js vue.js是一套构建用户界面的 轻型的渐进式前端框架.它的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件.使用vue可以给你 ...

  5. 批量将MP4 转换为 MP3

    0 需要先下载VLC 软件 1 win+R 运行 "CMD" 2 CD mp4目录 3 复制 并运行下面代码 for %%a in (*.mp4) do "C:\Prog ...

  6. SDUT 1269 走迷宫(BFS)

    点我看题目 题意:中文不详述. 思路 :上上上场比赛让一个BFS给虐了,上次比赛让一个三维的给废掉了.......所以急于从水题刷起......还因为数组开小了WA了5,6次 #include < ...

  7. nginx 配置的server_name参数(转)

    转自:http://www.sklinux.com/373 nginx中的server_name指令主要用于配置基于名称虚拟主机. 一 匹配顺序,server_name指令在接到请求后的匹配顺序如下: ...

  8. [水题]Codeforces337A Puzzles

    题目链接 题意:要在m个数里面选n个数, 要求这n个数的差值要最小 题意在hint里很清晰了 这道题从题意到题目本身都没有什么trick 写这道题完全是为了用一下#include <numeri ...

  9. JNI 多线程

    一.概述 JNI编程和Linux上的C/C++编程还是挺相似的,每次java调用JNI中的函数时都会传入有关JVM的一些参数(如JNIEnv,jobject),每次JNI回调java中的方法时都要通过 ...

  10. ssh 密钥详解

    ssh 无密码登录要使用公钥与私钥.linux下可以用用ssh-keygen生成公钥/私钥对,下面我以CentOS为例. 有机器A(192.168.1.155),B(192.168.1.181).现想 ...