java—09 数组+ String类

一、数组

数组初始化

java声明数组的时候不能指定其长度(元素的个数),一旦初始化完成,就不能改变了。

public class Test {

 public static void main(String[] args) throws Throwable{
     int[] a = {1,2,3};//静态
     System.out.println(a[0]);// 1
     
     int[] b = new int [4];//动态
     b[3]= 20;
     System.out.println(b[3]);// 20
 }
}

二、String类

2.1 认识hashCode

hashCode()是一个对象在堆中的内存地址通过hash算法进行了进制的转换得到int返回值。
如果两个对象的hashCode()值一样则他们是同一个对象。
hashCode()的作用:
1. 一个对象是否存在。
2. 两个对象是否是同一个对象。
3. 两个对象的hashCode值比较相当于引用之间使用"==",只比较地址,不比较值。

2.2 认识hash

翻看String中源码:

初始为0
 private int hash; // Default to 0
  public String(String original) {
        this.value = original.value;
        this.coder = original.coder;
        this.hash = original.hash;
    }
调用hashcode后,才会给对象的hash属性赋值:
public int hashCode() {
        int h = hash;
        if (h == 0 && !hashIsZero) {
            h = isLatin1() ? StringLatin1.hashCode(value)
                           : StringUTF16.hashCode(value);
            if (h == 0) {
                hashIsZero = true;
            } else {
                hash = h;
            }
        }
        return h;
    }

2.3 关于 String str = “abc”;(摘)

String str = “abc”;
编译的时候,编译器只会检查"="两边是否是同一类型(或者是多态),如果是,编的过程就结束了,译的过程中发现,有"abc"这样的字面量,它会把它看成是常量,放入到常量表中。
运行的时候,首先进行类加载,将源程序的字节码文件中的内容加载到方法区内存中,这时候JVM就会去检查有没有特殊的要处理的内容,如果有static修饰的变量,static代码块,常量等等,就会在类加载的时候先执行,执行完以后存入方法区内存,常量存入常量池中。
在类加载完以后,程序开始运行,执行到 String str = “abc”;的时候,将常量池中的"abc"的内存地址赋值给引用类型String str。这个String str是在栈内存空间中分配空间,用来存储"abc"的内存地址。从此,str所代表的内存空间中存放的是"abc"在方法区内存中的常量池中的内存地址。

在这里插入图片描述

2.4 关于 new String(String original)

在new的时候,字符串类型的实参在堆里面有,常量池里面也有。

String类的new String(String original)构造方法的实现:
 public String(String original) {
        this.value = original.value;
        this.hash = original.hash;
    }
String类有两个成员属性:
private final char value[];
private int hash; //这里是默认为0

// 老师讲解的正常写法应该是这样的:
public String(char[] value, int hash) {
    this.value = value;
    this.hash = hash;
}

public String(String original) {
    this.value = original.value;
    this.hash = original.hash;
}

这里的this.value = original.value;
        original.value是original对象中数组的地址。
       
        String str = new String("hello");
            构造方法中的形式参数:String original
            调用时传入的实际参数:"hello"
            String original = "hello";
	1、字面量"hello"是一个常量,在方法区内存中的字符串常量池中。
    2、字符串常量池中存放的字符串是“对象”形式存放的。
    3、String是引用类型,它表示字符串这一类对象。
          

在这里插入图片描述

2.5 字节数组和String的相互转换问题

public class Test {
    public static void main(String[] args) throws Throwable{
        String str1 = "2021牛年!";
        byte[] strBytes = str1.getBytes("GBK");//字符串打成GBK形式的字节流

        for (int i = 0; i < strtoBytes.length; i++) {

            System.out.println("0x" + Integer.toHexString(strtoBytes[i]));
        }
        System.out.println();
/*0x32
0x30
0x32
0x31
0xffffffc5
0xffffffa3
0xffffffc4
0xffffffea
0xffffffa3
0xffffffa1
*/
        String string  = new String(strtoBytes, "GBK");//又变回字符串
        System.out.println(string);//      2021牛年!

        byte[] bytes = new byte[5];
        for (int i = 0; i < bytes.length ; i++) {
            bytes[i] = (byte)(96+2);
        }
        String ter = new String(bytes, "utf8"); //字节流变回字符串
        System.out.println(ter);//      bbbbb
    }
}

2.6 StringBuilder 和 StringBuffer

2.6.1 String VS StringBuilder

1、String是不可变类,一旦String对象被创建,包含在对象中的字符序列是不可变的,直到对象被销毁;
StringBuffer 与 StringBuilder对象则是可变的
2、String和StringBuilder的底层都是char数组String的char[] 是final修饰的,只能被赋值一次
StringBuilder的char[]数组不被final修饰

2.6.2 StringBuilder的构造方法

1. StringBuilder源码:

public final class StringBuilder
    extends AbstractStringBuilder //父类是AbstractStringBuilder
    implements java.io.Serializable, Comparable<StringBuilder>, CharSequence
{xxx}
// 无参构造

public StringBuilder() {
        super(16);           
}
char[] value数组的初始容量是:16
2. 有参构造直接调用了父类的
public StringBuilder(int capacity) {
        super(capacity);
    }
    
    父类的有参构造:
public AbstractStringBuilder(int capacity) {
    	if (COMPACT_STRINGS) {
            value = new byte[capacity];
            coder = LATIN1;
        } else {
            value = StringUTF16.newBytesFor(capacity);
            coder = UTF16;
        }	
}
3. 字符串的拼接
 // String类型的对象作为参数
public StringBuilder append(String str) {
        super.append(str);
        return this;
    }
public StringBuilder(String str) {
        super(str.length() + 16);
        append(str); //字符串长度应该是传入字符串长度+16
    }  

最后使用StringBuilder中的toString方法打印出结果 
 @Override
    public String toString() {
        return new String(value, 0, count);// value.length = 16        
    }
// 这个方法被调用以后,方法区内存中的字符串常量池里才会有一个String常量。

输出“abc niu”:
public static void main(String[] args){
        StringBuilder strb = new StringBuilder("abc");
        strb.append(" ");
        strb.append("n");
        strb.append("i");
        strb.append("u");
      // abc,  ,n, i, u, abc niu
        System.out.println(strb);//abc niu

        String str = "abc";
        str = str + 'n';
        str = str + 'i';
        str = str + 'u';
     // abc, abc , abc n,abc ni,abc niu
        System.out.println(strb);//abc niu
    }
   
可以看见,采用string浪费空间。
而相比之下,StringBuilder可以节省空间
因为StringBuilder和StringBuffer底层有一个字符缓存数组
追加的字符串,不会直接放入字符串常量池中,会先放入堆中的缓存字符数组中。
直到调用toString方法才将最后的结果放入常量池中,这也是StringBuilder为什么优于String,不会随便在常量池中占位置。
注意:只有String类型的才存放到常量池中。
StringBuilder和StringBuffer,不是String类型的。

2.6.3 StringBuffer

StringBuffer: 是线程安全的,效率低,字符序列是可变的(通过append等方法操作);
StringBuilder: 是线程不安全的,效率高点;

1、StringBuffer  和  String之间的转换;

String toString() 返回此序列中数据的字符串表示形式。
  public static void main(String[] args){
        StringBuffer strbf = new StringBuffer("abc");
        System.out.println(strbf.toString());
    }
    
StringBuffer(String str):以指定的字符串创建StringBuffer对象。

2、StringBuffer方法:
 
StringBuffer insert(int offset, Object o) :将任意类型参数的字符串表示形式插入此序列中。 

StringBuffer delete(int start, int end) :移除此序列的子字符串中的字符。 

StringBuffer deleteCharAt(int index): 移除此序列指定位置的 char

总结:String完结。。。。。。在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值