一起学JAVA API Object String StringBuffer/StringBuilder

1前言

亲爱的小伙伴萌,目前我们看到的是java基础部分的一个新的部分API,这是个啥,又能做啥呢?

其实我们可以概括成一句话:帮助我们站在巨人的肩膀上,实现更加高效的开发,我们来一探究竟吧~

2什么是API

API(Application Programming Interface,应用程序接口)是一些预先定义的函数。目的是提供应用程序与开发人员基于软件可以访问的功能集,有时公司会将API作为其公共开放系统,也就是公司制定自己的系统接口标准,当需要进行系统整合,自定义和程序应用等操作时,公司所有成员都可以通过该接口标准调用源代码。

java.util包是java的核心工具包,包括各种实用工具类/集合类/日期时间工具等各种常用工具包

import java.util.Scanner;

import java.util.Arrays;

java.lang包是Java的核心,包含了java基础类

包括基本Object类/Class类/String类/基本数学类等最基本的类,这个包无需导入,默认会自动导入

import java.lang.Object;

import java.lang.String;

import java.lang.StringBuilder/StringBuffer;

正则表达式

包装类等——

那么我们接下来会学习一些常用的类,帮助大家完成“基建工程”,首先第一位选手就是传说中的Object类

3Object

3.1概念

Object类是所有java类的祖先(基础),也就是我们所说的“顶级父类”

他存在于java.lang.Object,这个包不需要我们手动导包

需要注意的是:每个类都使用Object作为超类,所有对象(包括数组)都实现这个类的方法

在不明确给出超类的情况下,Java会自动把Object类作为要定义类的超类

在这里插入图片描述

3.2常用方法介绍

toString()

本方法用于返回对应对象的字符串表示

hashCode()

本方法用于返回对象的hash码值

小贴士:hash码值的得出是通过一种算法,意在不同的对象具有不同的hash码值,用于区分不同的对象,

但是有时候也存在不同对象hash码值相同的特殊情况,我们称之为“hash碰撞”现象

equals()

本方法用于指示其他某个对象的是否与当前对象“相等”

3.3 练习: Object类练习

创建包: cn.tedu.api
创建类: TestObject.java

 

package cn.tedu.api;

import java.util.Objects;

/*本类用于顶级父类Object的入门案例*/
//1.查API手册
//2.连点两下Shift打开IDEA的搜索,注意勾选"include non-Project items",再搜Object
//3.按住Ctrl点hashCode()
//4.在拓展库External Libraries找到jdk1.8->rt.jar->java.lang.Object
public class TestObject {
    public static void main(String[] args) {
        //4.创建学生类的对象做测试
        Student s = new Student();
        Student s1 = new Student("海绵宝宝",3);
        Student s2 = new Student("海绵宝宝",3);

        //5.测试hashCode()
        /*本方法的作用是返回对应对象的int类型的哈希码值
        * 本方法力求不同的对象返回的哈希码不同
        * 这样我们就可以根据哈希值区分不同的对象*/
        System.out.println(s.hashCode());
        System.out.println(s1.hashCode());
        System.out.println(s2.hashCode());

        //6.测试toString()
        //打印s对象的是println(),这个方法会层层调用,一直到Object中的toString()
        /*Object中toString()的默认实现:对象的名字@十六进制的哈希码值
        * 子类重写了toString()以后:打印是对象的类型+属性+属性值*/
        //return getClass().getName() + "@" + Integer.toHexString(hashCode());
        System.out.println(s);
        System.out.println(s1);

        // 8.测试equals()
        /*Object中equals()的默认实现使用的是==比较
        * ==比较的是左右两边的值,如果是基本类型,比较的就是字面值,比如1和1,3.4和3.4
        * 如果是引用类型,比较的是引用类型变量保存的地址值
        * 子类重写了equals()与hashCode()以后,比较的就是对象的类型+属性+属性值*/
        System.out.println(s1.equals(s2));//false
        System.out.println(s.equals(s1));
    }
}
//1.创建一个学生类
class Student{
    //2.定义属性
    String name;//姓名
    int age;//年龄
    //3.1添加本类的无参构造
    public Student() {
        System.out.println("无参构造");
    }
    //3.2添加本类的全参构造
    public Student(String name, int age) {
        this.name = name;
        this.age = age;
        System.out.println("全参构造");
    }
    //7.在Student类中添加重写的toString()
    //右键->Generate->toString
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    //9.添加重写的equals与hashCode()
    /*equals()与hashCode()逻辑要保持一致,要重写都重写,要不重写,都不重写
    * Object默认实现:hashCode()的哈希码值根据地址值生成
    *               equals()底层使用==比较两个对象的地址值
    * Student类重写后:hashCode()的哈希码值根据重写后传入的对象的属性生成
    *                equals()比较两个对象的类型+所有属性与属性值
    * */
    @Override
    public boolean equals(Object o) {
        //前提:this代表的是调用本方法对象s1 o代表的是传入的对象s2
        //1.比较的是两个对象的地址值,如果==为true,证明直接就是同一个对象
        //后续就不用比较了,直接返回true
        if (this == o) return true;
        //2.1如果传入的对象是null,说明实际上并没有对象,还是引用类型的默认值
        //2.2如果两个对象获取类型不一致,比如一个是Cat类型,一个是Car类型
        //以上两种情况只要满足任意一种,不符合条件,直接返回false
        if (o == null || getClass() != o.getClass()) return false;
        //3.传入对象的类型是Object,父类无法使用子类的特有属性,所以需要强转
        /*多态:向上造型:把子类型看作是父类型,花木兰替父从军 Animal a = new Cat();
        向下造型:之前转成父类型的子类对象,又想使用子类自己的特有功能了,可以向下转型
                 写法:Cat c = (Cat) a; 比如花木兰打仗完了想用自己的特有功能:化妆*/
        //向下造型:把父类型Object转回子类型Student
        Student student = (Student) o;
        //4.比较的是两个对象的属性与属性值
        //如果是基本类型,直接比较值,所以用==比较
        //如果是引用类型,比如String,还需要使用bjects.equals()做比较
        return age == student.age && Objects.equals(name, student.name);
    }
    @Override
    public int hashCode() {
        //重写后根据属性生成
        return Objects.hash(name, age);
    }
}

4 String

4.1特点

String是一个封装char[]数组的对象,字符串不可变

通过下图的底层实现可以看出:被final修饰的,是常量

String str = "abc";等效于:char[] data = {‘a’,'b','c'}; 

在这里插入图片描述

 4.2 创建String对象的方式

方式一:

String(char[] value)分配一个新的String,使其表示字符数组参数中当前包含的字符序列。

方式二:String str = "abc";

在这里插入图片描述

4.3 常见方法 

String SPI总结

int hashCode()返回此字符串的哈希码。

boolean equals(Object anObject)将此字符串与指定的对象比较,比较的是重写后的串的具体内容

String toString()返回此对象本身(他已经是一个字符串!)。

int length() 返回此对象的长度。

String toUpperCase()所有字符都转为大写。

String toLowerCase()所有字符串都转换为小写。

boolean startsWith(String prefix) 测试此字符串是否以指定元素开头。

boolean endsWith(Sting suffix)测试此字符串是否以指定的字符串结束。

char charAt(int index) 返回指定索引/下标处的char值字符

int indexOf(String str)返回指定字符串在此字符串中最后一次出现出的索引。

String concat(String str)将指定字符串连接/拼接到此字符串的末尾,注意:不会改变原串

String[] split(String regex) 根据给定元素来分割此字符串。

String trim()返回取出首尾空格的字符串

byte[] getBytes()把字符串存储到一个新的byte数组中

String substring(int beginlndex)返回一个新子串,从指定下标处开始,包含指定下标

String substring(int beginlndex,int endindex)返回一个新子串,从指定下标开始到指定下标结束,但不包含结束下标

static String valueOf(int i)把int转换成String

4.4练习:String常用方法练习

创建包: cn.tedu.api
创建类: TestString.java

​
package cn.tedu.api;
/*本类用于练习String类的使用*/
public class TestString {
    public static void main(String[] args) {
        //1.创建String的方式一
        /*1.字符串类型底层维护的是char[],存在堆中*/
        char[] value = {'a','b','c'};
        String s1 = new String(value);//触发String(char[])的含参构造来创建对象
        String s11 = new String(value);//触发String(char[])的含参构造来创建对象
        //2.创建String的方式二
        String s2 = "abc";
        String s22 = "abc";
        String s3 = "ccc";
        //3.测试
        System.out.println(s1 == s2);//false,一个在堆里,一个在堆中常量池
        System.out.println(s1 == s11);//false,两个不同的对象,地址值不同
        System.out.println(s2 == s22);//true,都在堆中常量池,并且指向同一个,所以地址值相同
        System.out.println(s2 == s3);//false,都在堆中常量池,但是数据不同,指向两个地址

        /*Object类中equals()的默认实现是通过==来比较的。
        但是String类已经重写过了继承自Object中的equals()
        重写后,不再按照==比较,而是比较两个字符串的具体内容
        也就是说,不论创建方式,只要是串的内容一致,equals()就返回true
        * */
        System.out.println(s1.equals(s2));//true
        System.out.println(s1.equals(s11));//true
        System.out.println(s2.equals(s3));//false

    }
}

​

创建包: cn.tedu.api
创建类: TestString2.java

package cn.tedu.api;

import java.util.Arrays;

/*本类用来测试String类的常用方法*/
public class TestString2 {
    public static void main(String[] args) {
        //1.创建字符串
        String s1 = "abc";

        char[] values = {'a','b','c'};
        String s2 = new String(values);

        //2.测试常用方法
        /*String重写了hashCode(),是根据字符串的内容生成哈希码值,而不是根据地址值生成
        * 所以虽然s1与s2一个在堆的常量池中,一个在堆中,它两的哈希码值一样*/
        System.out.println(s1.hashCode());//96354
        System.out.println(s2.hashCode());//96354

        System.out.println(s1.equals(s2));//true,重写了,比较的是具体内容

        System.out.println(s1.toString());//不需要写,底层会自动调用s1对象的toString()
        System.out.println(s1);//abc,String重写了toString(),直接打印的是串的具体内容

        System.out.println(s1.length());//3,查看当前字符串的长度
        System.out.println(s1.toUpperCase());//ABC,将本字符串转为全大写
        System.out.println(s1.toLowerCase());//abc,将本字符串转为全小写
        System.out.println(s1.startsWith("a"));//true,判断本字符串是否以指定元素a开头
        System.out.println(s2.endsWith("a"));//false,判断本字符串是否以指定元素a结尾

        System.out.println(s1.charAt(0));//a,根据下标获取本字符串中对应的元素

        String s3 = "abcbdbba";
        System.out.println(s3.indexOf("b"));//1,返回本字符串中指定元素第一次出现的下标
        System.out.println(s3.lastIndexOf("b"));//6,返回本字符串中指定元素最后一次出现的下标

        System.out.println(s2.concat("cxy"));//abccxy,将指定字符串拼接到本字符串的结尾
        System.out.println(s2);//abc,说明上面的拼接是临时的,不会改变原串的内容

        String s4 = s2.concat("aaa");//如果想要多次使用拼接后的结果,需要定义一个字符串来保存结果
        System.out.println(s4);//abcaaa

        String s5 = "afbfcfdfe";
        //返回值类型是String[],所以需要使用Arrays.toString()打印
        //以指定字符作为分割符,分割当前的字符串
        //我们只是直接打印了split()的结果,没有使用变量保存
        System.out.println(Arrays.toString(s5.split("f")));//[a, b, c, d, e]

        //由于split()的返回值类型是String[],所以我们执行这个方法,可以拿到这个方法的返回值
        //所以a数组就是这个方法执行以后得到的结果,只不过我们保存下来了
        String[] a = s5.split("f");
        for (int i = 0; i < a.length; i++) {
            System.out.println(a[i]);
        }

        String s6 = "       hh hhh      ";//去除本字符串首尾两端的空格
        System.out.println(s6.trim());//hh hhh

        String s7 = "abcdefgh";
        System.out.println(s7.substring(3));//defgh,从指定下标处截取子字符串[3,结束]
        System.out.println(s7.substring(3,6));//def,从指定下标处截取子字符串[3,6)含头不含尾

        System.out.println(String.valueOf(10));//10,将int类型的参数10转为String类型
        System.out.println("20"+10);//2010,String与int拼接
        System.out.println(20+10);//30,int与int相加
        System.out.println(String.valueOf(80)+10);//8010,将int类型的参数80转为String类型,所以拼接

        byte[] bs = s7.getBytes();//将指定字符串转为byte[]
    }
}

5StringBuider/StringBuffer

5.1特点

1.封装了char[]数组

2.是可变的字符序列

3.提供了一组可以对字符内容修改的方法

4.常用append()来代替字符串做字符串拼接“+”

5.内部字符数组默认初始容量:super(str.length()+16);

6.如果大于16会尝试将扩容,新数组大小原来的变成两倍+2,容量如果还不够,直接扩容到需要的容量的大小。int newCapacity=value.length*2+2;

7.StringBuffer 1.0出道线程安全,StringBuiler1.5出道线程不安全

5.2常见方法

append()

5.3练习3.测试字符串连接

创建包:cn.tedu.api

创建类:TestString3.java

package cn.tedu.api;
/*本类用于测试字符串的拼接*/
public class TestString3 {
    public static void main(String[] args) {
        //需求:将26个字母拼接10000次
        String s = "abcdefghijklmnopqrstuvwxyz";
        //method1(s);//使用方式一拼接字符串
        method2(s);//使用方式二拼接字符串
    }
    //使用方式二拼接字符串
    private static void method2(String s) {
        //1.创建工具类对象
        StringBuffer sb = new StringBuffer();
        StringBuilder sb2 = new StringBuilder();
        //5.添加一个计时的功能
        //5.1拼接之前获取系统当前时间作为开始时间
        long t1 = System.currentTimeMillis();
        //2.拼接10000次
        for (int i = 0; i < 10000; i++) {
            //3.使用工具类对象的append()进行拼接
            //sb.append(s);
            sb2.append(s);
        }
        //5.2拼接之后获取系统当前时间作为结束时间
        long t2 = System.currentTimeMillis();
        //4.打印拼接的效果
        //System.out.println(sb);
        System.out.println(sb2);
        //5.3打印拼接总共消耗的时间
        System.out.println(t2-t1);
    }

    //使用方式一完成字符串的拼接
    private static void method1(String s) {
        //1.创建一个变量用来保存拼接后的效果
        String result = "";
        //5.给程序添加一个计时的功能
        //5.1获取循环开始的系统当前时间
        long t1 = System.currentTimeMillis();
        //2.创建循环执行10000次
        for (int i = 0; i < 10000; i++) {
            //3.进行字符串的拼接
            result = result + s;
        }
        //5.2获取循环拼接之后的系统当前时间
        long t2 = System.currentTimeMillis();
        //4.打印拼接后的效果
        System.out.println(result);
        //5.打印花费的时间
        System.out.println(t2-t1);
        System.out.println(t2);
    }

}

6 拓展


6.1 ==和equals的区别


1.当使用= =比较时,如果相比较的两个变量是引用类型,那么比较的是两者的物理地值(内存地址),如果相比较的两个变量都是数值类型,那么比较的是具体数值是否相等。
2.当使用equals()方法进行比较时,比较的结果实际上取决于equals()方法的具体实现
众所周知,任何类都继承自Object类,因此所有的类均具有Object类的特性,比如String、integer等,他们在自己的类中重写了equals()方法,此时他们进行的是数值的比较,而在Object类的默认实现中,equals()方法的底层是通过==来实现的。

6.2 练习: ==与equals测试


创建包: cn.tedu.api
创建类: Test.java

package cn.tedu.api;
/**本类用于测试==与equlas的区别*/
public class Test{
	public static void main(String[] args) {
		Person p1 = new Person("凹凸曼",16);
		Person p2 = new Person("凹凸曼",16);
		
		System.out.println(p1 == p2);//false,new了两个对象,p1和p2保存的地址值不同
		System.out.println(p1.name == p2.name);//true,name是String类型,保存在常量池中,值是同一个
		System.out.println(p1.age == p2.age);//true,age是int基本类型,保存的值都是18
		
		//第一次测试:结果false,使用的是Object默认的逻辑,也是用==来比较的
		//第二次测试:结果true,重写equals()后,就会使用子类重写后的功能,也就是说此时比较的不再是地址,而是类型&属性值
		System.out.println(p1.equals(p2));
	}
}

//1.创建Person类
class Person {
	String name;
	int age;
	
	public Person() {
		System.out.println("我是手动添加的无参构造");
	}
	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	//需求:比较两个对象的属性值,如果属性值都一样,就是"同一个对象",要求equals返回true
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Person other = (Person) obj;
		if (age != other.age)
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
	}
	
}

6.3 StringBuilder和StringBuffer的区别


1.在线程安全上 :
–StringBuffer是旧版本就提供的,线程安全的。@since JDK1.0
–StringBuilder是jdk1.5后产生,线程不安全的。@since 1.5
2. 在执行效率上,StringBuilder > StringBuffer > String
3.源码体现:本质上都是在调用父类抽象类AbstractStringBuilder来干活,只不过Buffer把代码加了同步关键字,使得程序可以保证线程安全问题。

在这里插入图片描述

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值