介绍这个类之前,先回顾一下API:
java.lang.Object
类是Java语言中的根类,即所有类的父类。它中描述的所有方法子类都可以使用。在对象实例化的时候,最终找的父类就是Object。
如果一个类没有特别指定父类, 那么默认则继承自Object类。例如:
public class MyClass /*extends Object*/ { // ... }
根据JDK源代码及Object类的API文档,Object类当中包含的方法有11个。今天我们主要学习其中的2个:
public String toString()
:返回该对象的字符串表示。
public boolean equals(Object obj)
:指示其他某个对象是否与此对象“相等”。比较的是地址!!
public String toString()
:返回该对象的字符串表示。
toString方法返回该对象的字符串表示,其实该字符串内容就是:对象的类型+@+内存地址值。
由于toString方法返回的结果是内存地址,而在开发中,基本用不到打印对象的地址形式。因此经常需要按照对象的属性得到相应的字符串表现形式,因此也需要重写它。
看案例:
但是,开发中直接输出对象,默认输出对象的地址其实是毫无意义的 开发中输出对象变量,更多的时候是希望看到对象的内容数据而不是对象的地址信息
toString存在的意义 父类toString()方法存在的意义就是为了被子类重写,以便返回对象的内容信息,而不是地址信息。
如果不希望使用toString方法的默认行为,则可以对它进行覆盖重写。例如自定义的Person类:
public class Person { private String name; private int age; @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + '}'; } // 省略构造器与Getter Setter }
不知道你还记不记得之前说过那个ptg插件快速生成标准javabean类的方式,里面就有这个toString()方法的重写。现在知道它是干什么用的了吧!
当然在IDEA中,有快捷键单独生成重写这个toString()方法的快捷键。
在IntelliJ IDEA中,可以点击
Code
菜单中的Generate...
,也可以使用快捷键
alt+insert
,点击toString()
选项。选择需要包含的成员变量并确定。如下图所示:
小贴士: 在我们直接使用输出语句输出对象名的时候,其实通过该对象调用了其toString()方法。
总结:
toString()方法的意义是为了被重写,这就是它的意义。
public boolean equals(Object obj)
:指示其他某个对象是否与此对象“相等”。
调用成员方法equals并指定参数为另一个对象,则可以判断这两个对象是否是相同的。这里的“相同”有默认和自定义两种方式。
如果没有覆盖重写equals方法,那么Object类中默认进行 =
=
运算符的对象地址比较,只要不是同一个对象,结果必然为false。
注意:这里不是之前那个String的equals的字符串内容比较。因为现在Student不是String,因此它在调用equals()方法时是调用Object类里的equals()。我们可以转到定义下去看:
发现在Object类里的equals()方法的确比较的是地址值。由于比较地址值在开发中基本用不到,所以我们基本都要重写该方法:
不用完全看懂这个代码,只需知道它是比较对象的内容,而不是是比较地址。注意这里用到了Objects类,这个后面还会学。
再看:
为什么这里就是true??因为String是Object的子类,在String中重写了equals()方法,我们转到定义看一下:
发现第一行if是在比较地址值,意思是说如果地址相同,即同一个对象,那么内容也必相同。如果地址不同就比较内容,后面的代码可以不用看懂,但是你把那个末尾那个equals()再转到定义:
发现确确实实是在比较内容。
如果希望进行对象的内容比较,即所有或指定的部分成员变量相同就判定两个对象相同,则可以覆盖重写equals方法。例如:
import java.util.Objects; public class Person { private String name; private int age; @Override public boolean equals(Object o) { // 如果对象地址一样,则认为相同 if (this == o) return true; // 如果参数为空,或者类型信息不一样,则认为不同 if (o == null || getClass() != o.getClass()) return false; // 转换为当前类型 Person person = (Person) o; // 要求基本类型相等,并且将引用类型交给java.util.Objects类的equals静态方法取用结果 return age == person.age && Objects.equals(name, person.name); } }
这段代码充分考虑了对象为空、类型一致等问题,但方法内容并不唯一。但是不用真的手动取实现重写这个方法。大多数IDE都可以自动生成equals方法的代码内容。在IntelliJ IDEA中,可以使用Code
菜单中的Generate…
选项,也可以使用
快捷键alt+insert
,并选择equals() and hashCode()
进行自动代码生成。如下图所示:
接着:
接着:
一直惦记next即可。
tips:Object类当中的hashCode等其他方法,今后学习。
回顾前面的一个问题,打印引用数据类型的对象名是打印一个地址(String除外),为什么是这样??
之前只是让注意区别没有说具体原因,现在学了Object类,可以解释一下原因。是因为printin这个函数本身的原因,我们分别转到定义看一下:
先看打印学生对象的那个pintln,转到定义看一下:
看不懂不要紧,再看第二个
发现转到定义时,形参都不是一样的,因此对他们的处理固然不一样。要彻底弄懂还得学更多的东西,但是目前只知道这么多。至少现在知道打印String对象名为什么打印的是内容,而不是地址。
小案例:
理解这个代码的执行过程和底层原理哦。也就是掌握Object类。
关于equals和toString方法的作用:
1.如果以后想要比较两个对象的属性值是否相等,就在Javabean类中重写equals方法。
2.如果以后想打印一个对象,出现的不是地址值,而是属性值,就在Javabean类中重写toString方法。
Objects类是对象工具类,它里面的的方法都是用来操作对象的。
在刚才IDEA自动重写equals代码中,使用到了java.util.Objects
类,那么这个类是什么呢?
在JDK7添加了一个Objects工具类,它提供了一些方法来操作对象,它由一些静态的实用方法组成,这些方法是null-save(空指针安全的)或null-tolerant(容忍空指针的),用于计算对象的hashcode、返回对象的字符串表示形式、比较两个对象。
在比较两个对象的时候,Object的equals方法容易抛出空指针异常,而Objects类中的equals方法就优化了这个问题。这是二者的一个区别之一。方法如下:
public static boolean equals(Object a, Object b)
:判断两个对象是否相等。
我们可以查看一下源码,学习一下:
public static boolean equals(Object a, Object b) { return (a == b) || (a != null && a.equals(b)); }
看案例:
Objects的equals
string的equlas:
抛出空指针异常。
static boolean isNull(Object obj) 判断对象是否为null,如果为null返回true。
Student s1 = null; Student s2 = new Student("蔡徐坤", 22); // static boolean isNull(Object obj) 判断对象是否为null,如果为null返回true System.out.println(Objects.isNull(s1)); // true System.out.println(Objects.isNull(s2)); // false
java.lang.Math(类): Math包含执行基本数字运算的方法。
它不能创建对象,它的构造方法被“私有”了。因为他内部都是“静态方法”,通过“类名”直接调用即可。
方法名 | 说明 |
---|---|
public static int abs(int a) | 获取参数a的绝对值: |
public static double ceil(double a) | 向上取整 |
public static double floor(double a) | 向下取整 |
public static double pow(double a, double b) | 获取a的b次幂 |
public static long round(double a) | 四舍五入取整 |
public class Demo { public static void main(String[] args) { System.out.println("-5的绝对值:" + Math.abs(-5));//5 System.out.println("3.4向上取整:" + Math.ceil(3.4));//4.0 System.out.println("3.4向下取整:" + Math.floor(3.4));//3.0 System.out.println("2的8次幂:" + Math.pow(2, 8));//256.0 System.out.println("3.2四舍五入:" + Math.round(3.2));//3 System.out.println("3.5四舍五入:" + Math.round(3.5));//4 } }
java.lang.System
类中提供了大量的静态方法,可以获取与系统相关的信息或系统级操作。
方法名 | 说明 |
---|---|
public static void exit(int status) | 终止当前运行的 Java 虚拟机,非零表示异常终止 |
public static long currentTimeMillis() | 返回当前时间(以毫秒为单位),时间七点为1970年1月1日(C语言出生的生日) |
public static void arraycopy(数据源数组, 起始索引, 目的地数组, 起始索引, 拷贝个数) | 数组拷贝 |
在控制台输出1-10000,计算这段代码执行了多少毫秒
import java.util.Date; //验证for循环打印数字1-9999所需要使用的时间(毫秒) public class SystemDemo { public static void main(String[] args) { //获取当前时间毫秒值 System.out.println(System.currentTimeMillis()); //计算程序运行时间 long start = System.currentTimeMillis(); for (int i = 1; i <= 10000; i++) { System.out.println(i); } long end = System.currentTimeMillis(); System.out.println("共耗时毫秒:" + (end - start)); } }
小补充:
浮点数做运算精度问题;
看程序说结果:
public static void main(String[] args) { System.out.println(0.09 + 0.01); System.out.println(1.0 - 0.32); System.out.println(1.015 * 100); System.out.println(1.301 / 100); }
运行结果:
和想象的结果不太一样,怎么才能精确计算呢?此时就需要BigDecimal类。
BigDecimal类提供了算术,缩放操作,舍入,比较,散列和格式转换的操作。提供了更加精准的数据计算方式
构造方法名 | 描述 |
---|---|
BigDecimal(double val) | 将double类型的数据封装为BigDecimal对象 |
BigDecimal(String val) | 将 BigDecimal 的字符串表示形式转换为 BigDecimal |
注意:推荐使用第二种方式,第一种存在精度问题;或者是直接使用valueof方法:
看个小案例:
使用valueof方法:
其余的自己去借助API文档学习。
BigDecimal类中使用最多的还是提供的进行四则运算的方法,如下:
方法声明 | 描述 |
---|---|
public BigDecimal add(BigDecimal value) | 加法运算 |
public BigDecimal subtract(BigDecimal value) | 减法运算 |
public BigDecimal multiply(BigDecimal value) | 乘法运算 |
public BigDecimal divide(BigDecimal value) | 触发运算 |
注意:对于divide方法来说,如果除不尽的话,就会出现java.lang.ArithmeticException异常。此时可以使用divide方法的另一个重载方法;
BigDecimal divide(BigDecimal divisor, int scale, int roundingMode): divisor:除数对应的BigDecimal对象;scale:精确的位数;roundingMode取舍模式
小结:Java中小数运算有可能会有精度问题,如果要解决这种精度问题,可以使用BigDecimal
第三天总结:(内容比较多而且比较难)
1,为什么要有多态?
2,多态创建对象的格式?
3,多态中调用成员变量和成员方法的特点?
4,以后我们创建对象是用多态方式,还是用普通方式呢?
5,多态在实际开发中的应用场景?
6,匿名内部类的格式?
7,匿名内部类在实际开发中有什么作用?
8,API和API帮助文档的区别?
9,Object和Objects两个类的作用。熟悉里面的讲解的方法
10,Math类的作用,熟悉里面的方法
11,System类的作用,熟悉里面的方法
12,BigDecimal类的作用,熟悉里面的方法
强调:API里面的方法,不需要背,以后用到了要学会如何查。
今天我们先学会,查询Object,Objects,Math,System,BigDecimal,BigDecimal的舍入模式。