Object类、常用API
一、Object类
1. Object类的 toString 方法
java.lang.Object
类是类层次结构的根(最顶层)类。每个类都使用Object
作为超(父)类。- 所有对象(包括数组)都实现这个
Object
类的方法。 String toString();
方法返回该对象的字符串的表示。- 直接打印一个对象的名字,其实就是调用对象的
toString
方法。 - 判断一个类是否重写了
toString
方法,直接打印这个类对应的对象即可。- 如果没有重写
toString
方法,那么打印的就是对象的地址值(默认)。 - 如果重写了
toString
方法,那么就按照重写的方式打印。
- 如果没有重写
public class Person {
private String name;
private int age;
//覆盖重写toString方法
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
public class Test {
public static void main(String[] args) {
Person person = new Person("朱古力",18);
//未覆盖重写toString方法时,打印对象的地址值
System.out.println(person); // demo01.Person@77459877
//覆盖重写之后,按照重写的格式打印
System.out.println(person); // Person{name='朱古力', age=18}
}
}
2. Object类的equals方法
-
boolean equals(Object obj)
指示其他某个对象与此对象”相等“。 -
Object
类equals
方法的源码:public boolean equals(Object obj) { return (this == obj); }
- 参数
Object obj
可以传递任意的对象。 - 方法体:
==
比较运算符,返回一个布尔值。- 基本数据类型:比较的是值。
- 引用数据类型:比较的是两个对象的地址值。
this
:谁调用该方法,this
就是谁。
- 参数
public class Person {
private String name;
private int age;
//覆盖重写toString方法
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
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) ); // false
}
}
3. 重写Object类的equals方法
Object
类的equals
方法默认比较的是两个对象的地址值,没有意义。- 需要重写
equals
方法,比较两个对象的属性值。若对象的属性值一样,返回true
,否则返回false
。 - **问题:**隐含多态(参数为
Object
类型)。多态的弊端:无法使用子类特有的内容。 - **解决:**使用向下转型。
public class Person {
private String name;
private int age;
//覆盖重写toString方法
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
//覆盖重写equals方法
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (this == obj) {
return true;
}
if ( obj instanceof Person) {
Person person = (Person) obj;
boolean bool = this.age == person.age && this.name.equals(person.name);
return bool;
}
return false;
}
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
public class Test {
public static void main(String[] args) {
Person person1 = new Person("朱古力",18);
Person person2 = new Person("朱古力",18);
// 未覆盖重写equals时,两对象地址值不同
//System.out.println( person1.equals(person2) ); // false
//覆盖重写equals方法
System.out.println(person1.equals(person2)); // true
System.out.println(person1.equals(person1)); // true
System.out.println(person1.equals(null)); // false
}
}
4. Objects类的equals方法
-
null
是不能调用方法的,会抛出空指针异常。 -
Objects
类的equals
方法:对两个对象进行比较,防止空指针异常。 -
源码:
public static boolean equals(Object a, Object b) { return (a == b) || (a != null && a.equals(b)); }
import java.util.Objects;
public class Test {
public static void main(String[] args) {
String str1 = null;
String str2 = "abc";
//null是不能调用方法的,会抛出空指针异常
//boolean bool1 = str1.equals(str2);
//使用Objects类的equals方法,防止空指针异常
boolean bool2 = Objects.equals(str1, str2);
System.out.println(bool2); // false
}
}
5. Object类和Objects类总结
-
Object
类介绍Object
类是所有类的父类。一个类都会直接或者间接的继承自该类。- 该类提供了一些非常常用的方法。
-
toString()
方法- 作用:打印对象的信息。
- 覆盖重写前:打印的是包名类名@地址值
- 覆盖重写后:打印的是对象中的属性值
-
equals()
方法- 作用:比较两个对象
- 覆盖重写前:比较的是两个对象的地址值
- 覆盖重写后:比较的是两个对象中的属性值
-
Objects
中的equals()
方法- 比较两个对象是否相同,但是增加了一些健壮性的判断。
二、日期时间类
1. 毫秒值的概念和作用
java.util.Date
:表示日期和时间的类。- 类
Date
表示特定的瞬间,精确到毫秒。 - 毫秒值的作用:可以对时间和日期进行计算。
- 可以将日期转换为毫秒进行计算,计算完毕,再把毫秒转换为日期。
- 时间原点(0毫秒):1970年1月1日 00:00:00(英国格林威治)
- 中国属于东八区,将时间增加8个小时:1970年1月1日 08:00:00。
2. Date类的构造方法和成员方法
Date
类的空参数构造方法:Date()
获取的是当前系统的时间和日期。
Date
类的带参数构造方法:Date(Long date)
传递毫秒值,将毫秒转换为Date
日期。
Date
类的成员方法:long getTime()
:将日期转换为毫秒(相当于System.currentTimeMillis()
),返回自1970年1月1日 00:00:00 GMT 以来,此Date
对象表示的毫秒数。
import java.util.Date;
public class Test {
public static void main(String[] args) {
//无参构造,获得系统当前日期与时间
Date date1 = new Date();
System.out.println(date1); // Sun Jan 12 20:22:29 CST 2020
//有参构造,将传入的毫秒参数值转换为日期
Date date2 = new Date(123456789L);
System.out.println(date2); // Fri Jan 02 18:17:36 CST 1970
//成员方法,返回自时间原点到当前时间的毫秒数
Date date3 = new Date();
long time = date3.getTime();
System.out.println(time); // 1578831920840
}
}
3. DateFormat类与SimpleDateFormat类介绍
-
java.text.DateFormat
是日期/时间格式化子类的抽象类。 -
作用:
- 格式化:(日期 ——> 文本)
- 解析:(文本 ——> 日期)
-
成员方法:
String format(Date date)
按照指定的模式,把Date
日期,格式化为符合模式的字符串。Date parse(String source)
把符合模式的字符串解析为Date
日期。
-
DateFormat
类是一个抽象类,无法直接创建对象的使用,可以使用DateFormat
的子类。 -
java.text.SimpleDateFormat extends DateFormat
-
构造方法:
-
SimpleDateFormat(String pattern)
用给定的模式和默认语言环境的日期格式符号构造SimpleDateFormat
。 -
参数:
String pattern
传递指定的模式。 -
模式:区分大小写。
y 年 M 月 d 日 H 时 m 分 s 秒 - 写对应的模式,会把模式替换为对应的日期和时间。
- 例如:“yyyy-MM-dd HH:mm:ss” “yyyy年MM月dd日 HH时mm分ss秒”
-
注意:模式中的字母不能更改,连接模式的符号可以改变。
-
4. DateFormat类的format和parse方法
-
使用
DateFormat
类中的方法format
,把日期格式化为文本。 -
String format(Date date)
按照指定的模式,把Date
日期格式化为符合模式的字符串。 -
使用步骤:
- 创建
SimpleDateFormat
对象,构造方法中传递指定的模式。 - 调用
SimpleDateFormat
对象中的方法format
,按照构造方法中指定的模式,把Date
日期格式化为符合模式的字符串(文本)。
import java.text.SimpleDateFormat; import java.util.Date; public class Test { public static void main(String[] args) { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Date date = new Date(); String time = sdf.format(date); System.out.println(date); // Sun Jan 12 21:09:26 CST 2020 System.out.println(time); // 2020-01-12 21:07:50 } }
- 创建
-
使用
DateFormat
类中的方法parse
方法,将文本解析为日期。 -
Date parse(String source)
把符合模式的字符串,解析为Date
日期。 -
使用步骤:
- 创建
SimpleDateFormat
对象,构造方法中传递指定的模式。 - 调用
SimpleDateFormat
对象中的方法parse
,把符合构造方法中模式的字符串,解析为Date
日期。
- 创建
-
注意:
public Date parse(String source) throws ParseException
。parse
方法声明了一个异常:ParseException
解析异常。- 如果字符串和构造方法中的模式不一样,那么程序就会抛出此异常。
- 调用一个抛出了异常的方法,就必须处理这个异常:要么
throws
继续声明抛出这一个异常,要么try...catch
自己处理这个异常。
public class Test { public static void main(String[] args) throws ParseException { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Date date = sdf.parse("2020-01-12 21:09:26"); System.out.println(date); // Sun Jan 12 21:09:26 CST 2020 } }
5. 练习
//题目:使用日期时间相关的API,计算一个人已经出生了多少天。
/*
分析:
1.利用Scanner获取用户的出生日期
2.将输入的日期转换为Date类型
3.再讲Date类型的日期转换为毫秒值
4.获取当前日期
5.将当前日期转换为毫秒值
6.用当前日期的毫秒值 - 出生日期的毫秒值
7.将毫秒值的差值转换为天数(time/1000/60/60/24)
*/
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Scanner;
public class Prac {
public static void main(String[] args) throws ParseException {
Scanner sc = new Scanner(System.in);
System.out.println("请输入您的出生日期,格式为:yyyy-MM-dd");
String birthdayString = sc.next();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date birthdayDate = sdf.parse(birthdayString);
long birthdayTime = birthdayDate.getTime();
long todayTime = new Date().getTime();
long time = todayTime - birthdayTime;
System.out.println("你已经来到这个世界" + time/1000/60/60/24 + "天了!");
}
}
三、Calendar类
1. Calendar类介绍:获取对象的方式
-
java.util.Calendar
类:日历类 -
Calendar
类是一个抽象类,里边提供了很多操作日历字段的方法(YEAR , MONTH , DAY_OF_MONTH , DAY
) -
Calendar
类无法直接创建对象使用,里边有一个静态方法:getInstance()
,该方法返回了Calendar
类的子类对象。 -
static Calendar getInstance()
使用默认时区和语言环境获得一个日历。public class Test { public static void main(String[] args) { Calendar c = Calendar.getInstance(); // 多态 // 重写了toString方法 System.out.println(c); } }
2. Calendar类的常用成员方法
-
public int get(int field)
:返回给定日历字段的值。-
int field
:日历类的字段,可以使用Calendar
类的静态成员变量获取。public static final int YEAR = 1; 年 public static final int MONTH = 2; 月 public static final int DATE = 5; 月中某一天 public static final int DAY_OF_MONTH = 5; 月中某一天 public static final int HOUR = 10; 时 public static final int MINUTE = 12; 分 public static final int SECOND = 13; 秒
import java.util.Calendar; public class Test01 { public static void main(String[] args) { Calendar calendar = Calendar.getInstance(); int year = calendar.get(Calendar.YEAR); //注意:月份是0~11 int month = calendar.get(Calendar.MONTH); int day = calendar.get(Calendar.DAY_OF_MONTH); System.out.println("今天是" + year + "年" + month+1 + "月" + day + "日"); //今天是2020年01月12日 } }
-
-
public void set(int field, int value)
:将给定的日历字段设置为给定值import java.util.Calendar; public class Test02 { public static void main(String[] args) { Calendar calendar = Calendar.getInstance(); calendar.set(Calendar.YEAR, 9999); calendar.set(Calendar.MONTH, 9); calendar.set(Calendar.DATE, 9); //还可以使用重载形式 //calendar.set(9999,9,9); int year = calendar.get(Calendar.YEAR); int month = calendar.get(Calendar.MONTH); int day = calendar.get(Calendar.DAY_OF_MONTH); System.out.println("设置后是:" + year + "年" + month + "月" + day + "日"); //设置后是:9999年9月9日 } }
-
public abstract void add(int field, int amount)
:根据日历的规则,为给定的日历字段添加或减去指定的时间量。public class Test03 { public static void main(String[] args) { Calendar calendar = Calendar.getInstance(); calendar.add(Calendar.YEAR, 1); System.out.println(calendar.get(Calendar.YEAR)); // 2021 calendar.add(Calendar.YEAR, -1); System.out.println(calendar.get(Calendar.YEAR)); // 2020 } }
-
public Date getTime()
:返回一个表示此Calendar时间值的Date对象。import java.util.Calendar; import java.util.Date; public class Test04 { public static void main(String[] args) { Calendar calendar = Calendar.getInstance(); Date date = calendar.getTime(); System.out.println(date); // Sun Jan 12 22:49:15 CST 2020 } }
四、System类的常用方法
-
public static long currentTimeMillis()
:返回以毫秒为单位的当前时间。- 可以用来测试程序的效率。
public class Test01 { public static void main(String[] args) { long start = System.currentTimeMillis(); for (int i = 0; i < 9999; i++) { System.out.println(i); } long end = System.currentTimeMillis(); System.out.println("共消耗了 " + (end - start) + " 毫秒!"); } }
-
public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
:将数组中指定的数据拷贝到另一数组中。src
:源数组srcPos
:源数组中的起始位置dest
:目标数组destPos
:目标数组中的起始位置length
:要复制的数组元素的数量
public class Test02 { public static void main(String[] args) { int[] src = {1, 2, 3, 4, 5}; int[] dest = {6, 7, 8, 9, 10}; System.out.print("原目标数组:"); // 原目标数组:6 7 8 9 10 for (int i = 0; i < dest.length; i++) { System.out.print(dest[i] + " "); } System.out.println(); System.arraycopy(src,0,dest,0,3); System.out.print("处理后的目标数组:"); // 处理后的目标数组:1 2 3 9 10 for (int i = 0; i < dest.length; i++) { System.out.print(dest[i] + " "); } } }
五、StringBuilder类
1. StringBuilder的原理
- String类
- 字符串是常量,它们的值在创建之后不能更改。
- 字符串的底层是一个
final
修饰的数组,不能改变,是一个常量。private final byte[] value;
- 进行字符串相加,内存中就会有多个字符串,占用空间高,效率低下。
- 例如:
String s = "a" + "b" + "c";
底层会有5个数组保存5个字符串(“a”, “b”, “c”, “ab”, “abc”)
- 例如:
- StringBuilder类
- 字符串缓冲区,可以提高字符串的操作效率(看为一个长度可以变化的字符串)。
- 底层也是一个数组,但是没有被
final
修饰,可以改变长度。byte[] value = new byte[16];
StringBuilder
在内存中始终是一个数组,占用空间少,效率高。- 例如:
"a" + "b" + "c"
这三个字符串会保存在一个同一个数组中。
- 例如:
- 如果超出了
StringBuilder
的容量,会自动扩容。
2. StringBuilder的构造方法
java.lang.StringBuilder
类:字符串缓冲区,可以提高字符串的效率。- 构造方法:
public StringBuilder()
构造一个空的StringBuilder
容器。public StringBuilder(String str)
构造一个StringBuilder
容器,并将字符串添加进去。
public class Test {
public static void main(String[] args) {
StringBuilder str1 = new StringBuilder();
System.out.println("str1: " + str1); // str1:
StringBuilder str2 = new StringBuilder("abc");
System.out.println("str2: " + str2); // str2: abc
}
}
3. StringBuilder的成员方法
public StringBuilder append(...)
添加任意类型数据的字符串形式,并返回当前对象自身。- 参数:可以是任意的数据类型。
- 返回值:返回调用者自身
this
,故无需接收返回值。 - 链式编程:方法的返回值是一个对象,可以根据对象继续调用方法。
public class Test01 {
public static void main(String[] args) {
StringBuilder str1 = new StringBuilder();
StringBuilder str2 = str1.append("abc");
// 返回的是调用方法的对象
System.out.println(str1); // abc
System.out.println(str2); // abc
System.out.println(str1 == str2); // true
// 可以接收任意数据类型
StringBuilder str3 = new StringBuilder();
str3.append("zhu");
str3.append("古");
str3.append('力');
str3.append(520);
str3.append(13.14);
System.out.println(str3); // zhu古力52013.14
// 链式编程
StringBuilder str4 = new StringBuilder();
str4.append("zhu").append("古").append('力').append(520).append(13.14);
System.out.println(str4); // zhu古力52013.14
}
}
StringBuilder
和String
可以相互转换:String —> StringBuilder
:可以使用StringBuilder
的构造方法。StringBuilder —> String
:可以使用StringBuilder
中的toString
方法。public String toString()
:将当前StringBuilder
对象转化为String
对象。
public class Test02 {
public static void main(String[] args) {
String string = "Hello";
StringBuilder stringBuilder = new StringBuilder(string);
stringBuilder.append("World!");
System.out.println("string: " + string); // string: Hello
string = stringBuilder.toString();
System.out.println("string: " + string); // string: HelloWorld!
System.out.println("stringBuilder: " + stringBuilder); // stringBuilder: HelloWorld!
}
}
六、包装类
1. 包装类的概念
- 包装类:基本数据类型的数据,使用起来非常方便,但是没有对应的方法来操作这些数据,所以可以使用一个类,把基本数据类型的数据包装起来,这个类叫做包装类。
- 在包装类中可以定义一些方法,用来操作基本数据类型。
基本类型 | 对应的包装类(位于java.lang 包中) |
---|---|
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
char | Character |
Boolean | Boolean |
2. 包装类的装箱与拆箱
- **装箱:**把基本数据类型的数据,包装到包装类中。(基本数据类型 —> 包装类)
- 构造方法:
Integer(int value)
构造一个新分配的Integer
对象,它表示指定的int
值。Integer(String s)
构造一个新分配的Integer
对象,它表示String
参数所指示的int
值。- 传递字符串时,必须是基本数据类型的字符串,否则会抛出异常。
- 静态方法:
static Integer valueOf(int i)
返回一个表示指定的int
值的Integer
实例。static Integer valueOf(String s)
返回保存指定的String
的值的Integer
对象。
- 构造方法:
- **拆箱:**在包装类中取出基本类型的数据。(包装类 —> 基本数据类型)
- 成员方法:
int intValue
以int
类型返回该Integer
的值。
- 成员方法:
public class Test01 {
public static void main(String[] args) {
//装箱:使用构造方法
Integer integer1 = new Integer(11);
Integer integer2 = new Integer("123");
System.out.println(integer1); // 11
System.out.println(integer2); // 123
//装箱:使用静态方法
Integer integer3 = Integer.valueOf(22);
Integer integer4 = Integer.valueOf("234");
System.out.println(integer3); // 22
System.out.println(integer4); // 234
//拆箱:使用成员方法
int i = integer1.intValue();
System.out.println(i); // 11
}
}
3. 包装类的自动装箱与自动拆箱
- 自动装箱与自动拆箱:基本类型数据和包装类之间可以自动的相互转换。
JDK1.5
之后出现的新特性。
public class Test02 {
public static void main(String[] args) {
//自动装箱
Integer integer = 12;
System.out.println(integer); // 12
//自动拆箱
int i = integer;
System.out.println(i); // 12
}
}
4. 包装类的基本数据类型与字符串类型之间的相互转换
- 基本类型 —> 字符串类型
基本数据类型的值 + ""
(常用)- 使用包装类中的静态方法:
static Srting toString(int i)
- 使用
String
类中的静态方法:static String valueOf(int i)
- 字符串类型 — > 基本类型
- 使用包装类的静态方法
parseXxx("字符串")
- 注意:
Character
没有此方法。
- 使用包装类的静态方法
public class Test03 {
public static void main(String[] args) {
// 基本类型 —> 字符串类型
// 基本数据类型的值 + ""
String str1 = 100 + "";
System.out.println(str1 + 200); // 100200
// 使用包装类的静态方法
String str2 = Integer.toString(100);
System.out.println(str2 + 200); // 100200
// 使用String类的静态方法
String str3 = String.valueOf(100);
System.out.println(str3 + 200); // 100200
//字符串类型 —> 基本类型
//使用包装类的静态方法
int i = Integer.parseInt("100");
System.out.println(i + 200); // 300
}
}