
「JavaSE学习笔记02」对象与类
¶Chapter 4. 对象与类
¶4.1 面向对象程序设计概述
面向对象程序设计(简称OOP),是当今主流程序设计范型。面向对象的程序是由对象组成的,每个对象(来自于标准库或自定义的)包含对用户公开的特定功能和隐藏的实现部分。在OOP中,不必关心对象的具体实现,只要能够满足用户的需求即可。面向对象的语言中,包含了三大基本特征:封装、继承、多态。
¶4.1.1 类
类(class),是构造对象的模板或蓝图。由类构造(construct)对象的过程,成为类的实例(instance)。
封装(encapsulation),给予对象“黑盒”特征,将数据与行为组合在一个包中,并对对象的使用者隐藏了数据的实现方式。对象中的数据成为实例域(instance fields),操纵数据的过程成为方法(method)。对于每个特定的类实例(对象)都有一组特定的实例域值,这些值的集合就是这个对象的当前状态。
类之间,最常用的关系:
依赖(“uses-a”)——一个类的方法操纵另一个类的对象
应尽可能将相互依赖的类减至最小。若类A不知道B的存在,它就不关心B的任何改变(即不会导致A产生BUG)。用软件工程的术语来说,就是让类之间的耦合度最小。
聚合(“has-a”)——意味着类A的对象包含类B的对象
继承(“is-a”)——若类A拓展类B,类A不但包含从类B继承的方法,还会拥有一些额外的功能。
¶4.1.2 对象
对象,是类的实体。它是一类事物的具体体现,它必然具备某类事物的属性和行为。
要想使用OOP,需清楚对象的三个主要特性:
- 对象的行为——可对对象施加哪些操作或哪些方法?
- 对象的状态——当施加那些方法时,对象如何响应?
- 对象标识——如何辨识具有相同行为与状态的不同对象?
同一个类的所有对象实例,由于支持相同行为而具有家族相似性。对象的行为是用可调用的方法定义的。
此外,每个对象都保存着描述当前特征的信息,即对象的状态。对象状态的改变必须通过调用方法实现。(若不经方法调用就改变对象状态,说明封装性遭破坏)
但是,对象的状态并不能完全描述一个对象,每个对象均有一个唯一的身份。需注意,作为一个类的实例,每个对象的标识永远不同,状态常常存在差异。
¶4.2 对象与类的相关操作
我们接下来编写的主力类(workhorse class),没有main方法而却有自定义的实例域和实例方法。若要创建一个完整的程序,应将若干类组合在一起,其中只有一个类有main方法。
Java中,一个源文件只能有一个公有类。但可以有任意个非公有类。许多程序员习惯将每一个类存在一个单独的源文件中。
¶4.2.1 最简单的类的定义
1 | |
注意事项:
- 成员变量是直接定义在类内部,在方法外部。若成员变量没有进行复制,那么会有默认值(规则与数组相同)
- 成员方法不用写
static关键字。 - 在Java中,所有方法都必须在类的内部定义,但并不表示它们是内联方法(这交给Java虚拟机去解决)。
局部变量与成员变量的区别:
| 局部变量 | 成员变量 | |
|---|---|---|
| 定义位置 | 方法内部 | 方法外部、写于类内部 |
| 内存位置 | 栈内存 | 堆内存 |
| 作用域 | 只有在方法当中可以使用 | 在整个类均可使用 |
| 生命周期 | 随方法进栈而诞生(随方法出栈而消失) | 随对象创建而诞生(随对象被垃圾回收而消失) |
| 默认值 | 无默认值,若要使用则必须赋值。 | 若没有赋值,则会自带默认值。 |
¶4.2.2 标准类(Java Bean)的定义
标准的类,也称Java Bean。它需满足:
都要使用
private关键字修饰,相应地,需为每一成员变量编写一对Getter/Setter方法。(详见下方的4.3)类需要编写一个无参数的构造方法与一个全参数的构造方法。
1 | |
利用IDEA来生成相应方法:(以Getter/Setter为例,若要生成构造方法同理)

选择你需要生成的方法类型,此处选中Getter和Setter,得到下面窗口。

下图即为生成成功。

TIPS:有些程序员会为每个参数前面加上一个前缀"a"。如:
public Employee(String aName, double aSalary),十分清晰。C++中一般用下划线作为实例域的前缀(
确实),如salary域会被命名为_salary。但Java程序员通常不这样做。
¶4.2.3 对象的构造方法
构造方法(构造器)就是专门用于创建对象的方法,当我们通过关键字new来创建对象时,实际上就是在调用构造方法。其格式为:
1 | |
注意事项:
- 仅当类没有提供任何构造方法的时候,系统才会提供一个默认的构造方法。(一旦编写了至少一个构造方法,系统则不再提供)
- 构造方法的名称必须与所在的类名称完全一样(包括大小写)。
- 构造方法不要写返回值类型(连
void都不写),当然也不能return一个具体的返回值。 - 构造方法总是伴随
new操作一起调用。
¶4.2.4 对象的创建与使用
我们知道,一个类并不能直接使用,需要根据类创建一个对象,方能使用。
导包:指出需要使用的类在哪里
格式:
import 包名称.类名称;1
import day03.demo1.Student; //别漏分号注:对于和当前类属于同一个包的情况,可省略不写导包语句
在Java中,
package与import语句,类似于C++中namespace和using指令创建
格式:
类名称 对象名 = new 类名称()或者类名称 对象名 = new 类名称(参数1, 参数2, ...)1
Student stu = new Student();使用
(在没有
Setter&Getter的情况下)使用成员变量:对象名.成员变量名使用成员方法:
对象名.成员方法名(参数1, 参数2, ...)
1 | |
¶[附]几个对象的内存图

在Java中,任何对象变量的值都是对存储在另外一个地方的一个对象的引用。new操作符的返回值也是一个引用。
可以将Java对象变量看作C++的对象指针。
1
2
3Date birthday; //Java;
等同于
Date* birthday; //C++
¶4.2.5 匿名对象
格式:new 类名称();
注意事项:匿名对象只能使用唯一一次,下次再使用时必须创建一个新对象。
使用建议:若确定有一个对象只需要使用唯一的一次,便可用匿名对象。
1 | |
¶4.2.6 静态static关键字
若类中的某个成员变量或方法用static关键字修饰,则以后创建的对象中的static修饰的变量或方法不再属于对象自己,而是属于类,也就说凡是本类的对象,都共享同一份。
无论是成员变量,还是成员方法。若有了static修饰,都推荐使用类名称进行调用。
static关键字修饰成员变量1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32/* Student.java文件中 */
public class Student {
private int id;
private String name;
static String room;
private static int idCounter = 0;//学号计数器,每new一个新对象便自增
public Student(){
this.id = ++idCounter;
}
public Student(String name){
this.name = name;
this.id = ++idCounter;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
}
/* JustTest.java文件中 */
public class JustTest {
public static void main(String[] args) {
Student one = new Student("Luffy");
one.room = "101教室";
System.out.printf("%s的学号为:%d,教室为:%s\n", one.getName(), one.getId(), one.getRoom());
Student two = new Student("Nami");
System.out.printf("%s的学号为:%d,教室为:%s\n", two.getName(), two.getId(), two.getRoom());
}
}static关键字修饰成员方法1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33/* MyClass.java文件中 */
public class MyClass {
int num; //成员变量
static int numStatic; //静态变量
public void method(){ //成员方法
System.out.println("我是成员方法!");
System.out.println(num); //成员方法可访问成员变量
System.out.println(numStatic); //成员方法可访问静态变量
}
public static void methodStatic(){ //静态方法
System.out.println("我是静态方法!");
//System.out.println(num); 错误写法!静态方法不能访问非静态变量
System.out.println(numStatic); //静态方法可访问静态变量
//System.out.println(this); 错误写法!静态方法不能使用this关键字
}
}
/* JustTest.java文件中 */
public class JustTest {
public static void main(String[] args) {
MyClass obj = new MyClass(); //创建对象方能使用非静态的成员方法
obj.method();
obj.methodStatic(); //正确,但不推荐
MyClass.methodStatic(); //对于静态方法,可直接通过类名称来调用
myMethod(); //本类当中的静态方法,可直接省略类名称
JustTest.myMethod(); //完全等效
}
public static void myMethod(){
System.out.println("这是我的方法!");
}
}静态代码块
格式为:
1
2
3
4
5public class 类名称{
static {
//静态代码块中的内容
}
}特点:
一旦第一次使用了该类的静态代码块,该静态代码块以后都不再执行
静态代码块的典型用途:用于一次性地对静态成员变量进行赋值
静态内容总是优先于非静态,故静态代码块比构造方法更早执行。
¶4.3 封装
封装性在Java中的体现:
- 方法是一种封装;
- 关键字
private也是一种封装。
一旦使用private进行修饰,那么本类当中仍然可以随意访问。但是,超出本类范围之外,不能再直接访问了。要间接访问private成员变量,就是定义一对Getter/Setter方法。
仅访问实例域而不进行修改的方法,称之为访问器方法(accessor method)。在Java中,对应为
Getter,不能有参数,返回值类型和成员变量相对应。命令规则一般为getXXX(若为boolean类型,则应命名为isXXX)。eg:getTime对实例域做出修改的方法,称之为更改器方法(mutator method)。在Java中,对应为
Setter,不能有返回值,参数类型与成员变量相对应。命令规则一般为setXXX。eg:setTime
如此封装的好处:
- 可改变内部实现,除了该类的方法之外,不会影响其他代码。
- 更改器方法可以执行错误检查,然而直接对域进行赋值将不会进行这些处理。
¶4.3.1 this
this关键字可以用来访问本类的内容。
一、在本类的成员方法中,访问本类的成员变量。
当方法的局部变量和类的成员变量重名的时候,根据“就近原则”,优先使用局部变量。
1 | |
为了解决上方产生的“二义性”,希望在本类的某个方法中访问本类当中的成员变量,需使用this.成员变量名。在每一个方法中,关键字this表示隐式参数。
即将上面代码块的第四行改为:System.out.println(name + ",你好。我是" + this.name);
二、在本类的成员方法中,访问本类的另一个成员方法。
1 | |
三、在本类的构造方法中,访问本类的另一个构造方法。
注意:this()调用必须是构造方法的第一个语句,且是唯一一个。
1 | |
¶4.4 Scanner类
通过Scanner类的学习,我们能够熟悉如何查询API,如何使用现有的类。
¶4.4.1 引用类型的使用步骤
导包
格式:
import 包路径.类名称;只有
java.lang包下的内容不需要导包,其他的包均需要import语句。创建
格式:
对象名 = new 类名称(参数1,...);使用
格式:
对象名.成员方法名()
¶4.4.2 概述
Scanner类,是一个可以解析基本类型和字符串的简单文本扫描器。它可以实现键盘输入数据到程序当中。
关于Scanner类的导包语句为:
1 | |
使用实例:
1 | |
¶4.5 Random类
Random类用于生成随机数字。
Random导包语句为:
1 | |
创建:
1 | |
使用:
获取一个随机
int型数字,其范围为int所有范围,含正负。1
int num = r.nextInt();获取一个随机
int型数字,传入参数代表右区间界线。范围为左闭右开区间。1
int num = r.nextInt(3); //实际上范围为0,1,2由于是左闭右开区间,如果我们想要得到的随机数,可以这样写:
1
2
3
4
5r.nextInt(b + 1);
r.nextInt(b + 1) + a;
//本来范围为[0, b],现在整体加a,范围变为[a, b + a];
//为了得到[a,b],则对传入参数-a即可。
r.nextInt(b - a + 1) + a;
¶4.6 泛型数组列表:ArrayList集合
¶4.6.1 引入——对象数组
1 | |
由于数组无法在运行过程中改变其本身的规模,此处即引入下一节要介绍的ArrayList类。
¶4.6.2 概述
ArrayList:一种可以动态增长和缩减的索引序列,称为数组列表。在Java SE5.0中,它是一个采用类型参数的泛型类。为了指定数组列表保存的元素对象类型,需要用<>将类名括起来加在后面。例如ArrayList <Employee>
泛型——装在集合当中所有元素,全部是统一的类型。但注意,泛型只能是引用类型,不能是基本类型(因为集合保存的均是引用类型的值)
ArrayList类似于C++的vector模板,它与vector都是泛型类型。但由于Java没有运算符重载,所以它不像vector模板为了便于访问元素重载[]运算符。此外,vector向量是值拷贝,而在Java中,a=b的赋值语句的操作结果,是让a和b引用同一个数组列表。另外,
java.util.List正是ArrayList所实现的接口。
¶4.6.3 数组列表的相关操作
一、创建某个类型的ArrayList集合:
1 | |
对于
ArrayList而言,直接打印得到的不是地址值,而是其内容,若内容为空,则得到空的中括号。
二、向集合添加元素:
public boolean add(E e):向集合当中添加元素,参数类型与泛型一致,返回值为boolean表示是否添加成功。
1 | |
三、通过索引值从集合中获取元素:
1 | |
四、从集合当中删除元素,参数为索引编号,返回值为被删除的元素:
1 | |
五、遍历集合中的元素:
1 | |
六、集合作为参数:
1 | |
¶4.6.4 数组列表存储基本类型数据 与 包装类
如果希望向集合ArrayList当中存储基本类型数据,则必须使用基本类型所对应的包装类。
| 基本类型 | 包装类 |
|---|---|
int | Integer |
char | Character |
byte | Byte |
long | Long |
short | short |
double | Double |
boolean | Boolean |
float | Float |
举例使用:
1 | |
ArrayList<Integer>的效率远远低于int[]数组,因此应该用它构造小型集合。
从JDK 1.5+开始,支持自动打包(autoboxing)(即 基本类型 –> 包装类型)、自动拆包(即 包装类型 –> 基本类型)。
1 | |
¶4.7 String类
Java没有内置的字符串类型,而是在标准Java类库中提供了一个预定义类String,它与C++中的字符串有很大的差异。
每个用双引号括起来的字符串都是(如"abcd")String类的一个实例。
特点:
字符串是常量,它们的值在创建之后不能更改!
1
2
3String strA = "Hello";
strA = "Java";
//上面的写法中,字符串的内容仍然没有改变,这样的写法是修改字符串变量strA,让它应用另外一个字符串。相当于将存放3的数值变量改成存放4一样字符串是共享使用的。
¶4.7.1 字符串的构造方法和直接创建
创建字符串的几种方式:
直接创建(无需使用
new):String str = "Hello!";创建一个空白字符串,不含任何内容:
public String();根据字符数组的内容,来创建对应的字符串:
public String(char[] array);根据字节数组的内容,来创建对应的字符串:
public String(byte[] array);
1 | |
¶4.7.2 字符串常量池、检测字符串是否相等
String类没有提供用于修改字符串的方法。
如果要将下面的str中后面的"key"修改为"ey!",在Java中,要先提取出需要的字符,然后再拼接上替换的字符串。
1 | |
C++的字符串可以修改,即能够修改字符串中的单个字符,但Java不行。
不可变的字符串有一个优点:编译器可以让字符串共享。
字符串常量池存放在方法区❓,而字符串变量指向常量池中相应的位置。
¶检测字符串是否相等:
由于==,对于引用类型而言,是根据地址值比较的。这个运算符只能够确定两个字符串是否放置在同一位置上。而双引号括住的字符串在常量池当中,而new出来的字符串不在常量池中。
1 | |
若确实需要字符串的内容进行比较可使用equals方法:
public boolean equals(Object obj); :参数可以为任何对象,但只有参数为一个字符串并且内容相同(严格区分英文大小写)的才会返回true,否则返回false。
尽管equals方法是可交换的(即a.equals(b)和b.equals(a)效果基本一致),但是,若要对一个常量与一个变量进行比较时,推荐常量字符串写在前面。原因见下:
1 | |
【附】:int compareTo(String other):按照字典序,若字符串位于other之前,返回负数;若字符串位于other之后返回正数;若两个字符串相等,返回0。
¶4.7.3 字符串相关API
一、字符串获取:
返回字符串的长度:
int length()注意,
String类获取长度是方法,即s.length();而数组的长度为成员,即a.length;获取
index位置(从0开始)的单个字符:char charAt(int index)查找参数字符串
str在本字符串当中首次出现的索引位置,若找不到则返回-1:int indexOf(String str)1
2char ch = "Hello".charAt(1); //e
int idx = "HelloHelloHelloHello".indexOf("llo"); //2
二、字符串截取:
String substring(int index)截取从
index位置(包括index)一直到字符串末尾的子串并将该子串返回。String substring(int begin, int end)从
begin位置开始,到达不想复制的第一个位置end,即[begin, end)。显然,s.substring(a, b)的长度即为。1
2
3String cur = "MonkeyDLuffy";
System.out.println(cur.substring(6)); //DLuffy
System.out.println(cur.substring(3, 6)); //key
三、字符串的拼接
Java语言允许使用+号拼接两个字符串。
1 | |
当将一个字符串与一个非字符串的值进行拼接时,后者被转换成字符串。(任何一个Java对象都可以转换成字符串)
四、字符串转换:
将当前字符串拆分为字符数组并作为返回值:
char[] toCharArray获得当前字符串底层的字节数组(IO流会使用):
byte[] getBytes()将所有出现的目标字符串
target替换为新的字符串,返回替换之后的结果新字符串:String replace(CharSequence target, CharSequence replacement)1
2
3
4char[] c = "Hello".toCharArray();
byte[] b = "Hello".getBytes();
String str1 = "How do you do?";
String str2 = str1.replace("o", "*"); //H*w d* y*u d*?
五、字符串的分割:
根据字符串
regex,将当前字符串切分成若干子串,并返回由这些子串组成的字符串数组:String[] split(String regex)1
2
3
4
5
6
7
8
9String text = "not to be";
String[] words = text.split(" ");
for(int i = 0; i < words.length; i++)
System.out.print(words[i]+" ");
/*
not
to
be
*/注意:split方法的参数为正则表达式,若要按照字符’
.'进行切分,必须写\\.
¶4.7.4 字符串转换为基本类型 与 包装类
除了Character类之外,其他所有包装类都具有parseXxx静态方法可以将字符串参数转换为对应的基本类型:
public static byte parseByte(String s):将字符串参数转换为对应的byte基本类型。public static short parseShort(String s):将字符串参数转换为对应的short基本类型。public static int parseInt(String s):将字符串参数转换为对应的int基本类型。public static long parseLong(String s):将字符串参数转换为对应的long基本类型。public static float parseFloat(String s):将字符串参数转换为对应的float基本类型。public static double parseDouble(String s):将字符串参数转换为对应的double基本类型。public static boolean parseBoolean(String s):将字符串参数转换为对应的boolean基本类型。若字符串参数内容无法正确地转换为对应的基本类型,则会抛出
java.lang.NumberFormatException异常。
¶4.8 StringBuilder 类
由于String类的对象内容不可改变,每当进行字符串拼接时,总是需要在内存中创建一个新对象,例如:
1 | |
如果要进行大量次拼接操作时,需要创建大量新的String对象,耗时且空间开销大,为解决此问题,可使用java.lang.StringBuilder类。
StringBuilder类为可变字符序列,它类似于String的字符串缓冲区,内部拥有一个数组用于存放字符串内容。当进行字符串拼接时,直接在该数组中加入新内容,同时StringBuilder本身也会自动维护数组的扩容。
常用方法有:
public StringBuilder append(...):添加任意类型数据的字符串形式,并返回当前对象自身(源码中就是返回this)。public String toString():将当前StringBuilder对象转换为不可变的String对象,并将该String对象进行返回。1
2
3
4
5
6
7public class JustTest {
public static void main(String[] args) {
StringBuilder curstr = new StringBuilder("Hello ").append("World").append("!");
String str = curstr.toString();
System.out.println(str);
}
}StringBuilder已经覆写了Object类的toString方法。
¶4.9 大数值类
java.math包中有两个有用的类,可以处理包含任意长度数字序列的数值。
BigInteger:实现任意精度的整数运算。BigDecimal:实现任意精度的浮点数运算。
由于Java没有提供运算符重载的功能,无法重定义
+和*运算符,所以BigInteger类运算时需用其add和multiply。
1 | |
¶4.9.1大数值相关API
返回该大整数与另一大整数other的和、差、积、商及余数:
BigInteger add(BigInteger other)BigInteger substact(BigInteger other)BigInteger multiply(BigInteger other)BigInteger divide(BigInteger other)BigInteger mod(BigInteger other)
返回值等于x的大整数:
static BigInteger valueOf(long x)
若该大整数与另一个大整数other相等,返回0;若小于other,返回负数;否则,返回正数:
int compareTo(BigInteger other)
¶4.10 数学工具类Math
- 获取绝对值,有多种重载:
public static double abs(double num); - 向上取整:
public static double ceil(double num); - 向下取整:
public static double floor(double num); - 四舍五入,返回
long型:public static long round(double num);
¶4.11 Object类
java.lang.Object类是Java中所有类的最终祖先,即在Java中每个类(包括数组类型)都是由它拓展而来的。
若一个类没有特别指定父类,那么默认继承自Object类,如:
1 | |
¶4.11.1 toString 方法
public String toString():返回该对象的字符串表示,在Object类中该方法输出为:对象类型@内存地址值。
当我们直接使用输出语句输出对象名时,其实通过该对象调用了其
toString()方法。
然而在开发中需要根据对象属性得到相应的字符串表现形式,接下来便需要对该方法进行覆写。(以自定义的 Person 类)一般打印格式为:类的名字,随后是一对括号括起来的域值。
1 | |
¶4.11.2 equals 方法
public boolean equals(Object obj):检测一个对象是否等于另一对象,在Object类中该方法判断两个对象是否具有相同的引用。(相当于==运算符的运算结果)
然而,对于大多数类中,更经常地需要检测两个对象状态的相等性,比如所有成员变量相同就判定两个对象相同。因而,可以如下覆写:
1 | |
TIPS:IDEA中的“代码”(Code)菜单——“生成”(Generate)可以快速生成上面的
toString方法和equals方法的覆写。
¶4.11.3 Objects 工具类
JDK7添加Objects工具类(注意,不是Object类),它由一些静态的实用方法组成,分为null-save(空指针安全)和null-tolerant(容忍空指针),用于计算对象的hashcode、返回对象的字符串表现形式、比较两个对象。
public static boolean equals(Object a, Object b):判断两个对象的内容是否相等。1
2
3public static boolean equals(Object a, Object b){
return (a == b) || (a != null && a.equals(b));
}public static <T> T requireNonNull(T obj):判断传入的引用对象是否为空。1
2
3
4public static void method(Object obj){
//Objects.requireNonNull(obj);
Objects.requireNonNull(obj, "传递的对象为null!");
} //对传递过来的参数进行合法性判断,判断是否为null
¶4.12 日期时间类
¶4.12.1 Date 类
java.util.Date类 的实例有一个状态,即特定的时间点。这个时间 是 用距离一个固定时间点的毫秒数(可正可负),而这个固定时间点为纪元(epoch)——UTC 时间 1971 年 1 月 1 日 00 : 00 : 00 。
由于我们身处东八区,则基准时间为1970年1月1日8时0分0秒
用类描述时间的好处在于,若类的设计不够完善,则可以编写自己的类以便增强或替代系统提供的类
构造方法:
public Date():分配Date对象并初始化此对象,以表示分配它的时间(精确到毫秒),自动设置当前系统时间的毫秒时刻;public Date(long date):分配Date对象并初始化此对象以表示自从纪元以来的指定毫秒数。1
2
3
4
5
6
7
8
9import java.util.Date;
public class Hello {
public static void main(String[] args) {
System.out.println(new Date());
//Thu Oct 29 21:03:14 CST 2020
System.out.println(new Date(0L)); //将毫秒值转成日期对象
//Thu Jan 01 08:00:00 CST 1970
}
}
¶4.12.2 DateFormat 类
java.text.DateFormat 为日期/时间格式化子类的抽象类,通过该类可以实现日期与文本间的转换(即Date对象与String对象间转换)
- 格式化:按指定格式,Date对象 -> String对象。
- 解析:按指定格式,String对象 -> Date对象。
一、构造方法
由于DateFormat为抽象类,需要常用的子类java.text.SimpleDateFormat(需要一个模式/格式来指定格式化或解析的标准),构造方法为:
public SimpleDateFormat(String pattern):用给定模式和默认语言环境的日期格式符号构造SimpleDateFormat。其中pattern为 代表日期时间的自定义格式 的字符串。格式规则
标识字母(区分大小写) 含义 y 年 M 月 d 日 H 时 m 分 s 秒
1 | |
二、常用方法
public String format(Date date):将Date对象格式化为字符串;1
2
3
4
5
6
7
8
9
10
11import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Hello {
public static void main(String[] args) {
Date date = new Date();
DateFormat df = new SimpleDateFormat("yyyy年MM月dd日"); //创建日期格式化对象,指定风格
String str = df.format(date);
System.out.println(str); //2020年10月29日
}
}public Date parse(String source):将字符串解析为Date对象;注意,该方法需要对异常进行处理!
1
2
3
4
5
6
7
8
9
10
11
12import java.text.DateFormat;
import java.text.ParseException; //导包
import java.text.SimpleDateFormat;
import java.util.Date;
public class Hello {
public static void main(String[] args) throws ParseException { //异常处理
DateFormat df = new SimpleDateFormat("yyyy年MM月dd日"); //创建日期格式化对象,指定风格
String str = "2001年1月7日";
Date bir = df.parse(str);
System.out.println(bir); //2020年10月29日
}
}public long getTime():将日期对象转换成对应的时间毫秒值。(可能已过时,但在计算某些时间差值时比较有用)
计算一个人从出生到此刻的天数:
1 | |
¶4.13 Calendar 类
java.util.Calendar为日历类,该类将所有可能用到的时间信息封装为静态成员变量以便获取。
Calendar类中的方法取代了许多Date的方法。
一、创建对象
由于Calendar类为抽象类,它不能够直接创建,而是通过静态方法返回一个子类对象来进行创建(多态),该静态方法为:
public static Calendar getInstance():使用默认时区与语言环境获得一个 日历 。1
Calendar cal = Calendar.getInstance();
二、常用方法
Calendar类中提供很多有关日历的成员常量,它们各自代表不同的日历字段,同时也对应于Calendar相关方法中的传入参数field。
| 字段值 | 含义 |
|---|---|
| YEAR | 年 |
| MONTH | 月(从0开始,可以+1使用) |
| DAY_OF_MONTH | 月中的天(几号) |
| HOUR | 时(12小时制) |
| HOUR_OF_DAY | 时(24小时制) |
| MINUTE | 分 |
| SECOND | 秒 |
| DAY_OF_WEEK | 周中的天(周几,周日为1,可以-1使用) |
Calendar.YEAR存的值为3,并不代表它就是记录月份,而是用于方法中识别的。其他成员常量也同理。
西方星期开始为周日,月份表示为。
根据Calendar类的API文档,常用方法有:
public int get(int field):给定日历字段field,让其返回该字段含义的值。1
2
3Calendar cal = Calendar.getInstance();
int curyear = cal.get(Calendar.YEAR);
//我传入一个参数Calendar.YEAR,方法get()就会知道我要查询当前年份的值public void set(int field, int value):给定日历字段field,要其字段对应含义的值修改为value。1
2Calendar cal = Calendar.getInstance();
cal.set(Calendar.YEAR, 2020);public abstract void add(int field, int amount):根据日历规则,为给定的日历字段添加或减去指定的时间量amount。若amount为负数,则说明减去偏移量;反之,为加。1
2
3
4
5
6Calendar cal = Calendar.getInstance(); //2020年10月30日
cal.add(Calendar.DAY_OF_MONTH, 2); //加2天
cal.add(Calendar.MONTH, -3); //减三个月
int mon = cal.get(Calendar.MONTH);
int day = cal.get(Calendar.DAY_OF_MONTH);
System.out.println(mon+"月"+day+"日"); //7月1日public Date getTime():返回一个表示此Calendar时间值(从 纪元 到现在的毫秒数)的Date对象。(不同于Date类的getTime()方法!)1
2Calendar cal = Calendar.getInstance();
Date date = cal.getTime();//Fri Oct 30 00:40:00 CST 2020
¶4.14 System 类
java.lang.System 类中提供大量静态方法,可获取与系统相关的信息或系统级操作。常用方法有:
public static long currentTimeMillis():获取当前系统时间与 1970 年 01 月 01 日 00:00 点之间的毫秒差值1
2
3
4
5
6
7
8
9public class JustTest {
public static void main(String[] args) {
long st = currentTimeMillis();
for(int i = 0; i < 1000000000; i++){}
long ed = currentTimeMillis();
long diff = ed - st;
System.out.println(diff); //4ms.........
}
}public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length):将数组中指定的数据拷贝到另一个数组中。