【小白的java成长系列】——String类的深入分析(基于源码)
来源:互联网 发布:软件质量保证的过程 编辑:程序博客网 时间:2024/05/01 18:00
接着前面面向对象来说吧~今天来说说String类。。其实String类也包含很多面向对象的知识的~
首先来问一个问题:我们在开发过程中,如果要使用一个类的话,就要创建对象,这句话没什么问题吧~在实际开发的时候确实是这样的,只有创建了对象才能真正的去使用一个普通的类,我们一般创建对象,几乎所有的类创建对象都是要通过new关键字来创建的~
问题就来了。。为什么我们的String可以直接写成String str = "abc";这样子呢?
当然String类也可以通过new来创建对象的。。。
其实也不难,我们看到它的源码说明就知道的:
* Strings are constant; their values cannot be changed after they * are created. String buffers support mutable strings. * Because String objects are immutable they can be shared. For example: * <p><blockquote><pre> * String str = "abc"; * </pre></blockquote><p> * is equivalent to: * <p><blockquote><pre> * char data[] = {'a', 'b', 'c'}; * String str = new String(data); * </pre></blockquote><p>
进入String的源码,最前面就能看到上面的文字的:大致的意思是,String的对象值其实是通过char[]数组来存储的,String str = "abc";等同于char data[] = {'a', 'b', 'c'}; String str = new String(data);明白清晰了吧~
1、String类的定义:
public final class String implements java.io.Serializable, Comparable<String>, CharSequence
问题:在开发过程中,我们可以继承String类吗?
答案:不行的,我们看定义就知道,String的定义使用了final修饰符,定义为了终结类,所以String是不能做扩展的。
implements:这个关键字是用来表示实现接口作用的,意思就是Serializable、Comparable和CharSequence都是接口的。
查看接口源码:
Comparable<T> :表示比较器作用,<T>采用了java泛型的形式
Serializable:
public interface Serializable {}
我们可以看到Serializable接口里面啥都木有,那为什么我们要实现这个接口呢?这个接口的作用是啥呢?
作用:java类的序列化,至于序列化,后面会详细介绍。其实Serializable是java的一个标记接口,什么叫标记接口?Serializable只是作为一个标记的作用,关于它具体的功能和作用交给了JVM底层去实现了,实现了这个接口,只是通知JVM,String这个类可以序列化。
CharSequence:表示字符序列吧~这个没啥好说的,String的存储方式依赖于字符序列的~
2、属性
private final char value[];//String值就是存储在value[]上的 private int hash; // Default to 0 表示hash值, private static final long serialVersionUID = -6849794470754667710L;//序列化作用 private static final ObjectStreamField[] serialPersistentFields = new ObjectStreamField[0];//序列化作用
我们只要了解String类的属性就可以,几乎都不会用到的,因为都是定义成了private,私有化了~
3、构造方法这里也只说几个特殊的,一般在开发过程中也不会用到构造方法的,因为很少使用new来创建String对象的,都是直接使用String str = "abc";这样子的形式。。
在面试过程中,很多面试官会问到String str = new String("abc");这个创建了几个对象?至于答案和解释,这边就不做介绍了,想知道的就去网上查找了解~这个涉及到底层的内存问题的,描述起来篇幅会很长的~
public String(String original) { this.value = original.value; this.hash = original.hash; }从上面可以看到,String两个核心就是value和hash的,这两个值基本决定了String对象的。
public String(char value[]) { this.value = Arrays.copyOf(value, value.length); }这个是通过底层数组拷贝的方式创建,其实底层使用的是System.arrayCopy()这个方法,此方法使用了native修饰的,底层是由C/C++来实现的,其实就是一个拷贝的作用。
public String(byte bytes[], int offset, int length) { checkBounds(bytes, offset, length); this.value = StringCoding.decode(bytes, offset, length); }这个表示的是通过字节(byte)来构造字符串,其实底层的实现也是通过System.arrayCopy()这个方法的。
其他的基本也没什么好说的,了解一下就可以的。我们可以看到有些构造使用了@Deprecated注解,这个注解表示的过时,不推荐使用这个方法的。
4、常用方法
public int length() {//返回字符串长度 return value.length; }public boolean isEmpty() {//判断字符串是不是为空 return value.length == 0; }public char charAt(int index) {//字符串中的某个字符,index表示字符的位置 if ((index < 0) || (index >= value.length)) { throw new StringIndexOutOfBoundsException(index); } return value[index]; }public byte[] getBytes() {//获取字节数组 return StringCoding.encode(value, 0, value.length); }public boolean equals(Object anObject) {//字符串比较,我们知道基本类型的比较都是通过==来做比较的,//但是字符串需要使用此方法来做比较的
我们主要来验证一下==和equals方法
package me.javen.oop;public class StringDemo {public static void main(String[] args) {String str1 = "hello" ;// 直接赋值String str2 = new String("hello") ;// 通过new赋值String str3 = str2 ;// 传递引用System.out.println("str1 == str2 --> " + (str1==str2)) ;// falseSystem.out.println("str1 == str3 --> " + (str1==str3)) ;// falseSystem.out.println("str2 == str3 --> " + (str2==str3)) ;// true//以下通过equals方法System.out.println("str1 equals str2 --> " + (str1.equals(str2))) ;// trueSystem.out.println("str1 equals str3 --> " + (str1.equals(str3))) ;// trueSystem.out.println("str2 equals str3 --> " + (str2.equals(str3))) ;// true}}此外还有一个比较方法也用得比较多:
public boolean equalsIgnoreCase(String anotherString) {//不分大小写比较
public boolean startsWith(String prefix) {//判断字符串是不是以prefix开头public boolean endsWith(String suffix) {//判断字符串是不是以suffix结尾public int hashCode() {//获取字符串的hash值public int indexOf(String str) {//获取字符str的起始位置,-1表示没有这个字符 return indexOf(str, 0); }public String substring(int beginIndex, int endIndex) {//截取字符串beginIndex表示起始位置,endIndex表示结束位置public String replaceAll(String regex, String replacement) {//字符串替换replacement替换regexpublic String[] split(String regex) {//分隔字符串,regex表示分隔符public String toLowerCase() {//将字符串全部转换为小写public String toUpperCase() {//将字符串全部转换为大写public String trim() {//去掉首尾空格,字符中间的空格不能去掉public static String valueOf(Object obj) {//将obj转换成字符串,这个可以传递任意类型,比如数字,字符,浮点数等等
此外还有其他的很多方法,这边就不列举出了,学习者可以通过代码的方式去使用这些个方法,列举出来的表示开发中常用的方法~
- 【小白的java成长系列】——String类的深入分析(基于源码)
- 【小白的java成长系列】——顶级类Object源码分析
- 【小白的java成长系列】——java关键字
- 【小白的java成长系列】——Java基础知识
- 【小白的java成长系列】——this关键字
- 【小白的java成长系列】——多线程初识(多人买票问题)
- 【小白的java成长系列】——构造方法私有化(单例设计)
- 【小白的java成长系列】——linux下的java环境变量设置
- 【小白的java成长系列】——java ide 开发工具eclipse的操作
- 【小白的java成长系列】——windows下搭建和配置java环境
- 深入java String JVM对String对象的连接优化 一(源码分析)
- 【小白的java成长系列】——Eclipse最常用快捷键
- 【小白的java成长系列】——面向对象基础
- Java源码分析——String的设计
- JAVA中String的纵向分析深入
- 深入java String拼接和StringBuffer、StringBuilder(分析源码)
- 目前看到的最棒的HashMap源码分析(基于java 8)--Java 8系列之重新认识HashMap
- 小白成长记——Java基础之File类的使用
- 遍历数组
- json相关 important!!!!
- C/C++的程序占用的内存分布
- static与const
- Myeclipse中Tomcat的两种部署方式
- 【小白的java成长系列】——String类的深入分析(基于源码)
- python idle 清屏问题的解决
- inet_ntoa的返回值类型错误
- [JavaScript]-----函数
- ViewFlipper
- 关于httpclient 请求https (如何绕过证书验证)
- android:点击左边按钮增加数值,点击右边按钮减小数值
- 代码坏味道之夸夸其谈的未来性
- Failure [INSTALL_FAILED_OLDER_SDK] Android-L