Java基础|1-07-Object类与常见API(二)@API篇

写在前面:
此系列文是笔者在学习Java系列课程的过程中,参考相关课件、视频讲解、课程代码,并结合一些文档、思维导图及个人理解,对所学内容做的阶段性梳理与总结。

  • 写于:2021年1月28日
  • 内容:Java后端系列笔记007(Java基础-Object类、常见API)
  • 全文:12819字;读完需要:20分钟


一、Object类

1.1 概述 [ 导图 ]

  • 如果一个类没有特别指定父类,那么默认则继承自Object类。例如:
public class MyClass /*extends Object*/ {
   
  	// ...
}

1.2 toString方法

方法摘要

public String toString():返回该对象的字符串表示

  • 其实该字符串内容就是:类名+@+内存地址值
    • 如:com.sj.demo01.Object.Person@16e8e0a
  • 具体值等于: getClass().getName() + '@' + Integer.toHexString(hashCode())
    • getClass().getName():代表返回对象所属名的类名,如:Person
    • hashCode():代表返回该对象的哈希值
      • 该方法将对象的内存地址进行哈希运算,返回一个int类型的哈希值
    • Integer.toHexString(hashCode()):代表将对象的哈希值用十六进制表示

覆盖重写

  • 直接打印对象的地址值没有意义,需要重写Object类中的toString方法(建议所有子类都重写此方法)
// 示例:自定义的Person类
public class Person {
     
    private String name;
    private int age;
	
    @Override    
    //重写方法,打印对象的属性(name,age)
    public String toString() {
   
        return "Person{" + "name='" + name + '\'' + ", age=" + age + '}';
    }

    // 省略构造器与Getter Setter
}
  • 在IntelliJ IDEA中,toString方法的自动重写:快捷键alt+insert → 点击toString() → 选择需要包含的成员变量 → OK

  • 看一个类是否重写了toString,直接打印这个类的对象即可。如果没有重写toString方法,那么打印的是对象的地址值

小贴士: 在我们直接使用输出语句输出对象名的时候,其实就是调用对象的toString()方法

1.3 equals方法

方法摘要

public boolean equals(Object obj):指示其他某个对象是否与此对象“相等”(这里的“相等”有默认和自定义两种方式)

//equals方法源码
public boolean equals(Object obj) {
   
    return (this == obj);
}
  • 参数Object obj:可以传递任意的对象
  • == 比较运算符,返回的是一个布尔值 true false
    • 基本数据类型:比较的是值
    • 引用数据类型:比较的是两个对象的地址值
  • this是谁?哪个对象调用的方法,方法中的this就是那个对象
  • obj是谁?传递过来的参数

默认地址比较

  • Object类的equals方法,默认“==”运算符,比较的是两个对象的地址值
  • 只要不是同一个对象,结果必然为false

对象内容比较

  • 如果希望进行对象的内容比较,需重写equals方法,比较两个对象的属性(name,age)
  • 问题:隐含着一个多态
    • 多态的弊端:无法使用子类特有的内容(属性和方法)
    • Object obj = p2 = new Person(“小白”,19);
  • 解决:可以使用向下转型(强转)把obj类型转换为Person
import java.util.Objects;

public class Person {
   	
	private String name;
	private int age;
	
    @Override
    public boolean equals(Object o) {
   
        // 如果对象地址一样,则认为相同,提高程序的效率
        if (this == o)
            return true;
        // 如果参数为空,或者类型信息不一样,则认为不同
        /* getClass() != o.getClass() 使用反射技术,判断o是否是Person类型(等效于 obj instanceof Person); 增加类型判断,可防止类型转换异常ClassCastException */
        if (o == null || getClass() != o.getClass())
            return false;
        //使用向下转型,把obj转换为Person类型
        Person person = (Person) o;
        // 要求基本类型相等,并且将引用类型交给java.util.Objects类的equals静态方法取用结果
        return age == person.age && Objects.equals(name, person.name);
    }

	/* (了解即可) 当equals方法被重写时,通常有必要重写 hashCode 方法, 以维护 hashCode 方法的常规协定,该协定声明相等对象必须具有相等的哈希码 */
	@Override
    public int hashCode() {
   
        return Objects.hash(name, age);
    }
}
  • 在IntelliJ IDEA中,自动生成equals方法:快捷键alt+insert → 选择equals() and hashCode()

equals 和 == 的区别

1.4 Objects类

Objects类的equals方法

  • 在比较两个对象的时候,Object的equals方法容易抛出空指针异常NullPointerException,示例:
public class Demo01Object {
   
	public static void main(String[] args) {
   
        String s1 = null;
        String s2 = "abc";
        // null是不能调用方法的,会抛出空指针异常
        boolean b = s1.equals(s2); // NullPointerException 
        System.out.println(b);
	}
}
  • Objects类中的equals方法优化了这个问题:对两个对象进行比较,防止空指针异常,源码:
//源码
public static boolean equals(Object a, Object b) {
   
   return (a == b) || (a != null && a.equals(b));
}
  • Objects中equals的使用,示例:
import java.util.Objects;

public class Demo02Objects {
   
	public static void main(String[] args) {
   
	    String s1 = null;
	    String s2 = "abc";
	    boolean b2 = Objects.equals(s1, s2);
	    System.out.println(b2);// false
	}
}

Objects类是什么

java.util.Objects类:

  • JDK7添加了一个Objects工具类,它提供了一些方法来操作对象,它由一些静态的实用方法组成
  • 这些方法是null-save(空指针安全的)或null-tolerant(容忍空指针的),用于计算对象的hashcode、返回对象的字符串表示形式、比较两个对象

二、日期时间类

2.1 Date类

  • 代码演示:
import java.util.Date;

public class Demo01Date {
   
    public static void main(String[] args) {
   
        /* Date类的空参数构造方法 Date() 获取当前系统的日期和时间 */
        System.out.println(new Date()); //Thu Jan 28 14:45:41 CST 2021
        
        /* Date类的带参数构造方法 Date(long date) :传递毫秒值,把毫秒值转换为Date日期对象 */
        System.out.println(new Date(0L)); // Thu Jan 01 08:00:00 CST 1970

	    /* long getTime() 把日期转换为毫秒值(相当于System.currentTimeMillis()方法) 返回自 1970 年 1 月 1 日 00:00:00 GMT 以来,此 Date 对象表示的毫秒数 */
        Date date = new Date(); //创建日期对象
        long time = date.getTime();
        System.out.println(time);//1611816684812
    }
}

小贴士

  1. 中国属于东八区,会把时间增加8个小时,所以我们的基准时间为:1970年1月1日8时0分0秒
  2. 在使用println方法时,会自动调用Date类中的toString方法。
    Date类对Object类中的toString方法进行了覆盖重写,所以结果为指定格式的字符串。

2.2 DateFormat类

  • 分别使用format、parse方法,代码演示:
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class Demo01DateFormat {
   
    public static void main(String[] args)  throws ParseException  {
   
        demo01();
        demo02();
    }

	/* 使用DateFormat类中的方法【format】, 把日期格式化为文本 (把Date对象转换成String) */
    private static void demo01() {
   
        //1.创建SimpleDateFormat对象,构造方法中传递指定的模式
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒");
        //2.调用SimpleDateFormat对象中的方法format
        //String format(Date date) 按照指定的模式,把Date日期,格式化为符合模式的字符串(文本)
        Date date = new Date();
        String d = sdf.format(date);
        System.out.println(date);//Thu Jan 28 17:10:22 CST 2021
        System.out.println(d);//2021年01月28日 17时10分22秒
    }
    
    /* 使用DateFormat类中的方法【parse】, 把文本解析为日期 (把String转换成Date对象) 注意: public Date parse(String source) throws ParseException parse方法声明了一个异常叫ParseException 如果字符串和构造方法的模式不一样,那么程序就会抛出此异常 调用一个抛出了异常的方法,就必须的处理这个异常,要么throws继续抛出这个异常,要么try catch自己处理 */
    private static void demo02() throws ParseException {
   
        //1.创建SimpleDateFormat对象,构造方法中传递指定的模式
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒");
        //2.调用SimpleDateFormat对象中的方法parse
        //Date parse(String source) 把符合模式的字符串,解析为Date日期
        Date date = sdf.parse("2021年01月21日 15时51分54秒");
        System.out.println(date);// Thu Jan 21 15:51:54 CST 2021
    }
}

2.3 练习

  • 要求:请使用日期时间相关的API,计算出一个人已经出生了多少天
  • 思路:
    • 获取当前时间对应的毫秒值
    • 获取自己出生日期对应的毫秒值
    • 两个时间相减(当前时间– 出生日期)
  • 代码实现:
public static void function() throws Exception {
   
	System.out.println("请输入出生日期 格式 YYYY-MM-dd");
	// 获取出生日期,键盘输入
	String birthdayString = new Scanner(System.in).next();
	// 将字符串日期,转成Date对象
	// 创建SimpleDateFormat对象,写日期模式
	SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
	// 调用方法parse,字符串转成日期对象
	Date birthdayDate = sdf.parse(birthdayString);	
	// 获取今天的日期对象
	Date todayDate = new Date();	
	// 将两个日期转成毫秒值,Date类的方法getTime
	long birthdaySecond = birthdayDate.getTime();
	long todaySecond = todayDate.getTime();
	//使用当前日期的毫秒值-出生日期的毫秒值
	long secone = todaySecond-birthdaySecond;	
	if (secone < 0){
   
		System.out.println("还没出生呢");
	} else {
   
		//把毫秒差值转换为天(s/1000/60/60/24)
		System.out.println(secone/1000/60/60/24);
	}
}

2.4 Calendar类

  • Calendar静态方法的使用:
import java.util.Calendar;

public class Demo01CalendarInit {
   
    public static void main(String[] args) {
   
        Calendar cal = Calendar.getInstance(); //多态
    }    
}
  • Calendar类中提供很多成员常量,代表给定的日历字段:
字段值 含义
YEAR
MONTH 月(从0开始,可以+1使用)
DAY_OF_MONTH 月中的天(几号)
HOUR 时(12小时制)
HOUR_OF_DAY 时(24小时制)
MINUTE
SECOND
DAY_OF_WEEK 周中的天(周几,周日为1,可以-1使用)
  • 常用方法的代码演示:
import java.util.Calendar;
import java.util.Date;

public class Demo02Calendar {
   
    public static void main(String[] args) {
   
        demo04();
    }

    /* public int get(int field):返回给定日历字段的值。 参数:传递指定的日历字段(YEAR,MONTH...) 返回值:日历字段代表的具体的值 */
    private static void demo01() {
   
        // 使用getInstance方法获取Calendar对象
        Calendar c = Calendar.getInstance();
        // 设置年
        int year = c.get(Calendar.YEAR);
        // 设置月(西方的月份0-11 东方:1-12)
        int month = c.get(Calendar.MONTH);
        // 设置日
// int date = c.get(Calendar.DAY_OF_MONTH);
        int date = c.get(Calendar.DATE);
        System.out.print(year + "年" + month + "月" + date + "日");//2021年0月28日
    }

    /* public void set(int field, int value):将给定的日历字段设置为给定值。 参数: int field:传递指定的日历字段(YEAR,MONTH...) int value:给指定字段设置的值 */
    private static void demo02() {
   
        //使用getInstance方法获取Calendar对象
        Calendar c = Calendar.getInstance();

        //设置年为9999
        c.set(Calendar.YEAR,9999);
        //设置月为9月
        c.set(Calendar.MONTH,9);
        //设置日9日
        c.set(Calendar.DATE,9);

        //同时设置年月日,可以使用set的重载方法
        c.set(8888,8,8);

        int year = c.get(Calendar.YEAR);
        int month = c.get(Calendar.MONTH);
        int date = c.get(Calendar.DATE);
        System.out.print(year + "年" + month + "月" + date + "日");//8888年8月8日
    }

    /* public abstract void add(int field, int amount): 根据日历的规则,为给定的日历字段添加或减去指定的时间量。 参数: int field:传递指定的日历字段(YEAR,MONTH...) int amount:增加/减少指定的值 正数:增加 负数:减少 */
    private static void demo03() {
   
        //使用getInstance方法获取Calendar对象
        Calendar c = Calendar.getInstance();
        //把年增加2年
        c.add(Calendar.YEAR,2);
        //把月份减少3个月
        c.add(Calendar.MONTH,-3);

        int year = c.get(Calendar.YEAR);
        int month = c.get(Calendar.MONTH);
        int date = c.get(Calendar.DAY_OF_MONTH);
        System.out.print(year + "年" + month + "月" + date + "日");//2022年9月28日
    }

    /* public Date getTime(): 返回一个表示此Calendar时间值(从历元到现在的毫秒偏移量)的Date对象。 把日历对象,转换为日期对象 */
    private static void demo04() {
   
        //使用getInstance方法获取Calendar对象
        Calendar c = Calendar.getInstance();

        Date date = c.getTime();
        System.out.println(date);//Thu Jan 28 19:46:56 CST 2021
    }
}

小贴士:

​ 西方星期的开始为周日,中国为周一。

​ 在Calendar类中,月份的表示是以0-11代表1-12月。

​ 日期是有大小关系的,时间靠后,时间越大。


三、System类

3.1 currentTimeMillis方法

  • 说明:currentTimeMillis方法实际上是 获取当前系统时间与1970年01月01日00:00点之间的毫秒差值
import java.util.Date;

public class SystemDemo {
   
    public static void main(String[] args) {
   
        //获取当前系统时间到1970 年 1 月 1 日 00:00:00经历了多少毫秒
        System.out.println(System.currentTimeMillis());//1611816867285
    }
}
  • 练习:验证for循环打印数字1-9999所需要使用的时间(毫秒)
public class SystemTest1 {
   
    public static void main(String[] args) {
   
        // 程序执行前,获取一次毫秒值
        long start = System.currentTimeMillis();
        // 执行for循环
        for (int i = 0; i < 10000; i++) {
   
            System.out.println(i);
        }
        // 程序执行后,获取一次毫秒值
        long end = System.currentTimeMillis();
        System.out.println("程序共耗时:"+(end-start)+"毫秒");//程序共耗时:95毫秒
    }
}

3.2 arraycopy方法

  • 练习:将src数组中前3个元素,复制到dest数组的前3个位置上
    • 复制元素前:src数组元素[1,2,3,4,5],dest数组元素[6,7,8,9,10]
    • 复制元素后:src数组元素[1,2,3,4,5],dest数组元素[1,2,3,9,10]
import java.util.Arrays;

public class DemoSystemArrayCopy {
   
    public static void main(String[] args) {
   
        //定义源数组
        int[] src = {
   1,2,3,4,5};
        //定义目标数组
        int[] dest = {
   6,7,8,9,10};
        System.out.println("复制前:"+ Arrays.toString(dest)); //复制前:[6, 7, 8, 9, 10]
        //使用System类中的arraycopy把源数组的前3个元素复制到目标数组的前3个位置上
        System.arraycopy(src,0,dest,0,3);
        System.out.println("复制后:"+ Arrays.toString(dest)); //复制后:[1, 2, 3, 9, 10]
    }
}

四、StringBuilder类

4.1 StringBuilder的原理

  • 由于String类的对象内容不可改变,所以每当进行字符串拼接时,总是会在内存中创建一个新的对象 —— 既耗时,又浪费空间
  • 为了解决这一问题,可以使用java.lang.StringBuilder

java.lang.StringBuilder类:字符串缓冲区,可以提高字符串的效率

4.2 构造方法

  • public StringBuilder():构造一个不带任何字符的字符串生成器,其初始容量为 16 个字符
  • public StringBuilder(String str):构造一个字符串生成器,并初始化为指定的字符串内容
public class Demo01StringBuilder {
   
    public static void main(String[] args) {
   
    	//空参数构造方法
        StringBuilder sb1 = new StringBuilder();
        System.out.println(sb1); // (空白)
        //带字符串的构造方法
        StringBuilder sb2 = new StringBuilder("java");
        System.out.println(sb2); // java
    }
}

4.3 常用方法

  • public StringBuilder append(...):添加任意类型数据的字符串形式,并返回当前对象自身
  • public String toString():将当前StringBuilder对象转换为String对象

append方法

  • append方法具有多种重载形式,可以接收任意类型的参数
  • 任何数据作为参数都会将对应的字符串内容添加到StringBuilder中,如:
public class Demo02StringBuilder {
   
	public static void main(String[] args) {
   
		//创建StringBuilder对象
		StringBuilder builder = new StringBuilder();
		//public StringBuilder append(任意类型):添加数据
		//append方法返回的是this,调用方法的对象builder,this==builder
		StringBuilder builder2 = builder.append("hello");//把builder的地址赋值给了bu2
		//对比一下
		System.out.println("builder:"+builder);//builder:hello
		System.out.println("builder2:"+builder2);//builder2:hello
		System.out.println(builder == builder2); //比较的是地址 true
		
	    // 可以添加 任何类型,且使用append方法无需接收返回值
		builder.append("hello");
		builder.append("world");
		builder.append(true);
		builder.append(100);
		
		// 在我们开发中,会遇到调用一个方法后,返回一个对象的情况。然后使用返回的对象继续调用方法。
        // 这种时候,我们就可以把代码现在一起,如 append方法一样,代码如下
		//【链式编程】
		builder.append("hello").append("world").append(true).append(100);
		System.out.println("builder:"+builder);
	}
}

备注:StringBuilder已经覆盖重写了Object当中的toString方法

toString方法

  • 通过toString方法,StringBuilder对象将会转换为不可变的String对象。如:
public class Demo03StringBuilder {
   
    public static void main(String[] args) {
   
        // 链式创建
        StringBuilder sb = new StringBuilder("Hello").append("World").append("Java");
        // 调用方法
        String str = sb.toString();
        System.out.println(str); // HelloWorldJava
    }
}

StringBuilder和String的相互转换

  • String --> StringBuilder
    • 可以使用StringBuilder的构造方法
    • StringBuilder(String str) :构造一个字符串生成器,并初始化为指定的字符串内容
  • StringBuilder --> String
    • 可以使用StringBuilder中的toString方法
    • public String toString():将当前StringBuilder对象转换为String对象
public class Demo04StringBuilder {
   
    public static void main(String[] args) {
   
        // String --> StringBuilder
        String str = "hello";
        System.out.println("str:"+str);// str:hello
        StringBuilder bu = new StringBuilder(str);
        // 往StringBuilder中添加数据
        bu.append("world");
        System.out.println("bu:"+bu); // bu:helloworld

        // StringBuilder --> String
        String s = bu.toString();
        System.out.println("s:"+s); //s:helloworld
    }
}

五、包装类

5.1 概述

  • 基本类型对应的包装类:
基本类型 对应的包装类(位于java.lang包中)
byte Byte
short Short
int Integer
long Long
float Float
double Double
char Character
boolean Boolean

5.2 装箱与拆箱

装箱 (基本类型的数据 --> 包装类)

  • 概念:把基本类型的数据,包装到包装类中
  • 构造方法:
    • Integer(int value) :构造一个新分配的 Integer 对象,它表示指定的 int 值
    • Integer(String s) :构造一个新分配的 Integer 对象,它表示 String 参数所指示的 int 值
      ★ 传递的字符串,必须是基本类型的字符串,否则会抛出异常(如:“100” 正确 ;“a” 抛异常)
  • 静态方法:
    • static Integer valueOf(int i) :返回一个表示指定的 int 值的 Integer 实例
    • static Integer valueOf(String s) :返回保存指定的 String 的值的 Integer 对象
//使用构造方法
Integer in1 = new Integer(4);
Integer in2 = new Integer("1");

//使用静态方法
//Integer in3 = Integer.valueOf("a");//NumberFormatException数字格式化异常
Integer in4 = Integer.valueOf(4);//使用包装类中的valueOf方法

拆箱 (包装类 --> 基本类型的数据)

  • 概念:在包装类中取出基本类型的数据
  • 成员方法
    • int intValue() :以 int 类型返回该 Integer 的值
int num = in1.intValue();

5.3 自动装箱与自动拆箱

  • 从Java 5(JDK 1.5)开始,基本类型与包装类的装箱、拆箱动作可以自动完成。 例如:
//示例1
Integer i = 4;//自动装箱。相当于Integer i = Integer.valueOf(4);
i = i + 5;//等号右边:将i对象转成基本数值(自动拆箱) i.intValue() + 5;
//加法运算完成后,再次装箱,把基本数值转成对象。

//示例2
ArrayList<Integer> list = new ArrayList<>();
//ArrayList集合无法直接存储整数,可以存储Integer包装类
list.add(1); //-->自动装箱 list.add(new Integer(1));
int a = list.get(0); //-->自动拆箱 list.get(0).intValue();

5.4 基本类型与字符串之间的转换

基本类型 --> 字符串(String)(三种方式)

  • 基本类型的值+"" :最简单的方法(工作中常用) ,如:24+""
  • 包装类的静态方法toString(参数),不是Object类的toString() 重载
    • static String toString(int i):返回一个表示指定整数的 String 对象
  • String类的静态方法valueOf(参数)
    • static String valueOf(int i) :返回 int 参数的字符串表示形式

字符串(String) --> 基本类型

  • 使用包装类的静态方法parseXXX(“字符串”);
    • Integer类: static int parseInt(String s)
    • Double类: static double parseDouble(String s)

代码演示:

public class Demo03Integer {
   
    public static void main(String[] args) {
   
        //基本类型->字符串(String)
        int i1 = 100;
        String s1 = i1+"";
        System.out.println(s1+200);//100200

        String s2 = Integer.toString(100);
        System.out.println(s2+200);//100200

        String s3 = String.valueOf(100);
        System.out.println(s3+200);//100200

        //字符串(String)->基本类型
        int i = Integer.parseInt(s1);
        System.out.println(i-10);
		
		// 如果字符串参数的内容无法正确转换为对应的基本类型,
		//则会抛出java.lang.NumberFormatException 异常
        int a = Integer.parseInt("a");// NumberFormatException
        System.out.println(a);
    }
}

全部评论

相关推荐

点赞 收藏 评论
分享
牛客网
牛客企业服务