(十)Java常用类

本文深入解析Java中的Object类和String类API,详细介绍了Object类的构造方法、成员方法及其功能,如getClass、toString、equals、hashCode、clone和finalize。同时,全面阐述了String类的构造方法、特性及常用API,包括字符串的创建、判断、获取、转换、替换、去除空字符串和比较等功能。
摘要由CSDN通过智能技术生成

API(Application Programming Interface,应用程序接口)是一些预先定义的函数,或指软件系统不同组成部分衔接的约定。用来提供应用程序与开发人员基于某软件或硬件得以访问的一组例程,而又无需访问原码,或理解内部工作机制的细节。

一、Object api
Object类是类层次结构的根类,所有类都直接或者间接的继承自该类。

Object类中,没有定义成员变量,但有构造方法public Object();

为什么所有类都会有一个默认的无参构造方法?
这与子类对象默认初始化有关 。
无参默认构造方法:

  • 当一个类没有定义构造方法的时候,就会自动添加默认构造方法;
  • 一旦有默认构造方法,在创建子类对象的时候,就会执行子类对象的隐式初始化;
  • 隐式初始化,默认调用父类的无参构造;
  • 所以最终,一定能保证,调用到Object类的无参构造方法,先初始化Object父类;

Object的成员方法

  • public final Class getClass()
  • public String toString()
  • public boolean equals(Object obj)
  • public int hashCode()
  • protected Object clone()
  • protected void finalize()(了解)

1.public final Class getClass()
返回一个Class对象,表示该对象所属的类。

Class obj = 对象.getClass()

一个Class对象,代表一个类,用来描述一个类的类型信息。
所有的类有共性,Class作为类描述了所有类的共性:构造方法、成员变量和成员方法。
jvm的每一个类,在类加载完成后,都会自动生成一个和该类对应的Class对象。一个类对应一个Class对象。
一个类在jvm中都有唯一一个Class对象。一个Class对象中封装了一个类的定义。

2.public String toString()
对象.toString()
返回该对象的字符串表示。通常,toString 方法会返回一个“以文本方式表示”此对象的字符串。结果应是一个简明但易于读懂的信息表达式。建议所有子类都重写此方法。

Object 类的 toString 方法返回一个字符串,该字符串由类名(对象是该类的一个实例)、at 标记符“@”和此对象哈希码的无符号十六进制表示组成。换句话说,该方法返回一个字符串,它的值等于:

getClass().getName() + '@' + Integer.toHexString(hashCode())

toString方法返回的字符串: 必须要能代表一个对象。

什么能表示一个对象的特征? 对象的成员变量就能够表示一个对象的特征。
从对象的差异性角度来理解对象的特征,同种类型对象虽然具有相同的属性,但是各个不同的对象,属性的取值可以不同,因此产生了差异。
所以,描述对象特征的字符串:是包含一个对象所有成员变量值的一个字符串。

3.public boolean equals(Object obj)
对象.equals(obj)
指示其他某个对象是否与此对象“相等”。

对象的相等?
从对象差异性的角度理解
a. 同种类型的的对象,差异性,差异在对象属性取值的不同。
b. 如果同种类型的两个对象,属性值对应相等了,就认为这两个对象相等。

所以,比较对象是否相等:
a. 是同种类型的对象
b. 对象的属性值相等

equals 方法在非空对象引用上实现相等关系:

  • 自反性:对于任何非空引用值 x,x.equals(x) 都应返回 true。 自己和自己相等
  • 对称性:对于任何非空引用值 x 和 y,当且仅当 y.equals(x) 返回 true 时,x.equals(y) 才应返回 true。 y 等于 x,且 x等于y
  • 传递性:对于任何非空引用值 x、y 和 z,如果 x.equals(y) 返回 true,并且 y.equals(z) 返回 true,那么 x.equals(z) 应返回 true。 如果x等于y,且y和z相等,x等于z
  • 一致性:对于任何非空引用值 x 和 y,多次调用 x.equals(y) 始终返回 true 或始终返回 false,前提是对象上 equals 比较中所用的信息没有被修改。
  • 对于任何非空引用值 x,x.equals(null) 都应返回 false。任何对象和null比较,结果确定false。

Object 类的 equals 方法实现对象上差别可能性最大的相等关系,即对于任何非空引用值 x 和 y,当且仅当 x 和 y 引用同一个对象时,此方法才返回 true(x == y 具有值 true)。比较的是对象的地址,等价于 ==。

4.public int hashCode()
一种典型的hash方法,返回该对象的哈希码值(int整数)。
对象 -> 整数

hash函数定义:
A hash function is any function that can be used to map data of arbitrary size onto data of fixed size.
The values returned by a hash function are called hash values, hash codes or simply hashes.

hashCode 的常规协定是:

  • 在 Java 应用程序执行期间,在对同一对象多次调用 hashCode 方法时,必须一致地返回相同的整数,前提是将对象进行 equals 比较时所用的信息没有被修改。(一个对象的hashcode值,根据对象成员变量的值算出来的)。
    从某一应用程序的一次执行到同一应用程序的另一次执行,该整数无需保持一致。

  • 如果根据 equals(Object) 方法,两个对象是相等的,那么对这两个对象中的每个对象调用 hashCode 方法都必须生成相同的整数结果。

  • 如果根据 equals(java.lang.Object) 方法,两个对象不相等,那么对这两个对象中的任一对象上调用 hashCode方法不要求一定生成不同的整数结果(数据冲突)。但是,程序员应该意识到,为不相等的对象生成不同整数结果可以提高哈希表的性能。

实际上,由 Object 类定义的 hashCode 方法确实会针对不同的对象返回不同的整数。
(这一般是通过将该对象的内部地址转换成一个整数来实现的,但是 JavaTM 编程语言不需要这种实现技巧)。

5.protected Object clone()
创建并返回此对象的一个副本。
对象.clone()

创建并返回此对象的一个副本。这样做的目的是,对于任何对象 x,表达式:

  • x.clone() != x 为 true, 被复制对象和原对象是不同的对象
  • x.clone().getClass() == x.getClass()也为 true,被复制的对象和原对象是同一个类型的对象
  • x.clone().equals(x) ,原对象和复制对象,内容相等

注意事项:CloneNotSupportedException
Object 类的 clone 方法执行特定的复制操作。首先,如果此对象的类不能实现接口 Cloneable,则会抛出 CloneNotSupportedException。

两个小问题:
a. clone方法权限的问题
b.Clonable是一个空接口(标记接口),是一种特殊的标记。
空接口的作用:做标记。一个类实现了空接口,那么它的数据类型就发生了变化,这个类既可以是子类即本身类型又可以是父类类型。
一个类实现了一个空接口,该类就被打上了一个标记,一旦一个类被打上了空接口的标记,我们就可以针对有这种标记类的对象,做特殊处理。

Object类的Clone方法是对原对象的不完全复制,即浅拷贝。
a.首先在堆上开辟复制对象的内存
b.将原对象成员变量的值依次复制到复制对象中(对于引用类型的成员变量,仅仅只是复制引用变量的值)。

和浅拷贝相对,还有深拷贝:
所谓深拷贝,就是指对原对象的完全复制,即复制对象和原对象是完全独立的。

深拷贝和浅拷贝的唯一区别,仅在于对原对象引用类型成员变量的复制:
a.浅拷贝只复制引用变量的值
b.深拷贝还会复制原对象引用变量所指向的对象。

6.protected void finalize()(了解)
实际开发中,一般不会使用这个方法。
对象.finalize()
a.当垃圾回收器确定不存在对该对象的更多引用时(当没有引用指向该对象的时候,此时对象其实已经变成了垃圾)
b.由对象的垃圾回收器调用此方法(这个方法的调用者是垃圾回收器)

需要了解该方法的执行时机:a 和 b的含义

比如:当我们要执行一些I/O或者是网络通信的功能的时候,其实jvm是借助操作系统内核完成的,所以当我们执行这些功能的时候,java程序需要占用一定的操作系统资源,我们希望当程序使用完毕操作系统资源的时候,能及时地释放资源。什么时候能安全的释放系统资源呢? 当使用资源的对象变成垃圾。

由于垃圾回收器执行时机不确定,所以导致了垃圾的对象的finalize执行时机也不确定。
finalize方法刚刚好,就是在对象变成垃圾并且被垃圾回收期回收的时候,会调用这个方法,但是,垃圾回收期回收垃圾对象的回收时机是不确定。

二、String api

String类:一个字符串就是一个String类对象。
字符串是由多个字符组成的一串数据(字符序列)。

字符串是常量,它的值在创建之后不能更改。因为每次对字符串的计算,jvm会自动创建新的String,把计算结果赋值给新的String对象。

1.String构造方法
public String()
public String(byte[] bytes)
public String(byte[] bytes,int offset,int length)
public String(char[] value)
public String(char[] value,int offset,int count)
public String(String original)

  • public String() 代表空字符串 “”
    不要把空字符串和空常量null混淆。

  • public String(byte[] bytes)
    利用字节数组创建字符数组所表示的字符串。
    字符 -> 数值形式 ‘a’ -> 97(在一个byte整数的表示范围之内)
    所以可以用多个字节值,表示多个字符——>即字符序列

  • public String(byte[] bytes,int offset,int length)
    利用字节数组的一部分创建字符序列, 从byte数组的offset开始的length个字节值。

  • public String(char[] value)
    利用一个字符数组创建字符数组代表的字符序列。

  • public String(char[] value,int offset,int count)
    创建value字符数组中,从第offset位置开始的count个字符,所代表的字符串对象。

  • public String(String original)
    根据已有的字符串去创建另一个字符串(String对象)。

2.特征
字符串是"常量",它的值在创建之后不能更改。
这里所谓的不可变,是指一个字符串对象一旦被创建,如果要修改字符串,总是创建新的字符串对象,在新的字符串对象中,修改字符序列。

常量池:存储字面值常量(java语言层面)
字符串常量池:存储字符串字面值常量

3.常用api

String类的的判断功能:
boolean equals(Object obj)
boolean equalsIgnoreCase(String str)
boolean contains(String str)
boolean startsWith(String str)
boolean endsWith(String str)
boolean isEmpty()

  • boolean equals(Object obj)
    用来比较字符串的内容是否相同,String对象.equals(obj)
  • boolean equalsIgnoreCase(String str)
    忽略字符串大小写比较字符串内容是否相等
  • boolean contains(String str)
    判断当前字符串对象是否包含目标字符串的字符序列
  • boolean startsWith(String str)
    判断当前字符串对象,是否以目标字符串的字符序列开头
  • boolean endsWith(String str)
    判断当前字符串,是否以目标字符串对象的字符序列结尾
  • boolean isEmpty()
    判断一个字符串,是不是空字符串

String类的的获取功能:
int length()
char charAt(int index)
int indexOf(int ch)
int indexOf(String str)
int indexOf(int ch,int fromIndex)
int indexOf(String str,int fromIndex)
String substring(int start)
String substring(int start,int end)

  • int length()
    获取当前字符串对象中,包含的字符个数
  • char charAt(int index)
    获取字符串对象代表字符序列中指定位置的字符。字符串中的字符,从左到右,给字符串中每一个字符,从0开始标号。
  • int indexOf(int ch)
    在当前字符串对象中,查找指定的字符在当前字符串中(首次)出现的位置,如果找到就返回字符首次出现的位置,如果没找到返回-1
  • int indexOf(String str)
    查找当前字符串中,目标字符串首次出现的位置,这里的位置是指目标字符串的第一个字符在当前字符串对象中的位置,如果找不到,返回-1。
  • int indexOf(int ch,int fromIndex)
    从当前字符串对象的指定位置开始,查找首次出现的指定字符的位置,如果没找到返回-1。
  • int indexOf(String str,int fromIndex)
    从当前字符串对象的指定位置开始,查找首次出现的指定字符串的位置,如果没找到返回-1。
  • String substring(int start)
    返回字符串,该字符串只包含当前字符串中从指定位置开始(包含指定位置字符)的之后那部分字符串。
    “zhangsan”.subString(5) -> “san”
  • String substring(int start,int end)
    返回字符串,只包含当前字符串中,从start位置开始(包含),到end(不包含)指定的位置,这部分字符串 [start, end)。

String类的的转换功能:
byte[] getBytes()
char[] toCharArray()
static String valueOf(char[] chs)
static String valueOf(int i)
String toLowerCase()
String toUpperCase()
String concat(String str)

  • 字符串 ——>其他类型数据
    byte[] getBytes() 获取一个用来表示字符串对象字符序列的字节数组
    char[] toCharArray() 获取的是用来表示字符串对象字符序列的,字符数组
  • 其他类型数据 -> 字符串
    static String valueOf(char[] chs) 把一个字符数组转换成对应的字符串
    static String valueOf(int i) 把一个字符转换成对应的字符
  • 字符串大小写的转化
    String toLowerCase() 把字符串全部转化为小写
    String toUpperCase() 把字符串全部转化为大写
  • String concat(String str)
    字符串拼接 作用等价于+ ,实现的字符串拼接

String类的替换功能

  • String replace(char old,char new)
    用新的字符替换原字符串中的指定的旧字符
  • String replace(String old,String new)
    用新的字符串替换原字符串中的指定的旧字符串

String类去除空字符串

  • String trim()
    去掉字符串中的空格字符(开头和结尾)

String类的比较功能

  • int compareTo(String str)
    比较两个字符串大小
  • int compareToIgnoreCase(String str)
    忽略大小写比较两个字符串大小

(1)字符串的比较,如何比较?
按照字典序比较字符串的大小。字典序原本的含义是指,英文单词在字典中出现的先后顺序,在字典中,先出现的字符小,后出现的字符大。

字符串的比较具体到编程语言,是根据两个字符串字符串从左往右数,第一个对应位置的不同字符,来决定两字符串的大小。

(2)比较的结果如何表示?
String类实现了Comparable接口,这个接口表示了一种抽象的比较大小的规则(协议)。
int compareTo(String o) 规定了一种比较的规则。
a.比较结果大于关系: 返回值 > 0 ,当前对象 > 带比较对象
b.比较结果的小于关系: 返回值 < 0 , 当前对象 < 待比较对象
c.比较结果的等于关系: 返回值 等于 0 ,当前对象和带比较对象相等

//compareTo()方法的源码
public int compareTo(String anotherString) {
        //获取当前字符串所代表的字符序列中包含的字符个数
        int len1 = value.length;
        //获取待比较字符串所代表的字符序列中包含的字符个数
        int len2 = anotherString.value.length;
        int lim = Math.min(len1, len2);//取两个字符串长度小者
        char v1[] = value;
        char v2[] = anotherString.value;

        int k = 0;//k指代下一个待比较的位置
        while (k < lim) {
            char c1 = v1[k];
            char c2 = v2[k];
            if (c1 != c2) {
                return c1 - c2;//c1 < c2 ,c1 - c2 < 0 ,小于关系
                               //c1 > c2 ,c1 - c2 > 0 ,大于关系
            }
            k++;
        }
        return len1 - len2;//如果两个字符串对应位置的字符都相同
    }

类似于“hello”,有双引号括起来的字符串是一个字符串字面值常量,所代表的也是一个String对象,存储在字符串常量池中,而一般的String对象是存储在堆上的。
常量池在java语言层面是用来存储字面值常量的,在方法区中。

字符串拼接何时会在堆上,创建新的字符串对象,何时不会呢?
a.当参与字符串拼接的两个字符串中,至少有一个是字符串的引用变量,此时拼接运算,必然会在堆上创建新的字符串对象。
s1 + s2 和s1 + “hello” 都会在堆上创建新的对象。
b.只有参与字符串拼接运算两个字符串,都是字符串常量的时候,此时不会在堆上创建新的字符串对象,而是直接拼接。

#个人学习记录,如发现有错误之处,欢迎与我交流

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值