常用类:Object
一、API概述(Application Programming Interface)
应用程序编程接口
编写一个机器人程序去控制机器人踢足球,程序就需要向机器人发出向前跑、向后跑、射门、
抢球等各种命令,没有编过程序的人很难想象这样的程序如何编写。但是对于有经验的开发人员来说,
知道机器人厂商一定会提供一些用于控制机器人的Java类,这些类中定义好了操作机器人各种
动作的方法。其实,这些Java类就是机器人厂商提供给应用程序编程的接口,
大家把这些类称为Xxx Robot API。
本章涉及的Java API指的就是JDK中提供的各种功能的Java类。
二、常用类
Object类/Scanner类
String类/StringBuffer类/StringBuilder类
数组高级和Arrays类
基本类型包装类(Integer,Character)
正则表达式(Pattern,Matcher)
Math类/Random类/System类
BigInteger类/BigDecimal类
Date类/DateFormat类/Calendar类
三、Object类概述及其类中的方法
1、Object类概述
Class Object是类Object结构的根;
每个班都有Object作为超类;
所有对象(包括数组)都实现了这个类的方法;
每个类都直接或者间接的继承Object类
例:随便写个类,都默认继承Object类
public class Student extends Object{
}
2、学习Object中的一个方法:哈希算法
public int hashCode()返回对象的哈希码值
注意:这里的哈希码值是根据哈希算法计算出来的一个值,这个值和地址有关系,
但是并不是实际的地址值。简单理解为地址值的另一种表现形式
案例:
//创建一个class文件,定义一个类
public class Student extends Object{
}
//同一个包下再创建一个class文件,定义一个类
public class StudentTest {
public static void main(String[] args) {
//因为在一个包内,所以能创建Student对象
Student s = new Student();
//调用Object中的hashCode方法
System.out.println(s.hashCode());
//再创建一个Student对象
Student s1 = new Student();
System.out.println(s1.hashCode());
}
}
执行结果如下:
356573597
1735600054
Process finished with exit code 0
//结论:调用hashCode方法时,输出的哈希码值不一定相同
3、学习Object中的一个方法:getClass
public final 类 getClass()
返回此Object的运行时类
返回的类对象是被表示类的static synchronized方法锁定的对象
案例:
public class StudentTest {
public static void main(String[] args) {
//创建一个Student对象
Student s = new Student();
System.out.println(s.getClass());
}
}
执行结果如下:
class myself.day18.Student
Process finished with exit code 0
//输出的是当前项目下一个相对路径的class类型
4、学习Object类中的一个方法:toSring
//创建一个Student2的类
public class Student2 {
//定义成员变量
private String name;
private int age;
//无参构造方法
Student2(){
}
//带参构造方法
Student2(String name,int age){
this.name = name;
this.age = age;
}
//定义公共的setXxx()和getXxx()方法
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setAge(int age) {
this.age = age;
}
public int getAge() {
return age;
}
}
public class StudentTest2 {
public static void main(String[] args) {
//创建Student2对象
Student2 s2 = new Student2();
System.out.println(s2.toString());//myself.day18.Student2@1540e19d
//System.out.println(s2.getClass().getName());//myself.day18.Student2
}
}
执行结果如下:
myself.day18.Student2@1540e19d
Process finished with exit code 0
/*
s2.toString()在s2.getClass().getName()基础上多了@1540e19d
根据toString方法说明:
getClass().getName() + '@' + Integer.toHexString(hashCode())
可知:
Integer类中有一个toHexString方法将哈希值转换成地址值
*/
查找Integer类中的toHexString方法
Integer类中有一个toHexString方法将哈希值转换成地址值
public static String toHexString(int i)
返回整数参数的字符串表示形式,作为16位中的无符号整数
因此可知:
System.out.println(s.toString());
等价于
System.out.println(s.getClass().getName()+"@"+Integer.toHexString(s.hashCode()));
我们虽然掌握了toString()的方法使用,但是呢打印的结果是一个地址值,拿到地址值是没有意义的
我们正常打印一个对象,其实是想看该对象中的成员变量的值。
又因为toString()方法的返回值是String类型,并且属于Object类中的
而Object类是所有类的父类,那么我们自己定义类的时候,就可以重写该方法,重写里面的实现。
将来调用toString()方法的时候,严格遵循编译看左,运行看右,所以调用的是重写后的方法。
在Student2中重写toString方法
.......(方便观看,上方省略)
public int getAge() {
return age;
}
//重写toString方法
@Override
public String toString() {
// return super.toString();
return "姓名:" + name + "年龄:" + age;
}
}
重写以后再返回StudentTest2类中,再次运行一下
public class StudentTest2 {
public static void main(String[] args) {
//创建Student2对象
Student2 s2 = new Student2();
System.out.println(s2.toString());
}
}
执行结果为:
姓名:null年龄:0
Process finished with exit code 0
赋值一下
public class StudentTest2 {
public static void main(String[] args) {
//创建Student2对象
Student2 s2 = new Student2();
System.out.println(s2.toString());
//赋值
s2.setName("伟爷");
s2.setAge(18);
System.out.println(s2.toString());
}
}
执行结果为:
姓名:null年龄:0
姓名:伟爷年龄:18
Process finished with exit code 0
5、类最终写法的诞生
通过上述案例,诞生了类的最终写法
类最终写法:4.0版本:
成员变量:private
构造方法:无参,有参
成员方法:getXxx()和setXxx(),有特有方法就加上特有方法
toString():自动生成即可 快捷键 Alt+Insert回车
最终版本案例:
class Student2 {
//定义成员变量
private String name;
private int age;
//无参构造方法
Student2(){
}
//带参构造方法
Student2(String name,int age){
this.name = name;
this.age = age;
}
//定义公共的setXxx()和getXxx()方法
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setAge(int age) {
this.age = age;
}
public int getAge() {
return age;
}
//重写方法
//Alt+Insert回车,选择toString()方法,回车再回车
@Override
public String toString() {
return "Student2{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class StudentTest2 {
public static void main(String[] args) {
//创建Student2对象
Student2 s2 = new Student2();
//赋值
s2.setName("伟爷");
s2.setAge(18);
System.out.println(s2.toString());
}
}
执行结果为:
Student2{name='伟爷', age=18}
Process finished with exit code 0
toString方法总结
如果子类中(学生类)不重写toString,在测试类中,通过对象调用该方法,打印出的是地址值;
重写之后再调用toString,打印出的就是规范的成员变量值
6、学习Object类中的一个方法:equals
public boolean equals(Object obj)指示一些其他对象是否等于此
==:
比较基本类型:比较的是值是否相同
比较引用类型:比较的地址值是否相同
equals:
比较的是引用数据类型
案例:
public class Student3 {
//定义成员变量
private String name;
private int age;
//无参构造方法
Student3(){
}
//带参构造方法
Student3(String name,int age){
this.name = name;
this.age = age;
}
//定义公共的setXxx()和getXxx()方法
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setAge(int age) {
this.age = age;
}
public int getAge() {
return age;
}
//重写toString()
@Override
public String toString() {
return "Student3{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class StudentTest3{
public static void main(String[] args) {
Student3 s3 = new Student3("伟爷",18);
Student3 s4 = new Student3("伟爷",18);
System.out.println(s3==s4);//比较的是地址值是否相同:false
Student3 s5 =s3;//将对象s3赋值给s5对象
System.out.println(s5==s3);//true
//用epuals比较引用数据类型
System.out.println(s3.equals(s4));//比较的是地址值是否相同:false
System.out.println(s3.equals(s5));//比较的是地址值是否相同:true
System.out.println(s3.equals(s3));//比较的是地址值是否相同:true
}
}
我们只知道equals是用来比较引用数据类型的,但是我们却不知道是内部是如何实现的;
如果想要弄明白一个类中的方法是如何实现的时候,API也没告诉我们怎么办呢?
看源码。将鼠标光标放在方法名上 ctrl+鼠标左键
以 System.out.println(s3.equals(s4));为例
ctrl+鼠标左键
会出现下面代码:
public boolean equals(Object obj) {
return (this == obj);
}
分析可知:this指的s3,obj指的是s4
通过观察源码发现:Object类中的equals方法,底层的实现依旧是 ==
而 == 比较引用数据类型比较的是地址值,当地址值不一样的时候返回的是false
由上可知,比较的都是地址值
如果我们想要比较两个对象的成员变量值,该怎么做呢?
由public boolean equals(Object obj)可知,equals是被public修饰的
想要在测试类中比较对象的成员变量值,在学生类中需要重写equals方法
(不需要我们自己重写,快捷键 Alt+Insert回车 自动生成即可)
重写equals方法后,再回到测试类。再次运行,调用equals比较的就是成员变量值了
public class StudentTest3{
public static void main(String[] args) {
Student3 s3 = new Student3("伟爷",18);
Student3 s4 = new Student3("伟爷",18);
System.out.println(s3==s4);//比较的是地址值是否相同:false
Student3 s5 =s3;//将对象s3赋值给s5对象
System.out.println(s5==s3);//true
//用epuals比较引用数据类型
System.out.println(s3.equals(s4));//比较的是地址值是否相同:true
System.out.println(s3.equals(s5));//比较的是地址值是否相同:true
System.out.println(s3.equals(s3));//比较的是地址值是否相同:true
}
}
equals方法总结:
如果子类中(学生类)不重写equals方法,默认调用的是Object类中的equals方法,默认比较的是地址值;
重写equals方法之后,比较的是对象成员变量值
7、学习Object类中的一个方法:clone
protected Object clone()
创建并返回此对象的副本
未重写clone方法之前,调用该方法的时候会直接报错,所以要先在子类(学生类)中重写克隆方法
重写该方法与重写其他方法有点区别,该方法需要通过子类super去调用,不能使用Alt+Inset快捷键
//重写clone方法。否则无法调用
//通过子类super去调用(重写该方法不能使用Alt+Inset快捷键)
//输入c,然后根据提示选择protected Object clone() {...}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
重写clone方法后,再次回到测试类来调用该方法
由上可知,重写clone方法后,在测试类调用该方法后,打印输出的时候,还是会报错;
这说明并不是什么样的类都可以被克隆,类需要满足一个标记才能被克隆
类该怎么去标记?
在工具说明书中:
clone的方法Object执行特定的克隆操作。
首先,如果此对象的类不实现接口Cloneable ,则抛出CloneNotSupportedException
将想要调用克隆方法的类实现Cloneable接口
通过观察API发现,Cloneable接口中没有成员变量也没有成员方法
今后看到类似于Cloneable接口里面什么都没有的接口,我们称之为标记接口
标记接口,只需在类名后面加implements Cloneable即可,表示实现接口
Public class Student4 implements Cloneable{
//定义成员变量
private String name;
private int age;
//无参构造方法
Student4(){
}
//带参构造方法
Student4(String name,int age){
this.name = name;
this.age = age;
}
//定义公共的setXxx()和getXxx()方法
...(为了方便观看,暂且省略)
添加指针后,回到测试类再次运行
由上可知,通过调用克隆方法,输出的结果会打印出一模一样的。
我们可以发现,通过再次创建对象,再次赋值,也可以打印出一模一样的结果,那么克隆的意义在哪?
答:当二次赋值的时候,再输出,结果与第一次是不一样的;
但是用克隆输出的时候,无论前面再怎么赋值,打印出的结果都是和第一次一样的
拷贝在IT行业中常见两种:
浅拷贝
拷贝的时候,重新创建一个对象,成员变量值和被拷贝的一样,但是后续修改与原先的没有关系
深拷贝
拷贝的时候,没有创建新的对象,只是改个名字,地址值都一样,修改拷贝后的连带影响到原先的
8、学习Object类中的一个方法:finalize
protected void finalize()
throws Throwable当垃圾收集确定不再有对该对象的引用时,
垃圾收集器在对象上调用该对象。
一个子类覆盖了处理系统资源或执行其他清理的finalize方法。
这个方法简单理解为就是用来垃圾回收的,什么时候回收呢?不确定。
具体情况下什么时候回收呢?自行上网了解GC机制(面试会问道)