一、Object类
1、Java中所有的类都会直接或者间接的继承自Object
如果一个类没有使用extends关键字继承其他类,那么这个类就继承了Object类
public class Person {
//给出属性
private String name;
private int age;
/*
@Override
public String toString() {
return name + "--" + age;
}
*/
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
2、equals方法的内部原理以及比较属性值
如果使用==比较的是引用类型,那么比较的是地址值
在Object中,有一个方法叫做equals,可以比较两个对象的内容是否相同
当通过一个对象调用equals方法,会先看一下自己有没有这个方法,如果没有,那么就会向上找父 类,一直到Object
在Object中的equals,是使用==比较的地址值。
如果想要使用equals方法比较对象的内容是否相同,那么我们可以在子类中对equals方法进行重写
public class Demo03Equals {
public static void main(String[] args) {
//创建三个Person对象
Person p1 = new Person("王宝强", 28);
Person p2 = new Person("贾乃亮", 25);
Person p3 = new Person("贾乃亮", 25);
//使用==比较这些对象
System.out.println(p1 == p2);// false
System.out.println(p2 == p3);// false
System.out.println("==============================");
System.out.println(p1.equals(p2)); //false
System.out.println(p2.equals(p3)); //true
}
}
3、equals方法的重写
重写equals,比较对象的属性,如果两个对象的属性完全相同,那么我们就把这两个对象看成是相 同的对象
两个对象分别是this和obj
@Override
public boolean equals(Object obj) {
//为了程序的健壮性进行非空判断
if(obj == null) {
return false;
}
//判断参数Object是否属于人,如果不属于人,那么就直接返回false。
if(!(obj instanceof Person)) {
return false;
}
//比较两个对象的属性是否完全相同
Person p = (Person)obj;
return this.name.equals(p.name) && this.age == p.age;
}
*/
//使用alt + insert 生成equals方法
重写equals方法:
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return age == person.age &&
Objects.equals(name, person.name);
}
4、Objects工具类
在jdk7之后,有了Objects工具类,他是用于操作对象的工具类。
static boolean equals(Object a, Object b):比较两个对象是否相同。
Objects中的equals方法, 内部会调用Object中的equals,所以,如果想要根据两个对象的属性进行比较。那么还需要在子类中重写Object中的equals方法。
public class Demo04ObjectsEquals {
public static void main(String[] args) {
//创建两个Teacher对象
Teacher t1 = new Teacher("小苍老师", 35);
Teacher t2 = new Teacher("小苍老师", 35);
//通过Objects工具类的equals方法,比较这两个对象是否相同。
//如果这两个对象的属性完全相同,那么我们就把这两个对象看成是相同的对象.
System.out.println(Objects.equals(t1, t2)); //true
//Objects中的equals和Object中的equals不同点
Teacher t3 = null;
Teacher t4 = null;
//System.out.println(t3.equals(t4));//NullPointerException 通过null调用任何方法或者属性引发空指针异常
System.out.println(Objects.equals(t3, t4)); //true
}
}
二、Date类
1、在java中,有一个类可以表示精确的时间瞬间,这个类叫做java.util.Date
Date这个单词的意思是日期, 但是在java中表示的是特定的时间瞬间,精确到了毫秒。
构造方法:
Date(): 以当前操作系统的时间点构造一个Date对象。
Date(long date): 需要传递一个long类型的毫秒值,表示从1970年1月1日 0时0分0秒 这个时间点过了多少毫秒。
中国用的是北京时间,北京时间是东八区的时间,比标准的时间要快八个小时。
所以中国的时间是从 1970年1月1日 8时0分0秒 开始的.
public class Demo01Date {
public static void main(String[] args) {
//使用空参构造创建Date对象
Date dateOne = new Date();
System.out.println(dateOne);
//使用有参构造创建Date对象并打印结果
Date dateTwo = new Date(0L);
System.out.println(dateTwo);
//创建一个Date对象,表示的时间为 1970年1月2日...
Date dateThree = new Date(1000 * 60 * 60 * 24);
System.out.println(dateThree);
}
}
2、Date 类中常见的方法
(1)long getTime(): 获取这个Date对象对应的毫秒值(从1970年1月1日 0时0分0秒开始过了多少毫秒)
public class Demo02DateMethod {
public static void main(String[] args) {
//创建一个Date对象
Date date = new Date(); //以当前操作系统的时间点构造一个Date对象
System.out.println(date.getTime()); //1535334864770
}
}
(2)void setTime(long time):设置一个毫秒值
public class Demo03DateMethod {
public static void main(String[] args) {
//创建一个Date对象
Date date = new Date();
System.out.println("date:" + date);
//给这个date对象重新设置时间
date.setTime(0L); //调用setTime方法之后,这个date对象所表示的时间就发生了改变
System.out.println("date:" + date);
}
}
3、SimpleDateFormat构造方法:
如果希望把Date对象转成我们自己喜欢的字符串,可以使用DateFormat这个类对Date对象进行格式化。
DateFormat是一个抽象类,如果要用,需要使用它的子类SimpleDateFormat
SimpleDateFormat构造方法:
SimpleDateFormat(String pattern): 根据指定的模式构造一个SimpleDateFormat对象。
模式就是将来要转换的格式,比如:
要转换的日期: 2018年08月27日 10时02分23秒
指定的模式为: yyyy年MM月dd日 HH时mm分ss秒
要使用指定的字母代替掉动态的数字。
年:y
月:M
日:d
时:H
分:m
秒:s
(1)其他方法:
String format(Date date): 将指定的Date对象按照指定的模式转成一个字符串.
使用步骤:
1. 创建一个Date对象
2. 创建SimpleDateFormat对象,指定一个模式。
3. 调用SimpleDateFormat的format方法,将Date对象转成String。
public class Demo04DateFormat {
public static void main(String[] args) {
//创建一个Date对象
Date date = new Date();
//创建一个SimpleDateFormat对象,指定一个模式。
//想要把日期转成 2018年08月27日 10时02分23秒 这种格式
//SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒");
//想要把日期转成 2018-08-27- 10:02:23 这种格式
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//调用SimpleDateFormat的format方法,将Date对象转成String。
String str = sdf.format(date);
System.out.println(str);
}
}
4、时间和字符串之间的转换
如果想要将一个字符串转成Date对象,那么也可以使用SimpleDateFormat。此时使用的方法叫做parse
Date parse(String source): 将指定个字符串转成一个Date对象。
使用步骤:
1. 创建字符串
2. 创建一个SimpleDateFormat对象,指定一个模式。
3. 调用SimpleDateFormat的parse,传递字符串,将这个字符串转成Date对象。
注意:
字符串中日期的格式必须和SimpleDateFormat中的模式一致,否则会出错
当调用parse方法的时候,需要抛出异常(后面说),
操作方式:把光标放到红线上面,然后按alt + 回车,然后选择第一个
总结:
Date -> String: format方法。 格式化
String -> Date: parse方法。 解析.
public class Demo05DateFormat {
public static void main(String[] args) throws ParseException {
//创建字符串
String str = "2018-08-27 10:14:06";
//创建一个SimpleDateFormat对象,指定一个模式。
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//调用SimpleDateFormat的parse进行转换
Date date = sdf.parse(str);
System.out.println(date);
}
}
5、案例:键盘录入一个出生日期,计算这个人到现在活了多少天?
思路:
1. 键盘录入一个字符串类型的时间,求出这个时间对应的毫秒值。
a. 使用Scanner键盘录入一个字符串
b. 使用SimpleDateFormat,将这个字符串转成一个Date对象。
c. 使用Date对象的getTime方法,获取到这个Date对象对应的毫秒值
2. 求出现在时间对应的毫秒值
a. 使用空参构造创建一个Date对象。
b. 调用getTime方法获取对应的毫秒值
3. 相减。
public class Demo06DateTest {
public static void main(String[] args) throws ParseException {
//键盘录入一个字符串类型的时间,求出这个时间对应的毫秒值。
//使用Scanner键盘录入一个字符串
Scanner sc = new Scanner(System.in);
System.out.println("请您键盘录入一个出生日期,格式为:yyyy-MM-dd");
String bornStr = sc.nextLine();
//使用SimpleDateFormat,将这个字符串转成一个Date对象。
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date born = sdf.parse(bornStr);
//使用Date对象的getTime方法,获取到这个Date对象对应的毫秒值
long bornMillis = born.getTime();
//求出现在时间对应的毫秒值
//使用空参构造创建一个Date对象。
Date now = new Date();
//调用getTime方法获取对应的毫秒值
long nowMillis = now.getTime();
//相减。
long result = nowMillis - bornMillis;
System.out.println(result / 1000 / 60 / 60 / 24);
}
}
三、Calendar日历类
Calendar 英语单词本意是日历的意思,但是这个类在java中也能够表示精确的时间瞬间,精确到毫秒。
Calendar是一个抽象类,如果要用,需要使用它的子类。
注意:
这个子类对象我们用的时候不是我们自己new出来的。而是通过Calendar对象调用静态方法获取到的。
获取Calendar子类对象的方法
static Calendar getInstance(): 根据当前的区域和时区获取一个Calendar子类对象.
和之前的区别:
之前创建对象都是自己new,
现在这个日历类对象不是自己new的,而是调用getInstance方法获取到的。
public class Demo01Calendar {
public static void main(String[] args) {
//调用Calendar 的getInstance方法获取一个日历对象
Calendar c = Calendar.getInstance();
//打印
System.out.println(c);
}
}
1、 Calendar中常见的方法:
public int get(int field): 获取一个指定字段的值。
get(年):获取的就是年的值
get(月):获取的就是月的值
get(日):获取的就是日的值
因为get方法所需要的参数是int类型,所以需要使用int数字来代替年月日
1表示的就是年, 2表示的是月。
如果每次调用get方法都传递数字,那么这样会大大的增加开发成本,并且会影响阅读性。
在Calendar中提供了很多常量,这些常量每一个都表示一个数字,并且这些常量的名字可以起到见名之意的效果。
所以我们可以使用Calendar中的这些常量来表示这些数字
注意: 在Calendar中月份是从0开始的。范围是0-11
public class Demo02CalendarMethod {
public static void main(String[] args) {
//先获取到一个日历对象
Calendar c = Calendar.getInstance();
int year = c.get(Calendar.YEAR);
System.out.println("year:" + year);//2018
//获取月份
int month = c.get(Calendar.MONTH);
System.out.println("month:" + (month + 1)); //8
//获取日
int day = c.get(Calendar.DAY_OF_MONTH);
System.out.println("day:" + day);
}
}
2、 在Calendar中,有一个方法可以设置指定字段的值,这个方法叫做set
void set(int field, int value):给指定的字段设置值
参数field: 表示给哪个字段设置值。
参数value: 表示设置成什么值。
public class Demo03CalendarMethod {
public static void main(String[] args) {
//获取一个Calendar对象
Calendar c = Calendar.getInstance();
//打印这个日历对象的年月日信息
System.out.println(c.get(Calendar.YEAR) + "-" + (c.get(Calendar.MONTH) + 1) + "-" + c.get(Calendar.DAY_OF_MONTH));
//重写给这个Calendar对象设置年月日信息
c.set(Calendar.YEAR, 1999);
c.set(Calendar.MONTH, 7); //Calendar中的月份比现实中要少1,所以7表示的就是现实中的8月
c.set(Calendar.DAY_OF_MONTH, 5);
//重写打印结果
System.out.println(c.get(Calendar.YEAR) + "-" + (c.get(Calendar.MONTH) + 1) + "-" + c.get(Calendar.DAY_OF_MONTH));
}
}
3、在Calendar中,有一个方法,可以对指定字段的值进行计算。这个方法叫做add
void add(int field, int amount): 对指定的字段进行计算
参数field:表示要对哪个字段进行计算
参数amount: 表示如何计算,如果这个参数是正数,就表示加上指定的值。
如果这个参数是负数,就表示减去指定的值
public class Demo04CalendarMethod {
public static void main(String[] args) {
//获取一个Calendar对象
Calendar c = Calendar.getInstance();
//打印这个Calendar对象的年月日信息
System.out.println(c.get(Calendar.YEAR) + "-" + (c.get(Calendar.MONTH) + 1) + "-" + c.get(Calendar.DAY_OF_MONTH));
//对年这个字段进行计算, 加上2年
//c.add(Calendar.YEAR, 2);
//对月这个字段进行计算
c.add(Calendar.MONTH, 5);
System.out.println(c.get(Calendar.YEAR) + "-" + (c.get(Calendar.MONTH) + 1) + "-" + c.get(Calendar.DAY_OF_MONTH));
}
}
4、在Calendar中有一个方法,可以获取到对应的Date对象。这个方法叫做getTime
Date getTime(): 获取Calendar对应的Date对象
public class Demo05CalendarMethod {
public static void main(String[] args) {
//获取一个Calendar对象
Calendar c = Calendar.getInstance();
//将这个Calendar转成一个Date对象
Date date = c.getTime();
System.out.println("date:" + date);
}
}
四、System表示系统类
在java中。System表示系统类,里面有很多系统相关或者系统级别操作的方法。
static long currentTimeMillis(): 获取当前操作系统的时间(从1970年1月1日 0点0分0秒 到操作系统的时间过了多少毫秒)
static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length): 复制数组。
public class Demo01System {
public static void main(String[] args) {
//获取当前操作系统对应的毫秒值
long millis = System.currentTimeMillis();
System.out.println(millis);
}
}
(1)案例:验证打印1-9999之间的所有数字使用多少毫秒
public class Demo02SystemTest {
public static void main(String[] args) {
//打印操作之前记录一下时间
long start = System.currentTimeMillis();
//进行打印操作
for(int i = 1; i < 10000; i++) {
System.out.println(i);
}
//打印操作之后记录一下时间
long end = System.currentTimeMillis();
//相减
System.out.println(end - start);
}
}
2、在System中有一个方法,可以对数组进行复制,这个方法叫做arraycopy
static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length): 复制数组。
参数src: 表示源数组
参数srcPos: 源数组的起始位置。
参数dest: 表示目标数组
参数destPos: 表示目标数组的起始位置。
参数length: 复制几个。
public class Demo03System {
public static void main(String[] args) {
//创建两个数组
int[] src = {1,2,3,4,5};
int[] dest = {6,7,8,9,10};
//将src数组的前三个元素赋值到dest数组的前三个位置
//System.arraycopy(src, 0, dest, 0, 3);
//将src中的元素复制到dest数组中, 从src数组中的索引为1的位置开始,复制2个。复制到dest索引为2的元素上(从索引为2的位置开始放)
System.arraycopy(src, 1, dest, 2, 2);
//打印两个数组
System.out.println(Arrays.toString(src));
System.out.println(Arrays.toString(dest));// 6 7 2 3 10
}
}
五、StringBuilder类
1、概念:
因为String不可改变,所以每次对字符串进行拼接都会产生新的字符串。
这样的话既耗时又浪费空间, 于是说就有了StringBuilder,它是一个可以改变的字符序列(可变的字符串),如果使用StringBuilder进行拼接,会大大的提高性能.
public class Demo01String {
public static void main(String[] args) {
//创建一个字符串
String s = "hello";
s += "world";
System.out.println(s);
}
}
2、StringBuilder中的构造方法
StringBuilder是一个可变的字符序列。 本质是一个数组。
在jdk9之前,是char数组
在jdk9及之后的版本,是byte数组。
StringBuilder和String本质是一样的,都是数组,只不过String不可以变,StringBuilder可以改变。
StringBuilder的构造方法:
StringBuilder(): 空参构造方法。使用空参构造方法创建的对象里面没有内容
StringBuilder(String str): 根据指定的字符串构造一个StringBuilder对象
public class Demo02StringBuilder {
public static void main(String[] args) {
//使用空参构造创建一个StringBuilder对象
StringBuilder sbOne = new StringBuilder();
System.out.println("sbOne:" + sbOne);
//使用有参构造创建一个StringBuilder对象
StringBuilder sbTwo = new StringBuilder("你好");
System.out.println("sbTwo:" + sbTwo); //你好
}
}
3、StringBuilder中的常见方法:
StringBuilder append(任意类型): 将任意类型的数据拼接(追加,添加)到StringBuilder对象的后 面。返回值为调用者对象本身
String toString():将StringBuilder对象转成一个字符串
public class Demo03StringBuilder {
public static void main(String[] args) {
//创建一个StringBuilder对象
StringBuilder sb = new StringBuilder();
//调用append方法,进行拼接
//StringBuilder newSb = sb.append("你好");
//System.out.println("sb:" + sb); //你好
//System.out.println("newSb:" + newSb); //你好
//向sb对象上面添加各种类型的数据
/*
sb.append("你好");
sb.append(10);
sb.append(3.14);
sb.append(false);
sb.append('a');
*/
//新的写法,链式编程
sb.append("你好").append(10).append(3.14).append(false);
System.out.println("sb:" + sb);
//toString方法,可以将StringBuilder对象转成一个String
String str = sb.toString();
System.out.println("str:" + str);
}
}
六、包装类、自动拆装箱
1、每一种基本类型都有其所对应的引用类型(包装类)
基本类型 引用类型
byte Byte
short Short
int Integer(特殊)
long Long
float Float
double Double
char Character(特殊)
boolean Boolean
基本类型和他对应的包装类用法是一样的。
基本类型其实就是一个简单的数字,仅仅能够进行运算或者直接使用,不能调用方法。
而引用类型是可以创建对象的,所以基本类型对应的保证类对象是可以调用方法的,这样的话包装类功能要更加强大。
基本类型能做的其实包装类也都可以做。
在jdk5之后,多了一个新特性,叫做自动拆装箱。
拆箱: 引用类型转成对应的基本类型。
装箱: 基本类型转成对应的引用类型。
public class Demo01Warp {
public static void main(String[] args) {
//装箱, 把int类型的10自动转成了Integer类型
Integer a = 10;
//装箱, 把int类型的20自动转成了Integer类型
Integer b = 20;
//因为要进行数学运算,所以会先把Integer类型的a和b转成int类型,然后去运算。运算出来的结果是int类型。
//把int类型的结果赋值给了Integer类型,于是就发生了自动装箱的效果.
Integer sum = a + b;
System.out.println(sum);
}
}
2、手动拆装箱
在jdk5之前,需要手动拆装箱。
手动装箱(int -> Integer)
Integer Integer.valueOf(int num): 可以把int数字转成Integer类型
手动拆箱(Integer -> int)
直接调用Integer对象的intValue方法即可
public class Demo02Warp {
public static void main(String[] args) {
//将基本类型的10转成包装类
int basicNumber = 10;
Integer warpNumber = Integer.valueOf(basicNumber);
//System.out.println(warpNumber);
//把包装类对象10转回int类型
int num = warpNumber.intValue();
System.out.println(num);
}
}
3、基本类型和字符串的相互转换:
基本类型 -> 转字符串
1. 直接在这个基本类型的数据后面加上 "" (推荐)
2. 使用String的静态方法valueOf
3. 可以使用对应包装类的toString方法
字符串 -> 基本类型
除了Character中,每一个包装类都有一个parseXXX的方法,可以将字符串转成对应的基本类型。
如果想要把字符串转成int数字,就调用Integer里面的parseInt方法
如果想要把字符串转成long数字,就调用Long里面的parseLong方法。
如果想要把字符串转成double数字,就调用Double里面的parseDouble方法。
注意:如果要把字符串转成数字,那么必须保证这个字符串中是一个合法的数字才可以
public class Demo03Parse {
public static void main(String[] args) {
//基本类型转字符串
int num = 3;
String strNum = num + "";
//String strNum = String.valueOf(num);
//String strNum = Integer.valueOf(num).toString();
System.out.println(strNum);
System.out.println("====================");
//把字符串转成基本类型的数字
String str = "123";
int number = Integer.parseInt(str);
System.out.println(number); //123
}
}