Java自学之String类

在实际项目开发中,String是一个必须使用的程序类,可以说是项目的核心组成类。在Java程序里所有的字符串都要求使用【’‘】进行定义,同时也可以利用【+】实现字符串的连接处理。

String类对象实例化

class StringDemo {
	public static void main(String[] args) {
		// 直接赋值实例化
		String str1 = 'www.uihtml.cn';
		// 构造方法实例化
		String str2 = new String('www.uihtml.cn');
	}
}

字符串比较

基本数据类型的相等判断可以直接使用Java中提供的【==】运算符来实现,直接进行数值的比较。如果在String类对象上使用【==】比较的将不再是内容,而是字符串的堆内存地址。

class StringDemo {
	public static void main(String[] args) {
		// 直接赋值实例化
		String str1 = 'www.uihtml.cn';
		// 构造方法实例化
		String str2 = new String('www.uihtml.cn');
		String str3 = str2;
		System.out.println(str1 == str2);	// false
        System.out.println(str1 == str3);	// false
        System.out.println(str2 == str3);	// true
	}
}

对于字符串内容的判断,在String类中已经提供了相应的equals()方法,只需要通过String类的实例化对象调用即可,此方法专门负责进行字符串内容的比较

class StringDemo {
	public static void main(String[] args) {
		// 直接赋值实例化
		String str1 = 'www.uihtml.cn';
		// 构造方法实例化
		String str2 = new String('www.uihtml.cn');
		System.out.println(str1.equals(str2));	// true
	}
}

字符串常量

在程序中常量是不可被改变内容的统称。但是由于Java中的处理支持,所以可以直接使用【’‘】进行字符串常量的定义。而这种字符串的常量,严格意义上来讲是String类的匿名对象。

class StringDemo {
	public static void main(String[] args) {
		String str = 'uihtml';
		// 字符串常量是String类的匿名对象,可以直接调用String类中的方法
		System.out.println('uihtml'.equals(str));	// true
	} 
}

两种实例化方式比较

直接赋值实例化对象

class StringDemo {
	public static void main(String[] args) {
		String strA = 'www.uihtml.cn';
		String StrB = 'www.uihtml.cn';
		System.out.println(strA == strB); // true
	}
}

通过直接赋值的方式为String类对象实例化会开辟一块堆内存空间,而且对同一字符串的对此直接赋值还可以实现对堆内存的重用,即采用直接赋值的方式进行String类对象实例化,在内容相同的情况下不会开辟新的堆内存空间,而会直接指向已有的堆内存空间。

构造方法实例化对象

class StringDemo {
	public static void main(String[] args) {
		String strA = new String('www.uihtml.cn');
		String strB = new String('www.uihtml.cn');
		System.out.println(strA == strB); // false
	}
}

如果要明确地调用String类中的构造方法进行String类对象的实例化操作,那么一定要使用关键字new,而每当使用关键字new就表示要开辟新的堆内存空间,而这块堆内存的内容就是传入构造方法中的字符串数据。

因为每一个字符串都是一个String类的匿名对象,所以首先在堆内存中开辟一块空间保存字符串,而后又使用关键字new,开辟另一块堆内存空间,而真正使用的是用关键字new开辟的堆内存。而之前定义的字符串常量开辟的堆内存空间将不会被任何的栈内存所指向,成为垃圾空间,并等待被GC回收。所以,使用构造方法的方式开辟的字符串对象,实际上会开辟两块空间,其中有一块空间将成为垃圾。

除了内存的浪费之外,如果使用了构造方法实例化String类对象,由于关键字new永远表示开辟新的堆内存空间,所以其内容不会保存在对象池中。

class StringDemo{
	public static void main(String[] args) {
		String strA = 'www.uihtml.cn';
		String strB = new String('www.uihtml.cn');
		System.out.println(strA == strB); // false
		System.out.println(strA.equals(strB)); // true
        // String类对象手动入池
        String strC = new String('www.uihtml.cn').intern();
        System.out.println(strA == strC); // true
	}
}

字符串常量池

Java中使用【”】就可以进行字符串实例化对象定义,如果处理不当就有可能为多个内容相同的实例化对象重复开辟堆内存空间,这样必然造成内存大量浪费。为了解决这个问题,在JVM中提供了一个字符串常量池(或者称为“字符串对象池”,其本质属于一个动态对象数组),所有通过直接赋值实例化的String类对象都可以自动保存在此常量池中,以供下次重复使用。

Java中字符串常量池一共分为两种:静态常量池及运行时常量池。

静态常量池

程序(*.class)在加载的时候会自动将此程序中保存的字符串、普通的常量、类和方法等信息,全部进行分配。

class StringDemo{
	public static void main(String[] args) {
		String strA = 'www.uihtml.cn';
		String strB = 'www.' + 'uihtml' + '.cn';
		System.out.println(strA == strB); // true
	}
}

本程序使用了两种方式定义了String类对象,由于在实例化strB对象时,所有参与连接的字符串都是常量,所以在程序编译时会将这些常量组合在一起进行定义,这样就与strA对象的内容相同,最终的结果就是继续使用字符串常量池中提供的内容为strB实例化,不会再开辟新的堆内存空间。

运行时常量池

当一个程序(*.class)加载之后,有一些字符串内容是通过String对象的形式保存后再实现字符串连接处理,由于String对象的内容可以改变,所以此时称为运行时常量池。

class StringDemo{
	public static void main(String[] args) {
		String name = 'uihtml'; // 定义一个变量
		String strA = 'www.uihtml.cn';
		String strB = 'www.' + name + '.cn'; // 动态拼凑
		System.out.println(strA == strB); // false
	}
}

本程序中利用一个name的对象定义了要连接的字符串的内容,由于name属于程序运行时才可以确定的内容,这样就使得程序编译时无法知道name的具体内容,所以strB对象将无法从字符串常量池【静态常量池】中获取字符串引用。

原创文章,作者:ZERO,如若转载,请注明出处:https://www.edu24.cn/course/java/java-string.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
ZEROZERO
上一篇 2020年11月26日
下一篇 2020年12月3日

相关推荐

  • Java自学之数组

    在Java中数组是一组相关变量的集合,属于引用数据类型。 定义 数组引用传递分析 数组属于引用数据类型,在数组使用时需要通过关键字new开辟堆内存空间,一块堆内存空间也可以同时被多…

    2020年11月26日
    1.3K
  • Java自学之异常的捕获与处理

    在程序开发中,程序的编译与运行是两个不同的阶段,编译主要针对的是语法检测,而在程序运行时却有可能出现各种各样的错误导致程序中断执行,那么这些错误在Java中统一称为异常。 异常处理…

    2020年12月11日
    1.4K
  • spring boot练习篇之用户登录系统【接入数据库】

    抛弃JSP,只做纯粹的前后端分离项目。 写在前面 学习基础知识是枯燥无味的,之所以会这样,多数是因为心不静,对于如何运用它,感到茫然。所以建议大家在学习Java基础知识的时候,一定…

    2021年5月28日
    1.3K
  • JAVA基础知识整理

    终于下定决心2020年转JAVA开发,自学之路坎坷曲折。俗话说的话,好记性不如烂笔头。如果有小伙伴们也像我一样在JAVA自学之路上徘徊,那就关注一下我的博客网站。我会不定期更新一下…

    2020年1月11日
    1.8K
  • spring4.x学习之用户登录与注册

    在之前的文章中我已经把后端工程项目创建好了,接下来就是编写项目了。 首先,我先创建一个数据库。数据库使用的是MySQL,数据库管理工具用的是Navicat。 打开数据库管理工具Na…

    2019年3月21日
    2.1K
  • JAVA学习之多线程知识点整理

    1、什么是进程?什么是线程? 进程是一个应用程序。线程是一个进程中的执行场景或者执行单元。一个进程可以启动多个线程。进程之间内存独立不共享。同一个进程中的线程之间,堆内存和方法区内…

    2020年6月19日
    1.3K
  • spring4.x学习之创建工程

    断断续续学习Java有两三个月了,目前还是处于入门阶段。关于java及spring那些的设计理念方面的理论知识,不花费大量精力及时间是看不懂的(至少对于我这么一个前端转后端的初学者…

    2019年3月19日
    1.9K
  • spring boot练习篇之用户登录系统【接口篇】

    写在前面 抛弃JSP,只做纯粹的前后端分离项目。 作为一个资深前端工作者,想要转JavaWeb开发,无论是书籍,还是网上视频、资料,竟然没有一篇能清楚明白地讲解怎样搭建一个前后端分…

    2021年5月25日
    1.7K
  • Java自学之继承

    在面向对象的设计过程中,类是基本的逻辑单位。但是对于这些基本的逻辑单位需要考虑到重用的设计问题,所以在面向对象的设计里提供有继承,并利用这一特点实现类的可重用性定义。 类继承定义 …

    2020年12月3日
    1.4K
  • Java自学之内部类

    内部类是一种常见的嵌套结构,利用这样的结构使得内部类可以与外部类共存,并且方便地进行私有操作的访问。 内部类基本概念 内部类(内部定义普通类、抽象类、接口的统称)是指一种嵌套的结构…

    2020年12月14日
    1.5K

发表回复

登录后才能评论