Java String的理解

Java String的理解

在Java中String是一个比较特殊的对象---不可继承,不可变,直接赋值创建

不可继承,不可变

  • String 类型被标final关键字修饰,所以不可继承
public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    // ....
}
  • Sting类中提供了一个final修饰的字符数组,用于存储Sting类型的值,所以一旦初始化则不能修改。
public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    private final char value[];

    public String() {
        this.value = "".value;
    }
}

String的创建

Sting类型是Java中最常用的一个对象,可以通过两种方式进行创建

  • 直接赋值
    因为比较常用,所以 JVM对String类型进行了优化,可以对String类型直接赋值,直接将该String类型创建在常量池中,以方便引用

JVM对直接赋值的String类型,会先从常量池中查询对应的String类型,如果没有则会创建一个存储到常量池中,然后返回该引用。

// 直接赋值
String s = "llll";

  • new关键字创建String对象
    new关键字创建的String对象的区别在于,会先在堆内存中进行初始化,然后到常量池中加载对应的String类型。返回堆内存中的地址值给引用
  • 两种方式的区别

String方法简介

构造方法

  • 基础构造方法
public String() {
    this.value = "".value;
}

public String(String original) {
    this.value = original.value;
    this.hash = original.hash;
}
  • 字符数组构造方法
// 根据整个字符数组创建字符串
public String(char value[]) {
    this.value = Arrays.copyOf(value, value.length);
}

//截取部分字符数组创建字符串
public String(char value[], int offset, int count) {
    if (offset < 0) {
        throw new StringIndexOutOfBoundsException(offset);
    }
    if (count <= 0) {
        if (count < 0) {
            throw new StringIndexOutOfBoundsException(count);
        }
        if (offset <= value.length) {
            this.value = "".value;
            return;
        }
    }
    // Note: offset or count might be near -1>>>1.
    if (offset > value.length - count) {
        throw new StringIndexOutOfBoundsException(offset + count);
    }
    this.value = Arrays.copyOfRange(value, offset, offset+count);
}
  • 根据Unicode编码进行创建字符串
// 没有使用过。。。
public String(int[] codePoints, int offset, int count) {
    if (offset < 0) {
        throw new StringIndexOutOfBoundsException(offset);
    }
    if (count <= 0) {
        if (count < 0) {
            throw new StringIndexOutOfBoundsException(count);
        }
        if (offset <= codePoints.length) {
            this.value = "".value;
            return;
        }
    }
    // Note: offset or count might be near -1>>>1.
    if (offset > codePoints.length - count) {
        throw new StringIndexOutOfBoundsException(offset + count);
    }

    final int end = offset + count;

    // Pass 1: Compute precise size of char[]
    int n = count;
    for (int i = offset; i < end; i++) {
        int c = codePoints[i];
        if (Character.isBmpCodePoint(c))
            continue;
        else if (Character.isValidCodePoint(c))
            n++;
        else throw new IllegalArgumentException(Integer.toString(c));
    }

    // Pass 2: Allocate and fill in char[]
    final char[] v = new char[n];

    for (int i = offset, j = 0; i < end; i++, j++) {
        int c = codePoints[i];
        if (Character.isBmpCodePoint(c))
            v[j] = (char)c;
        else
            Character.toSurrogates(c, v, j++);
    }

    this.value = v;
}
  • 根据字节数组创建字符串
// 需要指定编码集,根据传递的编码集解码
public String(byte bytes[], int offset, int length, String charsetName)
        throws UnsupportedEncodingException {
    if (charsetName == null)
        throw new NullPointerException("charsetName");
    checkBounds(bytes, offset, length);
    this.value = StringCoding.decode(charsetName, bytes, offset, length);
}
public String(byte bytes[], int offset, int length, Charset charset) {
    if (charset == null)
        throw new NullPointerException("charset");
    checkBounds(bytes, offset, length);
    this.value =  StringCoding.decode(charset, bytes, offset, length);
}

// 根据传入的字节数组和其长度创建字符串
public String(byte bytes[], int offset, int length) {
    checkBounds(bytes, offset, length);
    this.value = StringCoding.decode(bytes, offset, length);
}

public String(byte bytes[]) {
    this(bytes, 0, bytes.length);
}
  • 使用StringBuffer和StringBuilder创建字符串,不过不常用,可以使用这两个对象的toString方法创建字符串,更有效率

    public String(StringBuffer buffer) {
        synchronized(buffer) {
            this.value = Arrays.copyOf(buffer.getValue(), buffer.length());
        }
    }

    public String(StringBuilder builder) {
        this.value = Arrays.copyOf(builder.getValue(), builder.length());
    }
  • 预留方法,默认访问类型,通过直接赋值创建字符串
// 预留方法,默认访问类型,通过直接赋值创建字符串
String(char[] value, boolean share) {
    // assert share : "unshared not supported";
    this.value = value;
}

静态方法

  • valueOf()

调用toString()方法

public static String valueOf(Object obj) {
    return (obj == null) ? "null" : obj.toString();
}

public static String valueOf(int i) {
    return Integer.toString(i);
}

public static String valueOf(long l) {
    return Long.toString(l);
}

public static String valueOf(float f) {
    return Float.toString(f);
}

public static String valueOf(double d) {
    return Double.toString(d);
}

调用构造

public static String valueOf(char data[]) {
    return new String(data);
}

public static String valueOf(char data[], int offset, int count) {
    return new String(data, offset, count);
}

public static String valueOf(char c) {
    char data[] = {c};
    return new String(data, true);
}

public static String copyValueOf(char data[], int offset, int count) {
    return new String(data, offset, count);
}

public static String copyValueOf(char data[]) {
    return new String(data);
}

boolean

public static String valueOf(boolean b) {
    return b ? "true" : "false";
}
  • 格式化
public static String format(String format, Object... args) {
    return new Formatter().format(format, args).toString();
}

public static String format(Locale l, String format, Object... args) {
    return new Formatter(l).format(format, args).toString();
}

普通方法

intern()方法
可以通过调用该方法指向常量池中的对象

public native String intern();

参考源码

原文地址:https://www.cnblogs.com/jingwa/p/11606327.html

时间: 2024-10-15 11:29:50

Java String的理解的相关文章

我对java String的理解 及 源码浅析

每天起床告诉自己,自己的目标是 ”技术 + 英语 还有生活“! -泥沙砖瓦浆木匠 一.char说起到String 这也是自己第二次回过头来啃java基础书,小生自认为愚昧无知.如果大神有好的教育,可以评论私信.以下都是我的看法:为什么说char呢,我这里先卖个关子.在java中,char是用unicode编码的,占16位(2字节).从ansi编码(1字节)到unicode编码(2字节).Java中使用Unicode的原因是,Java的Applet(网页)运行,Unicode里面包含最多最广比如:

java String 深入理解

说出下面程序的输出 class StringEqualTest { public static void main(String[] args) { String s1 = "Programming";                String s2 = new String("Programming");                String s3 = "Program" + "ming";             

java String类型 深入理解

本文摘自:http://www.cnblogs.com/ITtangtang/p/3976820.html 这作者写的非常好,少许地方有笔误,值得收藏 在讲解String之前,我们先了解一下Java的内存结构. 一.Java内存模型 按照官方的说法:Java 虚拟机具有一个堆,堆是运行时数据区域,所有类实例和数组的内存均从此处分配. JVM主要管理两种类型内存:堆和非堆,堆内存(Heap Memory)是在 Java 虚拟机启动时创建,非堆内存(Non-heap Memory)是在JVM堆之外的

理解Java String和String Pool

本文转载自: http://blog.sina.com.cn/s/blog_5203f6ce0100tiux.html 要理解 java中String的运作方式,必须明确一点:String是一个非可变类(immutable).什么是非可变类呢?简单说来,非可变类的实例是不能被修改的,每个实例中包含的信息都必须在该实例创建的时候就提供出来,并且在对象的整个生存周期内固定不变.java为什么要把String设计为非可变类呢?你可以问问 james Gosling :).但是非可变类确实有着自身的优势

Java提高篇——理解String 及 String.intern() 在实际中的应用

1. 首先String不属于8种基本数据类型,String是一个对象.   因为对象的默认值是null,所以String的默认值也是null:但它又是一种特殊的对象,有其它对象没有的一些特性. 2. new String()和new String("")都是申明一个新的空字符串,是空串不是null: 3. String str="kvill":  String str=new String ("kvill");的区别: 在这里,我们不谈堆,也不谈

Java中String的理解

Java中String的理解 最近在读String的源码,看了些String的文章,自己对String作了下总结记录下来. 1.String为什么是不可变的? String是final类,不可继承,其方法也不可被覆盖,避免从子类操纵父类属性:String的值保存在private final char[]数组中,本质是一个字符数组,私有则外部不可访问和修改,final引用则引用(或说引用的值)不变.引用可以简单地认为是堆上对象的首地址.String内部的private int hash,缓存has

java常量池理解

String类两种不同的创建方式 String s1 = "zheng"; //第一种创建方式 String s2 = new String("junxiang"); //第二种创建方式 第一种创建方式是编译期在常量池中创建对象,如果常量池中已经存在"zheng"这个String对象,就将地址赋给s1.第二种创建方式是运行期在堆中创建对象,无论堆中是否已有都会重新创建一个对象. String s1 = new String("xyz&q

java String中的intern()

1 Java会确保一个字符串常量只有一个拷贝. 例1:String s0=”kvill”;  String s1=”kvill”;  String s2=”kv” + “ill”;  System.out.println( s0==s1 );  System.out.println( s0==s2 );  结果为:  true  true  因为例子中的s0和s1中的”kvill”都是字符串常量,它们在编译期就被确定了,所以s0==s1为true:而”kv”和”ill”也都是字符 串常量,当一个

【Java】深入理解ThreadLocal

一.前言 要理解ThreadLocal,首先必须理解线程安全.线程可以看做是一个具有一定独立功能的处理过程,它是比进程更细度的单位.当程序以单线程运行的时候,我们不需要考虑线程安全.然而当一个进程中包含多个线程的时候,就需要考虑线程安全问题,因为此时线程可能会同时操作同一个资源,当两个或者两个以上线程同时操作一个资源的时候,就会造成冲突.不一致等问题,即线程不安全. 解决线程安全问题,本质上就是解决资源共享问题,一般有以下手段: 1)可重入(不依赖环境):2)互斥(同一时间段只允许一个线程使用)