java中三个特殊的类------String类、Object类、包装类

1.String类

1.1 String类的两种实例化方式

  1. 直接赋值
    String str = "hello"
  2. 通过构造方法实例化String类
    String str = new String("hello")

1.2 字符串相等比较(内容)
public boolean equals(String anotherString);成员方法,需要通过对象调用
例:
str1.equals(str2);
看代码:

public class Test{
    public static void main(String[] args){
        String str1 = "hello";
        String str2 = new String("hello");
        System.out.println(str1 == str2);
        System.out.println(str1.equals(str2));
    }
}

输出结果:
false
true
这里就体现出equals()方法的作用了,str1 == str2这判断的是这两个字符串的地址是否相同,因为str2用了new,重新开辟了一个新空间,所以和str1的地址肯定是不相同的;但equals()比较的是两个字符串的内容,str1和str2内容相同,所以返回true。
看图:
在这里插入图片描述

1.3字符串常量是String的匿名对象
例:"hello".equals(str2);
这里有一个坑,如果我们使用:str.equals(“hello”),有可能会出现nullPointException(空指针异常)报错,因为str可能是一个空字符串。
所以记住,以后在开发中,如果要判断用户输入的字符串是否等同于特定字符串,一定要将字符串(String常量)写在前面。
1.4 对象池(对象数组)
我们先来看一段代码吧:

public class Test{
    public static void main(String[] args){
        String str1 = "hello";
        String str2 = "hello";
        System.out.println(str1 == str2);
    }
}

我们先来猜猜这个的返回值吧。肯定好多人都认为它返回的是false吧,但不是的,为了让你们相信,直接上图吧。
在这里插入图片描述
没错,它返回的就算true。
肯定有疑问了吧,上边不是说了str1 == str2比较的是地址吗?它两地址怎么会相等。
那是因为JVM底层会自动维护一个字符串的对象池,如果采用直接赋值的形式进行String的对象实例化 (这里要特别注意,如果使用了new,str1 == str2 )肯定是false,因为new就会开辟一个新空间,地址肯定不相等,这个对象会自动保存在这个对象池中。如果下次继续使用直接赋值的形式声明String类,这个时候,如果对象池中已经有了第二次声明的这个内容,则会直接引用,不会创建新的空间(所以str1的地址等于str2的地址);如果没有,则开辟新的堆空间后,再将其保存在对象池中供下次使用。
再画图解释一下吧:
在这里插入图片描述
1.5 字符串常量不可变更
字符串一旦定义后不可改变。因为字符串的底层实现就算字符数组,我们都知道,数组最大的一个缺陷就算它的长度是固定的,所以定义字符串的常量时,它的内容不可改变。
我们来看看这段代码:

public class Test{
    public static void main(String[] args){
        String str = "hello";
        System.out.println(str+"world");
    }
}

它的输出结果如下:
在这里插入图片描述
我们发现hello和world连接在了一起,不是说字符串内容一旦定义就不能改变吗?
其实这里并没有改变字符串内容,变的是字符串对象。我们来看实际的过程图;
在这里插入图片描述
说这个的目的何在呢?
因为改变的是对象的引用,前边的“hello”和"world"都成了垃圾空间,如果一直+下去,垃圾空间将会特别大。
1.6 字符与字符数组的相互转换
a. 将字符数组转为字符串

public String(char[] value)

public String (char[] value, int offest, int count)//offest表示从数组的哪个位置开始,count表示将count个字符转为字符串

例:

public class Test{
    public static void main(String[] args){
        char[] arr = {'h','e','l','l','o','w','o','r','l','d'};
        String str1 = new String(arr);
        String str2 = new String(arr, 5, 5);
        System.out.println(str1);
        System.out.println(str2);
    }
}

在这里插入图片描述
b. 将字符串转为单个字符

public char charAt(int index)

例:

public class Test{
    public static void main(String[] args){
        String str = "hello world";
        char c = str.charAt(4);
        System.out.println(c);
    }
}

在这里插入图片描述
c. 将字符串变为字符数组

public char[] toCharArray()

例:

public class Test{
    public static void main(String[] args){
        String str = "hello world";
        char[] arr = str.toCharArray();
        System.out.println(arr.length);
    }
}

在这里插入图片描述
1.7 字节(byte)与字符串
a. 将字节数组转为字符串

public String(byte[] value)

public String(byte[] value, int offest, int count)

b.将字符串转为字节数组

public byte[] getBytes()

例:

public class Test{
    public static void main(String[] args){
        String str = "hello world";
        byte[] data = str.getBytes();
        for(int i = 0; i < data.length; i++){
            System.out.print(data[i]+"、");
        }
        System.out.println();
        //将字节数组转换为字符串
        System.out.println(new String(data));
    }
}

在这里插入图片描述
1.8 字符串比较
a. 不区分大小写相等比较

public boolean equalsIgnoreCase(String anotherString)

例:

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

在这里插入图片描述
b. 比较两个字符串大小

public int compareTo(String anotherString)
  1. 返回大于0:表示大于比较对象
  2. 返回等于0:表示两者相等
  3. 返回小于0:表示小于比较对象

例:

public class Test{
    public static void main(String[] args){
        String str1 = "hello world";
        String str2 = "Hello World";
        System.out.println(str1.compareTo(str2));
    }
}

在这里插入图片描述
1.9 字符串查找

  1. public boolean contains(String str):判断str在本字符串中是否存在
    例:
public class Test{
    public static void main(String[] args){
        String str = "hello world";
        System.out.println(str.contains("ld"));
    }
}

在这里插入图片描述
2.public boolean startsWith(String str):判断是否以指定字符串开头
例:

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

在这里插入图片描述
3. public boolean startsWith(String str, int index):判断指定位置是否以指定字符串开头
例:

public class Test{
    public static void main(String[] args){
        String str = "hello world";
        System.out.println(str.startsWith("w", 6));
    }
}

在这里插入图片描述
4. public boolean endsWith(String str):判断是否以指定字符串结尾
例:

public class Test{
    public static void main(String[] args){
        String str = "hello world";
        System.out.println(str.endsWith("d"));
    }
}

在这里插入图片描述
1.10 字符串替换

  1. public String replaceAll(String regex, String replacement):替换所有指定内容
    例:
public class Test{
    public static void main(String[] args){
        String str = "hello world";
        System.out.println(str.replaceAll("l", "_"));
    }
}

在这里插入图片描述
2. public String replaceFirst(String regex, String replacement):替换首个指定内容
例:

public class Test{
    public static void main(String[] args){
        String str = "hello world";
        System.out.println(str.replaceFirst("l", "_"));
    }
}

在这里插入图片描述
1.11 字符串拆分
3. public String[] split(String regex):将字符串按照指定格式全部拆分
例:

public class Test{
    public static void main(String[] args){
        String str = "hello world";
        String[] result = str.split(" ");//按照空格拆分
        for(String s: result){
            System.out.println(s);
        }
    }
}

在这里插入图片描述
4. public String[] split(String regex, int limit):将字符串按照指定格式部分拆分,数组长度为limit
例:

public class Test{
    public static void main(String[] args){
        String str = "hello world haha";
        String[] result = str.split(" ", 2);
        for(String s: result){
            System.out.println(s);
        }
    }
}

在这里插入图片描述
1.12 字符串截取
5. public String substring(int beginIndex):从指定位置开始截取到字符串结尾
例:

public class Test{
    public static void main(String[] args){
        String str = "hello world haha";
        System.out.println(str.substring(3));
    }
}

在这里插入图片描述
6. public String substring(int beginIndex, int endIndex):截取部分
例:

public class Test{
    public static void main(String[] args){
        String str = "hello world haha";
        System.out.println(str.substring(3, 9));
    }
}

在这里插入图片描述
1.13 String类的其他方法
a. 去掉左右空格

public String trim()

例:

public class Test{
    public static void main(String[] args){
        String str = "   hello world haha ";
        System.out.println(str.trim());
    }
}

在这里插入图片描述
b. 字符串转大小写

public String toUpperCase()

public String toLowerCase()

例:

public class Test{
    public static void main(String[] args){
        String str = "hello world";
        String str1 = "HELLO";
        System.out.println(str.toUpperCase());
        System.out.println(str1.toLowerCase());
    }
}

在这里插入图片描述
c. 判断字符串是否为空(只能判断是否为空字符串而不是null)

public boolean isEmpty()

例:


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

在这里插入图片描述
在这里插入图片描述
1.14 两只sb(StringBuffer()、StringBuilder())----方便字符串的修改(前边说过String是不能修改字符串的)
a. 字符串修改

public StringBuffer append(各种数据类型)

例:

public class Test{
    public static void main(String[] args){
        StringBuffer sb = new StringBuffer();
        sb.append("hello").append("world");
        fun(sb);
        System.out.println(sb);
    }
    public static void fun(StringBuffer s){
        s.append("\n").append("Calm");
    }
}

在这里插入图片描述
b. StringBuffer与String的相互转换
(1)String转成StringBuffer
调用StringBuffer的构造方法或append()方法
(2)StringBuffer转为String
调用toStrig()方法
c. 字符串反转

public StringBuffer reverse()

例:

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

在这里插入图片描述
d. 删除指定范围的数据

public StringBuffer delete(int start, int end)

例:

public class Test{
    public static void main(String[] args){
        StringBuffer sb = new StringBuffer();
        sb.append("hello").append("world");
        System.out.println(sb.delete(2, 5));
    }
}

在这里插入图片描述
e. 插入数据

public StringBuffer insert(int offest, 各种数据类型)

例:

public class Test{
    public static void main(String[] args){
        StringBuffer sb = new StringBuffer();
        sb.append("hello").append("world");
        System.out.println(sb.insert(2, "你好"));
    }
}

在这里插入图片描述
总结
String、StringBuffer、StringBuilder的区别:

  1. String的内容不可以修改,而两只sb可修改内容(append)
  2. StringBuffer采用同步处理,线程安全,效率较低
  3. StringBuilder采用异步处理,线程不安全,效率较高。
    例:
		String s = "hello";
        System.out.println(s+"world");

底层会将String自动转换为StringBuilder。

2.Object类-----接收除基本类型所有的类的对象

Object是java默认提供的类

java中,除了Object类,所有的类都存在继承关系,默认会继承Object父类,所有类(除了8大基本类型(byte、short、int、long、float、double、char、boolean))对象都可以通过Object类进行接收。

2.1 取得对象信息-----toString()
直接使用对象的输出,默认输出一个地址编码,但如果输出的是String对象,此时会输出字符串的内容而不是地址,这是因为String覆写了Object的toString()方法。

System.out.println():系统输出默认会调用对象的toString(),也就算说,一旦出现System.out.println(),其实就算调用了toString(),输出的是toString()里的东西。

例:

class Person{
    private int age;
    private String name;

    public Person(int age, String name) {
        this.age = age;
        this.name = name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {

        return age;
    }

    public String getName() {
        return name;
    }
}
public class Test{
    public static void main(String[] args){
        Person person = new Person(18,"张三");
        System.out.println(person);
    }
}

在这里插入图片描述
从输出结果可以看出,输出的是一个地址编码,这个地址就算Person类的地址。
现在我们想要输出年龄和姓名的话,就需要覆写它的toString()方法。
看代码:

class Person{
    private int age;
    private String name;

    public Person(int age, String name) {
        this.age = age;
        this.name = name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {

        return age;
    }

    public String getName() {
        return name;
    }

    @Override
    public String toString() {
        return "Person{" +
                "age=" + age +
                ", name='" + name + '\'' +
                '}';
    }
}
public class Test{
    public static void main(String[] args){
        Person person = new Person(18,"张三");
        System.out.println(person);
    }
}

我们现在再来看看输出结果:
在这里插入图片描述

如果我们不想输出地址,而要输出本类信息,就需要在子类中覆写toString()方法。

2.2 对象比较-----equals()
String类对象的比较使用的是equals()方法,实际上,String类的equals()也是覆写了Object类的equals()方法。
例:

class Person{
    private int age;
    private String name;

    public Person(int age, String name) {
        this.age = age;
        this.name = name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {

        return age;
    }

    public String getName() {
        return name;
    }

    @Override
    public String toString() {
        return "Person{" +
                "age=" + age +
                ", name='" + name + '\'' +
                '}';
    }

    @Override
    public boolean equals(Object obj){
        if(obj == null){
            return false;
        }
        if(this == obj){
            return true;
        }
        //如果obj不是Person类对象
        if(!(obj instanceof Person)){
            return false;
        }
        //向下转型,比较属性值
        Person per = (Person) obj;
        return (this.age == per.age) && (this.name.equals(per.name));
    }
}
public class Test{
    public static void main(String[] args){
        Person person1 = new Person(18,"张三");
        Person person2 = new Person(18,"张三");
        System.out.println(person1.equals(person2));
    }
}

在这里插入图片描述
2.3 接收引用数据类型
Object可以接收所有引用类型,包括:类、数组、接口。

public class Test{
    public static void main(String[] args){
        //Object接收数组对象,发生向上转型
        Object obj = new int[]{1, 4, 2, 7};
        //向下转型,需要强转
        int[] data = (int[]) obj;
        for(int i : data){
            System.out.print(i+"、");
        }
    }
}

在这里插入图片描述

3. 包装类

包装类就算将基本类型封装到类中。

自己实现一个包装类:

class IntDemo{
    private int num;
    public IntDemo(int num){
        this.num = num;
    }
    public int intValue(){
        return this.num;
    }
}
public class Test{
    public static void main(String[] args){
        //子类对象向上转型
        Object obj = new IntDemo(78);
        //向下转型
        IntDemo data = (IntDemo) obj;
        //取出里面的基本数据类型操作
        System.out.println(data.intValue());
    }
}

在这里插入图片描述
IntDemo实际上就算int类型的包装类,使用intValue()就可以实现将基本类型变为对象的需求。

3.1 分类
a. 对象型包装类(Object的直接子类):Boolean(boolean)、Character(char)
b. 数值型包装类(Number的直接子类),存在数值转换异常:Byte(byte)、Integer(int)、Short(short)、Long(long)、Double(double)、Float(float)
3.2 装箱与拆箱-----基本数据类型与相应包装类的数据处理

装箱:将基本数据类型变为包装类对象,利用每个包装类提供的构造方法实现包装。

Integer num = new Integer(19);

拆箱:将包装类中包装的基本类型值取出来,利用Number类提供的xxValue()方法实现拆箱处理。

int data = num.intValue();

在JDK1.5之后提供了自动拆装箱处理机制。

//自动装箱
Integer num = 34;
//自动拆箱
System.out.println(--num * 2);

包装类对象之间的值比较依然要使用equals()方法
我们下来看一段代码,就知道为什么要这样了。

public class Test{
    public static void main(String[] args){
        Integer num1 = new Integer(20);
        Integer num2 = new Integer(20);
        System.out.println(num1 == num2);
        System.out.println(num1 == new Integer(20));
        System.out.println(num1.equals(new Integer(20)));
    }
}

在这里插入图片描述
至于原因,在上边String类里已经解释的很清楚了。这里有两个new,没new一次就会在堆空间里开辟一个新空间,所以num1和num2的地址不同。

public class Test{
    public static void main(String[] args){
        Integer num1 = new Integer(20);
        Integer num2 = 20;
        Integer num3 = 200;
        Integer num4 = 200;
        Integer num5 = 56;
        Integer num6 = 56;
        System.out.println(num1 == num2);
        System.out.println(num3 == num4);
        System.out.println(num5 == num6);
    }
}

在这里插入图片描述
为什么会出现上边这种现象呢?
那是因为对于Integer来说,如果它的对象值在-128~127之间的直接赋值,Integer对象在Integer常量池产生,会复用已有对象,这个区间内的Integer值可以直接使用==判断。除此之外,所有的数据都会在堆上产生,并不会复用已有对象。

3.3 字符串与基本类型的转换

  1. 将字符串转为基本类型(静态方法)
    调用各个包装类.parsexx(String str)
    例:
public class Test{
    public static void main(String[] args){
        String str = "123";
        System.out.println(Integer.parseInt(str));
    }
}

在这里插入图片描述
但如果123后边还有字符串类型的字符的话,转换就会出错:
在这里插入图片描述
2. 基本类型变为字符串
a. “”+基本类型,会产生垃圾空间
b. 使用Sting类的valueOf(基本类型),此方法不会产生垃圾空间

public class Test{
    public static void main(String[] args){
        int num = 100;
        String str = String.valueOf(num);
        System.out.println(str.length());
    }
}

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/huaijiu123/article/details/83829512