您的位置:首页 > 编程语言 > Java开发

Java笔记之string类简介和构造方法

2020-02-02 14:22 1301 查看

 

1、String是不可变类。

这句话想必大家已烂熟于心了,究其原因呢?一般以为:对象一旦创建完成是不会因外界的改变而改变

首先看一个简单的例子:

1 String str= "abc";
2 System.out.println("str: " + str);  // 输出s:abc
3 str = "def";
4 System.out.println("str: " + str);  // 输出s:def

此时看上去,str输出结果变了,那么是否与上面的说法自相矛盾呢?答案是否定的,因为str只是指向堆内存中的引用,存储的是对象在堆中的地址,而非对象本身,str本身存储在栈内存中。

实际上,此时堆内存中依然存在着"abc"和"def"对象。对于"abc"对象本身而言,对象的状态是没有发生任何变化的。

那么为什么String类具有不可变性呢,显然,既然不可变说明String类中肯定没有提供对外可setters方法。接下来来具体看一下String类的定义。

下面是String类中主要属性的定义(Java 1.7源码):

   public final class String implements java.io.Serializable, Comparable<String>, CharSequence{
private final char value[];
private int hash; // Default to 0
}

与之前版本的Java String源码相比,String类减少了int offset 和 int count的定义。这样变化的结果主要体现在:

1.避免之前版本的String对象subString时可能引起的内存泄露问题;

2.新版本的subString时间复杂度将有O(1)变为O(n);

通过上面String类的定义,类名前面用了final class修饰,因此,String类不能被继承。对于其属性定义,可以看出,属性value[]和hash都是被定义成private类型,且由于没有提供对外的public setters方法,String类属性不可被改变。

其中,需要重点关注属性value[],其被final char修饰,因此字符型数组value只会被赋值一次就不可修改。其存储内容正好是String中的单个字符内容。

1.2创建String类的对象的两种方式:

  1. ""直接赋值法
  2. new关键字法

此处的==比较是内存地址,equal方法默认比较的也是内存地址,而此处string类重写了equal方法,将字符串转化为字符数组,比较的是字符数组中的字符内容是否一致。

Q:new string (“ABC”);创建了几个对象?

A:2个,一个是字符串常量池。另一个是位于堆内存中 

注:使用string的equal方法时,尽量使用常量作为方法的调用者,这样不会报错。

class MyString {

      public static void main (String [] args) {

      test(null);

    } 

      public static void test(String str){

       if("中国".equal(str)){

          System.out.println("回答正确");

        }else{

          System.out.println("回答错误");

        }     

    }

如果写成str.equal("中国"),如果传入的参数为null时,会报空指针异常。

2、string的构造方法

String(); 构造一个空字符串对象
String(byte[] bytes); 通过byte数组构造字符串对象
String(byte[] bytes,int offset,int length);通过byte数组,从offset开始,总共length长的字节构造字符串对象
String(char[] value); 通过char数组构造字符串对象
String(byte[] char,int offset,int length);通过char数组,从offset开始,总共length长的字节构造字符串对象
String(String original); 构造一个original的副本,拷贝一个original
String(StringBuffer buffer);通过StringBuffer数组构造字符串对象

 

 

public class Demo01 {     
        
    public static void main(String[] args) {             
            // 字节数组         
        byte[] bArray = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h' };

      // 字符数组 char[] cArray = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h' }; //声明一个StringBuffer StringBuffer strbuf = new StringBuffer("strbuf"); // 实例一个String对象 String str = new String("str abcd"); //实例一个String对象 通过一个btye数组构造字符串对象(字节数组) String strb = new String(bArray); //实例一个String对象 通过一个char数组构造字符串对象(字符数组) String strc = new String(cArray); //实例一个String对象 通过一个char数组构造字符串对象(字节数组,开始的数据,截得数据长度) String strbIndex = new String(bArray, 1, 5); //实例一个String对象 通过一个char数组构造字符串对象(字符数组,开始的数据,截得数据长度) String strcIndex = new String(cArray, 1, 2); //实例一个String对象 通过一个StringBuffer对象构造字符串对象

        StringBuilder strbuff =new StringBuilder();

        strbuff.append("jack"); 

String strbuff = new String(strbuf);
System.out.println("实例一个带参String对象:  "+str);
System.out.println("实例一个带byte数组参数String对象:  "+strb);
System.out.println("实例一个带char数组参数String对象:  "+strc);
System.out.println("实例一个带byte数组参数String对象,截取从1开始截取,截5位:  "+strbIndex);
System.out.println("实例一个带char数组参数String对象,截取从1开始截取,截2位:  "+strcIndex);
System.out.println("实例一个带StringBuffer参数String对象:  "+strbuff);
// 如果是字节类型,将输出地址
System.out.println(bArray);
// 如果是字符类型,将输出字符
System.out.println(cArray);
}
}

 输出的结果:

实例一个带参String对象: str abcd
实例一个带byte数组参数String对象: abcdefgh
实例一个带char数组参数String对象: abcdefgh
实例一个带byte数组参数String对象,截取从1开始截取,截5位: bcdef
实例一个带char数组参数String对象,截取从1开始截取,截2位: bc
实例一个带StringBuffer参数String对象: jack
[B@499a12ee
abcdefgh

 

转载于:https://www.cnblogs.com/AllenRandolph/p/6934113.html

  • 点赞
  • 收藏
  • 分享
  • 文章举报
dianzhuangan1167 发布了0 篇原创文章 · 获赞 0 · 访问量 167 私信 关注
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: