三个特殊类——String类:

三个特殊类——String类:

  • String类;
  • Object类;
  • 包装类;

(1)String类的两种实例化方式:

①——直接赋值
例如:String str = “hello”;

  • String是一个类,类是引用数据类型,所有引用数据类型在堆上存放着,也就是说,“hello”也在堆上存放着。总而言之一句话:String类直接赋值,在堆上开辟空间。
  • 只有String类才可以直接赋值,而其他的类都需要new操作一下。

②——通过构造方法实例化对象(传统的方式):

String类的构造方法有很多,下面只是其中一个:

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

——用上面的构造方法实例化String类:
例如:String str = new String(“hello”);

(2)字符串的比较:

通过equals()方法,这才比较的是字符串的内容。

equals()方法的源码:

public boolean equals(String anotherString){
	、、、、;
}

[注意]:
没有使用static关键字,就说明是一个成员方法,那就需要通过对象调用,比如:str1.equals(another String)。

相关代码如下:

public class test1 {
    public static void main(String[] args) {
         // 当是两个整型变量进行比较时(基本数据类型):
        int i1 = 10;
        int i2 = 10;
        //比较的是两个变量的值:返回true
        System.out.println(i1 == i2);

        // 当是两个String类的字符串进行比较时(引用数据类型在堆上存放):
        /**注意:String是引用数据类型,那么存放的就是str1与str2的地址,即
         “==”比较的就是str1与str2的地址,因此会返回false,所以字符串的比
         较利用String类提供的equals()方法。
         */
        String str1 = "hello";
        String str2 = new String("hello");
        //地址的比较
        System.out.println(str1 == str2);
        //字符串内容的比较
        System.out.println(str1.equals(str2));
    }
}

[注意]:

  • "=="比较的是两个字符串的地址;
  • "equals"比较的是两个字符串的内容;

(3)字符串常量(" "括起来的)是String类的匿名对象

public class test1{
    public static void main(String[] args) {
        //假设用户输入为str1,推荐使用第二种
        String str1 = null;
        //System.out.println(str1.equals("hello"));当用户输入为空时,就是说对象不存在,不存在的对象去调用equals()方法与"hello"进行比较,就会产生空指针异常,而下面的就不存在这种情况
        System.out.println("hello".equals(str1));
    }
}

[注意]:
在以后的开发中,如果要判断用户输入的字符串是否等同于特定字符串,一定要将特定字符串(String常量)写在前面,避免NullPointerException。

(4)问题引入:

▼——采用String类的直接赋值进行比较:

public class test1 {
    public static void main(String[] args) {
        String str1 = "hello";
        String str2 = "hello";
        String str3 = "hello";
        System.out.println(str1.equals(str2));
        System.out.println(str2.equals(str3));
        System.out.println(str3.equals(str1));
        
        //这里为什么没有开辟新的空间呢?因为采用了共享的设计模型
        System.out.println(str1 == str2);
        System.out.println(str2 == str3);
        System.out.println(str1 == str3);
    }
}

[解释]:
在JVM底层实际上会自动维护一个对象池(字符串对象池,就是一个对象数组),如果现在采用了直接赋值的模式进行String类的对象实例化操作,那么该实例化对象(字符串内容)将自动保存在这个对象池中,如果下次继续使用直接赋值的模式声明String类对象,此时对象池之中如果有指定的内容,将直接进行引用;如果没有,则开辟新的字符串对象而后将其保存在对象池之中以供下次使用。

▼——通过构造方法new:
例如:String str = new String(“hello”);
程序从右向左执行,这里就会产生两个对象,一个是"hello"字符串常量产生的String类的匿名对象,也就是所谓的垃圾空间;一个是str所指向的对象。

——在String类中有一个方法叫做手工入池:
public native String intern();

  • 没有static声明,还是一个成员方法,需要通过对象调用;
  • 只有方法声明,而没有方法体,叫做本地方法,并不是抽象方法,只是java调用了c语言的同名函数,叫intern(),代表函数体在其他语言中。

[总结]:
通过上述分析可知,如果使用String类构造方法就会开辟两块堆内存空间,并且其中一块对内存将成为垃圾空间,除此之外,也会对字符串共享产生问题。

——解释String类中两种对象实例化的区别?

  • 直接赋值:只会开辟一块堆内存空间,并且该字符串可以自动保存在对象池中以供下次使用;
  • 构造方法:会开辟两块堆内存空间,其中一块成为垃圾空间,不会自动保存在对象池中 ,可以使用intern()方法手工入池;

(5)字符串常量不可变更:

字符串一旦定义后不可改变。

可以发现,原来的匿名对象内容一直没有改变,改变的是引用,也就是str1的指向,这样就会形成大量的垃圾空间,在之后的开发中,应该杜绝使用。

▼——三个原则:

  1. 字符串使用就采用直接赋值;
  2. 字符串比较就使用equals();
  3. 字符串别改变太多次(原则上不超过3次);

(6)字符与字符串的相互转换:

6.1——字符数组与字符串的相互转换(重要):
public String(char[] value)
public String(char[] value, int offset(开始位置), int count(数量))

——相关代码:

public class test1{
    public static void main(String[] args) {
        char[] data = new char[]{'h','e','l','l','o'};
        //public String(char[] value):全部元素都转变
        String str = new String(data);
        System.out.println(str);

        //public String(char[] value, int offset, int count):部分转换
        String str1 = new String(data, 0, 3);
        System.out.println(str1);
    }
}

6.2——将字符串转为单个字符:

public char charAt(int index);

  • 取得指定索引位置的字符,索引从0开始;
  • 没有static修饰,所以是对象方法,通过对象.方法直接调用。
public class test1{
    public static void main(String[] args) {
        char c = "hello".charAt(1);//注意:索引从0开始,不能越界
        System.out.println(c);
    }
}

6.3——将字符串转化为字符数组:
String->char[]
public char[] toCharArray();

  • 没有static修饰,所以是对象方法,通过对象.方法直接调用。
public class test1{
    public static void main(String[] args) {
        String str = "hello";
        char[] data = str.toCharArray();
        //数组具有的属性length,如果可以使用数组的length,就证明是数组了
        System.out.println(data.length);
        System.out.println("hello".length());
    }
}

[注意]:

  • 取得字符串的长度:public int length();
  • 取得字符数组的长度:数组.length;

[例题]——现在有一个字符串,判断其是否是由数字组成:

public class test1{
    public static void main(String[] args) {
        String str = "1234a56";
        System.out.println(isNumbers(str));
    }
    public static boolean isNumbers(String str){
        char[] data = str.toCharArray();
        for(int i = 0; i < data.length; i++){
            //判断每一个字符是否在‘0’—‘9’:
            if(data[i] < '0' || data[i] > '9'){
                //不是数字,停止遍历:
                return false;
            }
        }
        return true;
    }
}

(7)字节(byte)与字符串:

7.1将字节数组转化为字符串(重要):
[注意]:

  • 字节常用于数据传输与编码转换的处理之中;
  • 在String类中提供有对字节的支持;

▼——byte->string:
public String(byte byte[]);(构造方法)
public String(byte byte[], int offset, int length);(构造方法)

public class test1{
    public static void main(String[] args) {
        //字节数组:
        byte[] data = new byte[]{1,5,6,7,9};
        String str = new String(data);
        System.out.println(str);
    }
}

7.2将字符串转为字节数组(重要):
▼——String->byte[]
public byte[] getBytes();

public class test1{
    public static void main(String[] args) {
        String str = "hello";
        byte[] data = str.getBytes();
        for(int i = 0; i < data.length; i++){
            System.out.print(data[i]+"、");
        }
    }
}

7.3将字符串按照指定编码转为字节数(编码转换处理):
public byte[] getBytes(String charsetName) throws UnsupportedEncodingException

public class test1{
    public static void main(String[] args) throws Exception{
        String str = "hello";
        byte[] data = str.getBytes("ISO-8859-1");
        for(byte b:data){
            System.out.print(b+"、");
        }
    }
}

(8)字符串比较:

8.1区分大小写的比较:
public boolean equals(Object anObject);

public class test1{
    public static void main(String[] args) {
        String str1 = "hello";
        String str2 = "Hello";
        System.out.println(str1.equals(str2));//false
        String str3 = "hello";
        System.out.println(str1.equals(str3));//true
    }
}

8.2不区分大小写的比较:
public boolean equalsIgnoreCase(String anotherString);

public class test1{
    public static void main(String[] args) {
        String str1 = "hello";
        String str2 = "Hello";
        System.out.println(str1.equalsIgnoreCase(str2));//true
    }
}

8.3比较两个字符串大小关系:
public int compareTo(String anotherString);

  • 返回值 > 0:表示大于比较对象;
  • 返回值 = 0:两者相等;
  • 返回值 < 0:表示小于比较对象;

[注意]:
只要两个字符串对应位置不一样,就会判断,不会继续往后走!

public class test1{
    public static void main(String[] args) {
        System.out.println("A".compareTo("a"));//-32,A=65;a=97
        System.out.println("a".compareTo("A"));//32
        System.out.println("A".compareTo("A"));//0
        System.out.println("AB".compareTo("AC"));//-1
        System.out.println("刘".compareTo("杨"));//-5456
    }
}

(9)字符串查找(重要):

▼——判断一个子字符串是否存在:
public boolean contains(CharSequence s);

public class test1{
    public static void main(String[] args) {
        String str1 = "hello word!";
        System.out.println(str1.contains("o word"));
    }
}

▼——判断是否以指定的字符串开始:
public boolean startsWith(String prefix);

public class test1{
    public static void main(String[] args) {
        String str1 = "hello word!";
        System.out.println(str1.startsWith("hel"));
    }
}

▼——从指定位置开始判断是否以指定字符串开头:
public boolean startsWith(String prefix, int toffset);

public class test1{
    public static void main(String[] args) {
        String str = "e";
        String str1 = "hello";
        System.out.println(str1.startsWith(str,3));
    }
}

——以下为了解:
▼——从头开始查找指定字符串的位置,查到了返回位置的开始索引,如果查不到返回-1:
public int indexOf(String str);

public class test1{
    public static void main(String[] args) {
        String str = "e";
        String str1 = "hello";
        System.out.println(str1.indexOf(str));//返回1
        System.out.println(str1.indexOf("a"));//返回-1
    }
}

▼——从指定位置查找子字符串的位置:

public int indexOf(String str,int fromIndex);

public class test1{
    public static void main(String[] args) {
        String str = "e";
        String str1 = "helle";
        System.out.println(str1.indexOf(str,2));//返回4
        //从str1字符串的2位置查找str内容
    }
}

▼——由后向前查找子字符串的位置:
public int lastIndexOf(String str);

public class test1{
    public static void main(String[] args) {
        String str = "e";
        String str1 = "helle";
        System.out.println(str1.lastIndexOf(str));//只返回4
        //从后向前的遍历str1,查找str从后向前第一次出现的位置 
    }
}

▼——从指定位置由后向前查找子字符串:
public int lastIndexOf(String str, int fromIndex);

public class test1{
    public static void main(String[] args) {
        String str = "e";
        String str1 = "helle";
        System.out.println(str1.lastIndexOf(str,3));//返回1
        //从指定位置开始从后向前的遍历str1,查找str从后向前第一次出现的位置
    }
}

▼——判断是否是以指定字符串结尾:
public boolean endsWith(String suffix);

public class test1{
    public static void main(String[] args) {
        String str1 = "helle";
        System.out.println(str1.endsWith("le"));//返回true
    }
}

(10)字符串替换:

▼——替换所有的指定内容:
public String replaceAll(String regex, String replacement);

public class test1{
    public static void main(String[] args) {
        String str1 = "hello";
        System.out.println(str1.replaceAll("l","A"));
        //将str1中的“l”都替换为“A”
    }
}

▼——替换首个内容:
public String replaceFirst(String regex, String replacement);

public class test1{
    public static void main(String[] args) {
        String str1 = "hello";
        System.out.println(str1.replaceFirst("l","A"));
        //将str1中第一次出现的“l”替换为“A”
    }
}

(11)字符串拆分:

▼——将字符串全部拆分:
public String[] split(String regex);

示例1:

public class test1{
    public static void main(String[] args) {
        String str1 = "hello world hello bit";
        //按照“o”进行拆分:
        String[] result = str1.split("o");
        for(String s: result){
            System.out.println(s);
        }
    }
}

示例2:

public class test1{
    public static void main(String[] args) {
        String str1 = "hello world hello bit";
        //按照“o”进行拆分:
        String[] result = str1.split(" ");
        for(String s: result){
            System.out.println(s);
        }
    }
}


示例3:
[注意]:
有转义字符的拆分。

public class test1{
    public static void main(String[] args) {
        String str = "196.128.1.1";
        String[] result = str.split("\\.");
        for(String s:result){
            System.out.println(s);
        }
    }
}

▼——将字符串部分拆分,该数组长度就是limit极限:
public String[] split(String regex, int limit);

[注意]:
当是String[] result = str1.split(" ",5)时,空格本来有3个,但是现在却是5,结果就是按照空格进行全部拆分,也就是说,大于等于,也可以。

public class test1{
    public static void main(String[] args) {
        String str1 = "hello world hello bit";
        //按照“o”进行拆分:
        String[] result = str1.split(" ",2);
        for(String s: result){
            System.out.println(s);
        }
    }
}

(12)字符串截取:

▼——从指定索引截取到结尾:
public String substring(int beginIndex);

public class test1{
    public static void main(String[] args) {
        String str = "hello";
        System.out.println(str.substring(2));//结果是:llo
    }
}

▼——截取部分内容:
public String substring(int beginIndex, int endIndex);

public class test1{
    public static void main(String[] args) {
        String str = "hello";
        System.out.println(str.substring(2,4));//结果是:ll—>[2,4)
    }
}

(13)字符串的其他方法:

▼——去掉字符串中的左右空格,保留中间空格:
public String trim();

public class test1{
    public static void main(String[] args) {
        String str = "      he llo ";
        System.out.println(str.trim());
    }
}

▼——字符串转大写:
public String toUpperCase();

public class test1{
    public static void main(String[] args) {
        String str = "      he llo ";
        System.out.println(str.toUpperCase());
    }
}

▼——字符串转小写:
public String toLowerCase();

public class test1{
    public static void main(String[] args) {
        String str = "HELlo";
        System.out.println(str.toLowerCase());
    }
}

▼——字符串入池操作:
public native String intern();

▼——字符串连接,等同于“+”,不入池:
public String concat(String str);

▼——取得字符串长度:
public int length();

▼——判断是否为空字符串,但不是null,而是长度为0:
[注意]:
这个方法不能判断str = null;会出现空指针异常!
isEmpty()这个方法只能判断空字符窜,不能判断空指针。
public boolean isEmpty();

public class test1{
    public static void main(String[] args) {
        String str = "HELlo";
        System.out.println(str.isEmpty());
    }
}

[注意]:
String类中并没有提供首字母转大写的方法,需要自己实现:
思路:通过字符串的截取以及转大写方法。

public class test1{
    public static void main(String[] args) {
        System.out.println(firstCaseUp("heLLo"));
    }
    public static String firstCaseUp(String str){
        return str.substring(0,1).toUpperCase()+str.substring(1);
    }
}

(14)两只sb——StringBuffer类:

▼——String类的特点:
任何的字符串常量都是String对象;
String的常量一旦被声明就不可更改,如果改变了对象的内容,只是其引用的指向发生改变而已;

▼——引入StringBuffer类:
在String类中,使用“+”进行字符串的拼接;
在StringBuffer类中,使用append()方法进行字符串的拼接;

▼——引入StringBuffer类的目的:
由于String类的不可更改特性,为了方便字符串的修改,提供了StringBuffer类。

——a、字符串的修改:
public StringBuffer append(各种数据类型);

public class test1{
public static void main(String[] args) {
StringBuffer sb = new StringBuffer();
sb.append(“hello”).append(" world").append(10);
System.out.println(sb);
}
}

——b、StringBuffer<——>String:

■String——>StringBuffer:

调用StringBuffer的构造方法或者append()方法。

■StringBuffer——>String:

调用StringBuffer的toString()方法。

[相互转化的参考代码]:

public class test1{
    public static void main(String[] args) {
        //① 通过构造方法转换:
        StringBuffer sb = new StringBuffer("hello");
        System.out.println(sb);

        //②通过append()方法转换:
        StringBuffer sb1 = new StringBuffer();
        sb1.append("hello");
        System.out.println(sb1);

        //③通过toString()方法转回为String类:
        String result1 = sb.toString();
        String result2 = sb1.toString();
        //证明result1与result2是String类:通过调用字符串才有的方法
        System.out.println(result1.isEmpty());
        System.out.println(result2.isEmpty());
    }
}

——c、这两个类的继承结构:

	■String:

public final class String implements java.io.Serializable,Comparable,CharSequence;

	■StringBuffer:

public final class StringBuffer extends AbstractStringBuilder implements java.io.Serializable,CharSequence;

——d、StringBuffer特有的方法:

▼——字符串反转:
public synchronized StringBuffer reverse();

public class test1{
    public static void main(String[] args) {
        StringBuffer sb = new StringBuffer("hello");
        System.out.println(sb.reverse());
    }
}

▼——删除指定范围的数据:
public synchronized StringBuffer delate(int start, int end);

public class test1{
    public static void main(String[] args) {
        StringBuffer sb = new StringBuffer("helloworld");
        System.out.println(sb.delete(2,5));//同样是[2,5)
    }
}

▼——插入数据:
public synchronized StringBuffer insert(int offset, 各种数据类型 b);

public class test1{
    public static void main(String[] args) {
        StringBuffer sb = new StringBuffer("helloworld");
        System.out.println(sb.insert(0,"你好"));
    }
}

(15)两只sb——StringBuild类:

StringBuild类的方法与StringBuffer类的一模一样。

[问题]:
请解释String、StringBuffer、StringBuild的区别?

  1. String类的内容不可以修改,而StringBuffer与StringBuild的内容可以修改;
  2. StringBuffer采用了同步处理,线程安全,效率低;而StringBuilder采用了异步处理,线程不安全,效率高;
  3. 在执行String与"+"进行字符串的拼接的时候,底层会将String转换为StringBuilder进行处理;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值