美文网首页
2020-08-18--Java--day01【Object类、

2020-08-18--Java--day01【Object类、

作者: program_white | 来源:发表于2020-08-18 22:58 被阅读0次

    主要内容

    • Object类
    • Date类
    • DateFormat类
    • Calendar类

    1.Object类

    1.1概述

    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):指示其他某个对象是否与此对象“相等”。

    1.2 toString方法

    • public String 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
    }
    

    在IntelliJ IDEA中,可以点击Code菜单中的Generate...,也可以使用快捷键alt+insert,点击toString()选项。选择需要包含的成员变量并确定。生成的重写方法toString方法就类似于上边的方法。

    小贴士: 在我们直接使用输出语句输出对象名的时候,其实通过该对象调用了其toString()方法。如果输出的内容为一个地址值,那么该类没有重写toString,否则,就重写了toString方法。

    那么接下来就可以试验一下哪些方法重写了toString,哪些方法没有重写toString。

    Person类:

    public class Person {
        private String name;
        private int age;
    
        public Person() {
        }
    
        public Person(String name, int age) {
            this.name = name;
            this.age = age;
        }
    
        /*
            直接打印对象的地址值没有意义,需要重写Object类中的toString方法
            打印对象的属性(name,age)
         */
        @Override
        public String toString() {
            return "Person{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
       //getter和setter省略
    

    Main类:

    public class Demo01ToString{
        public static void main(String[] args) {
            /*
                Person类默认继承了Object类,所以可以使用Object类中的toString方法
                String toString() 返回该对象的字符串表示。
             */
            Person p = new Person("张三",18);
            String s = p.toString();
            System.out.println(s);//com.itheima.demo01.Object.Person@75412c2f | abc | Person{name=张三 ,age=18}
    
            //直接打印对象的名字,其实就是调用对象的toString  p=p.toString();
            System.out.println(p);//com.itheima.demo01.Object.Person@5f150435 | abc | Person{name=张三 ,age=18}
    
            //看一个类是否重写了toString,直接打印这个类的对象即可,如果没有重写toString方法那么打印的是对象的地址值
            Random r = new Random();
            System.out.println(r);//java.util.Random@3f3afe78  没有重写toString方法
    
            Scanner sc = new Scanner(System.in);
            System.out.println(sc);//java.util.Scanner[delimiters=\p{javaWhitespace}+..  重写toString方法
    
            ArrayList<Integer> list = new ArrayList<>();
            list.add(1);
            list.add(2);
            list.add(3);
            System.out.println(list);//[1, 2, 3]  重写toString方法
        }
    }
    
    • Random类中就没有重写toString方法
    • Scanner类重写了toString方法
    • ArrayList也重写了toString方法

    1.3 equals方法

    1.Object类中的Equals()

    Person类默认继承了Object类,所以可以使用Object类的equals方法.

    public boolean equals(Object obj):指示其他某个对象是否与此对象“相等”。

    equals方法源码:

    public boolean equals(Object obj) {
             return (this == obj);
    }           
    
    • 参数:Object obj:可以传递任意的对象
    • 返回值:== 比较运算符,返回的是一个布尔值 true false
    • 基本数据类型:比较的是值
    • 引用数据类型:比价的是两个对象的地址值

    举例:
    Person类:

    public class Person {
        private String name;
        private int age;
    
        public Person() {
        }
    
        public Person(String name, int age) {
            this.name = name;
            this.age = age;
        }
       // getter和setter省略
    }
    

    MainEquals:

    public class Demo02Equals {
        public static void main(String[] args) {
    
            Person p1 = new Person("迪丽热巴",18);
            //Person p2 = new Person("古力娜扎",19);
            Person p2 = new Person("迪丽热巴",18);
            System.out.println("p1:"+p1);//p1:com.itheima.demo01.Object.Person@58ceff1
            System.out.println("p2:"+p2);//p2:com.itheima.demo01.Object.Person@7c30a502
    
            boolean b = p1.equals(p2);       //调用Object类中的Equals方法,this为p1,obj为p2
            System.out.println(b);        //false
    

    对应源码:

    this是谁?

    • 那个对象调用的方法,方法中的this就是那个对象;p1调用的equals方法所以this就是p1。
      obj是谁?
    • 传递过来的参数p2
      返回为false,因为引用类型比较地址值。

    在创建对象p1和p2后,加上一段:

    p1 = p2
    

    那么代码结果为true,因为p2 的地址值也是p1的地址值。

    2.重写Object类的Equals方法

    Object类的equals方法,默认比较的是两个对象的地址值,没有意义。

    所以我们要在Person类中重写equals方法,比较自己想要比较的内容:
    例如:
    比较两个对象的属性(name,age)

    问题:

    我们观察Object类中的Equals方法的参数,类型为Object。
    这里隐含着一个多态,发生了向上转型--Person-->Objetct。

    • 那么多态的弊端:无法使用子类特有的内容(属性 和方法)。
      Object obj = p2 = new Person("古力娜扎",19);
    • 解决:可以使用向下转型(强转)把obj类型转换为Person。

    所以我们在Person类中重写Equals方法时,参数类型如果为Object的话,要进行判断参数的类型,因为Object类时所有类的父类,我们不知道Object类创建的对象是哪个类。

    Person类--Equeals():

    public boolean equals(Object obj) {
            //增加一个判断,传递的参数obj如果是this本身,直接返回true,提高程序的效率
            if(obj==this){
                return true;
            }
    
            //增加一个判断,传递的参数obj如果是null,直接返回false,提高程序的效率
            if(obj==null){
                return false;
            }
    
            //增加一个判断,防止类型转换一次ClassCastException
            if(obj instanceof Person){
                //使用向下转型,把obj转换为Person类型
                Person p = (Person)obj;
                //比较两个对象的属性,一个对象是this(p1),一个对象是p(obj->p2)
                boolean b = this.name.equals(p.name) && this.age==p.age;
                return b;
            }
            //不是Person类型直接返回false
            return false;
    

    在该方法中充分考虑了参数对象为空、参数为本身等问题,如果对象类型为Person类,那么就向下转型为Person类,就可以调用该类的属性和方法了,进而就可以判断该类的age和name和本类是否一致。

    可以使用快捷键alt+insert,并选择equals() and hashCode()进行自动代码生成,
    tips:Object类当中的hashCode等其他方法,今后学习。

    自动生成的代码:

    @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            //getClass() != o.getClass() 使用反射技术,判断o是否是Person类型  等效于 obj instanceof Person
            if (o == null || getClass() != o.getClass()) return false;
            Person person = (Person) o;
            return age == person.age && Objects.equals(name, person.name);
        }
    

    流程与上述代码大概一致,但是子啊比较的时候使用Objects.equals()不太明白,下一节讲Object类的静态方法Equals()。

    1.4 Object类中的静态方法Equals()

    Objects类的equals方法:对两个对象进行比较,防止空指针异常。

    equals()源码:

    public static boolean equals(Object a, Object b) {
            return (a == b) || (a != null && a.equals(b));
    }
    

    该方法可有效的防止比较对象为空时报错的情况。
    DemoObjects类:

    public class Demo03Objects {
        public static void main(String[] args) {
            String s1 = "abc";
    //        String s1 = null;
            String s2 = "abc";
            boolean b = s1.equals(s2); // NullPointerException null是不能调用方法的,会抛出空指针异常
            System.out.println(b);
    
            //s1,s2为引用类型,只不过String类重写了toString方法,s1=s2=“abc”
            boolean b2 = Objects.equals(s1, s2);
            System.out.println(b2);
    
        }
    }
    
    • 当s1和s2都为“abc”时,因为使用s1.Equals(s2)和Object.Equals(s1,s2)是一样的。
    • 当s1为空时,在使用该空对象s1调用Equals(s2),报出NullPointerException (空指针异常),而调用Object.equals(s1=null,s2)不会报错。
    • 问题:equals()对于引用类型比较的应该是地址值,那么我们创建了两个String类对象,理论上应该地址值是不同的,但是由于String类常量池的存在,所以s1和s2指向的地址是相同的。

    1.5Object类方法总结

    1.toString()方法
    1. 作用:打印对象信息
    2. 重写前:打印的是包名类名@地址值
    3. 重写后;打印的是对象自定义的内容
    2.equals()方法
    1. 作用:比较两个对象
    2. 重写前:比价两个对象的地址值(Object类)
    3. 重写后:比较类中自定义的内容
    3.Objec类中静态equals()
    1. 作用:比较两个对象是否相同。
      只是加了一些健壮性操作,防止空指针异常。

    2.日期时间类

    • java.util.Date:表示日期和时间的类,类 Date 表示特定的瞬间,精确到毫秒。

    • 毫秒:千分之一秒 1000毫秒=1秒
      特定的瞬间:一个时间点,一刹那时间。

    • 时间原点(0毫秒):
      1970 年 1 月 1 日 00:00:00(英国格林威治)。

    • 把毫秒转换为日期:
      1 天 = 24 × 60 × 60 = 86400 秒 = 86400 x 1000 = 86400000毫秒

    • 毫秒值的作用:可以对时间和日期进行计算,例如:2099-01-03 到 2088-01-01 中间一共有多少天?
      可以日期转换为毫秒进行计算,计算完毕,在把毫秒转换为日期。

    注意:
    中国属于东八区,会把时间增加8个小时,也就是1970 年 1 月 1 日 08:00:00

    2.1Date类

    Date拥有多个构造函数,只是部分已经过时

    1.构造方法

    1.空参数构造方法:获取当前系统的时间

        /*
            Date类的空参数构造方法
            Date() 获取当前系统的日期和时间
         */
        private static void demo01() {
            Date date = new Date();
            System.out.println(date);//Fri Aug 21 22:58:31 CST 2020
        }
        public static void main(String[] args) {
            demo01();
        }
    

    2.带参数的构造方法:传入long类型的毫秒值,返回对应日期。

    /*
            Date类的带参数构造方法
            Date(long date) :传递毫秒值,把毫秒值转换为Date日期
         */
        private static void demo02() {
            Date date = new Date(0L);
            System.out.println(date);// Thu Jan 01 08:00:00 CST 1970
    
            date = new Date(3742767540068L);
            System.out.println(date);// Sun Aug 08 09:39:00 CST 2088
        }
         public static void main(String[] args) {
            demo02();
        }
    
    2.成员方法

    1.成员方法getTime():获取当前日期对应的毫秒值(Long类型)

        /*
            long getTime() 把日期转换为毫秒值(相当于System.currentTimeMillis()方法)
              返回自 1970 年 1 月 1 日 00:00:00 GMT 以来此 Date 对象表示的毫秒数。
         */
        private static void demo03() {
            Date date = new Date();
            long time = date.getTime();      //获取当前日期对应的毫秒值
            System.out.println(time);       //3742777636267
        }
        public static void main(String[] args) {
            demo03();
        }
    

    2.2DateFormat类

    java.text.DateFormat 是日期/时间格式化子类的抽象类,我们通过这个类可以帮我们完成日期和文本之间的转换,也就是可以在Date对象与String对象之间进行来回转换。

    • 格式化:按照指定的格式,从Date对象转换为String对象。
    • 解析:按照指定的格式,从String对象转换为Date对象。
    1.构造方法

    由于DateFormat为抽象类,不能直接使用,所以需要创建常用的子类java.text.SimpleDateFormat的对象来使用。
    这个类的构造方法需要一个模式(格式)来指定格式化或解析的标准。构造方法为:

    • public SimpleDateFormat(String pattern):用给定的模式和默认语言环境的日期格式符号构造SimpleDateFormat。
    • 参数pattern是一个字符串,代表日期时间的自定义格式。
    2.格式规则

    常用的格式规则为:

    标识字母(区分大小写) 含义
    y
    M
    d
    H
    m
    s

    备注:更详细的格式规则,可以参考SimpleDateFormat类的API文档0。

    写对应的模式,会把模式替换为对应的日期和时间
    例如:"yyyy-MM-dd HH:mm:ss"

    • 注意:
      模式中的字母不能更改,连接模式的符号可以改变
      "yyyy年MM月dd日 HH时mm分ss秒"
    3.SimpleDateFormat构造方法的使用
    import java.text.DateFormat;
    import java.text.SimpleDateFormat;
    
    public class Test {
        public static void main(String[] args) {
            DateFormat obj = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss");
        }
    }
    

    传入后没有任何输出,只是在之后的使用中会起到限定格式的作用。

    4.format方法

    public String format(Date date):将Date对象格式化为字符串。

    Test:

    public class Test {
        public static void main(String[] args) {
            // 1.创建SimpleDateFormat对象,在构造中设置格式
            DateFormat obj = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss");
    
            // 2.获取当前时间(无格式)
            Date data = new Date();
            System.out.println(data);    //Sat Aug 22 23:15:42 CST 2020
            
            // 3.调用format()继续宁转换
            String str = obj.format(data);
            System.out.println(str);        //2020-08-22 23-16-48
        }
    }
    
    5.parse方法

    public Date parse(String source):将字符串解析为Date对象。

    public class Test {
        public static void main(String[] args) throws ParseException {
            // 1.创建SimpleDateFormat对象,在构造中设置格式
            DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss");
    
            // 2.生成与构造方法中格式一致的时间格式
            String str = "2020-08-22 23-16-56";
    
            // 3.调用parse转换为Data类型
            Date data = df.parse(str);
            System.out.println(data);   //Sat Aug 22 23:16:56 CST 2020
        }
    }
    

    在使用parse的过程中,会报出错误,原因是在该类parse方法的内部使用了异常捕获,所以我们在使用是也要异常捕获,alt+Enter选择第一个选项--在该方法中加上异常捕获,或者选择第二个,try-catch捕获异常。

    2.3时间日期练习

    请使用日期时间相关的API,计算出一个人已经出生了多少天。

    思路:

    1.获取当前时间对应的毫秒值
    2.获取自己出生日期对应的毫秒值
    3.两个时间相减(当前时间– 出生日期)

    伪代码流程:
    1.使用Scanner类中的方法next,获取出生日期
    2.使用DateFormat类中的方法parse,把字符串的出生日期,解析为Date格式的出生日期
    3.把Date格式的出生日期转换为毫秒值
    4.获取当前的日期,转换为毫秒值
    5.使用当前日期的毫秒值-出生日期的毫秒值
    6.把毫秒差值转换为天(s/1000/60/60/24)

    代码实现:

    import java.text.DateFormat;
    import java.text.ParseException;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.Scanner;
    
    public class Test {
        public static void main(String[] args) throws ParseException {
            // 1.使用Scanner类中的方法next,获取出生日期
            Scanner sc = new Scanner(System.in);
            System.out.println("请输入您的出生日期,格式:yyyy-MM-dd");
            String birthdayDateString = sc.next();
            // 2.将出生日期转换为Data格式(调用parse方法)
            DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
            Date birthdaydata = df.parse(birthdayDateString);
            // 3.把Data格式转换为毫秒值
            long birthdaydataTime = birthdaydata.getTime();
            System.out.println(birthdaydataTime);       //973785600000
            // 4.获取当前时间并转换为毫秒值
            Date data = new Date();
            long NowTime = data.getTime();
            // 5.相减,将毫秒值转换为天
            long time = NowTime - birthdaydataTime;
            System.out.println(time/1000/60/60/24);      //7226
        }
    }
    

    2.4Calendar类

    1.概念

    java.util.Calendar是日历类,在Date后出现,替换掉了许多Date的方法。

    2. 获取方式

    Calendar为抽象类,Calendar类在创建对象时并非直接创建,而是通过静态方法创建,返回子类对象,如下:

    Calendar静态方法:

    • public static Calendar getInstance():使用默认时区和语言环境获得一个日历

    例如:

    public class Demo01Calendar {
        public static void main(String[] args) {
            Calendar c = Calendar.getInstance();//多态写法,左边为父类引用,右边new一个子类对象
            System.out.println(c);
        }
    }
    
    3.常用方法

    根据Calendar类的API文档,常用方法有:

    • public int get(int field):返回给定日历字段的值。
    • public void set(int field, int value):将给定的日历字段设置为给定值。
    • public abstract void add(int field, int amount):根据日历的规则,为给定的日历字段添加或减去指定的时间量。
    • public Date getTime():返回一个表示此Calendar时间值(从历元到现在的毫秒偏移量)的Date对象。

    成员方法的参数:
    int field:日历类的字段,可以使用Calendar类的静态变量获取。

    Calendar类中提供很多成员常量,代表给定的日历字段:

    字段值 含义
    YEAR
    MONTH 月(从0开始,可以+1使用)
    DAY_OF_MONTH 月中的天(几号)
    HOUR 时(12小时制)
    HOUR_OF_DAY 时(24小时制)
    MINUTE
    SECOND
    DAY_OF_WEEK 周中的天(周几,周日为1,可以-1使用)

    get/set方法

    • get方法用来获取指定字段的值。get方法默认获取当前时间。
    • set方法用来设置指定字段的值。

    代码使用演示:

    public class Demo02Calendar {
        public static void main(String[] args) {
            demo01();
            demo02();
        }
        /*
            public int get(int field):返回给定日历字段的值。
            参数:传递指定的日历字段(YEAR,MONTH...)
            返回值:日历字段代表的具体的值
         */
        private static void demo01() {
            //使用getInstance方法获取Calendar对象
            Calendar c = Calendar.getInstance();
    
            int year = c.get(Calendar.YEAR);
            System.out.println(year);       //2020
    
            int month = c.get(Calendar.MONTH);
            System.out.println(month+1);//西方的月份0-11 东方:1-12      //8
    
            //int date = c.get(Calendar.DAY_OF_MONTH);
            int date = c.get(Calendar.DATE);
            System.out.println(date);            //23
        }
        /*
            public void set(int field, int value):将给定的日历字段设置为给定值。
            参数:
                int field:传递指定的日历字段(YEAR,MONTH...)
                int value:给指定字段设置的值
         */
        private static void demo02() {
            //使用getInstance方法获取Calendar对象
            Calendar c = Calendar.getInstance();
    
            // 1.一个一个设置
            //设置年为9999
            c.set(Calendar.YEAR,9999);
            //设置月为9月
            c.set(Calendar.MONTH,9);
            //设置日9日
            c.set(Calendar.DATE,9);
            
            //2. 同时设置年月日,可以使用set的重载方法
            c.set(8888,8,8);
    
            int year = c.get(Calendar.YEAR);
            System.out.println(year);         //8888
    
            int month = c.get(Calendar.MONTH);
            System.out.println(month);//西方的月份0-11 东方:1-12    //8
    
            int date = c.get(Calendar.DATE);
            System.out.println(date);            //8
        }
    }
    

    add方法

    add方法可以对指定日历字段的值进行加减操作,如果第二个参数为正数则加上偏移量,如果为负数则减去偏移量。

    代码如:

    public class Demo02Calendar {
        public static void main(String[] args) {
            demo03();
        }
    /*
            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);
            System.out.println(year);        // 2022
    
            int month = c.get(Calendar.MONTH);
            System.out.println(month);//西方的月份0-11 东方:1-12       //4
    
            //int date = c.get(Calendar.DAY_OF_MONTH);
            int date = c.get(Calendar.DATE);
            System.out.println(date);         //24 
        }
    }
    

    getTime方法

    在Date中得getTime()是将Date类型的日期转化为Long类型的毫秒值,但是在
    Calendar中的getTime方法并不是获取毫秒时刻,该类重写了getTime(),作用是拿到对应的Date类型对象。

    public class Demo02Calendar {
        public static void main(String[] args) {
            demo04();
        }
    
        /*
            public Date getTime():返回一个表示此Calendar时间值(从历元到现在的毫秒偏移量)的Date对象。
            把日历对象,转换为日期对象
         */
        private static void demo04() {
            //使用getInstance方法获取Calendar对象
            Calendar c = Calendar.getInstance();
    
            Date date = c.getTime();
            System.out.println(date);     //Mon Aug 24 23:37:58 CST 2020
        }
    }
    

    2.5 日期相关类总结

    1.Date类

    A. 构造方法

    • 无参构造:Date(),根据系统时间创建日期对象
    • 有参构造:Date(long time),根据传入的毫秒值创建时间对象(1970-01-01-00:00【中国推迟8个小时】)

    B. 成员方法

    • long getTime(),获取当前Date日期对象的毫秒值时间
    • String toLocaleString(),根据本地格式显示当前Date对象。
    2.DataFormat类&SimpleDateFormat类

    A. 构造方法

    • SimpleDateFormat(String s),根据指定模板创建日期格式化对象

    B. 成员方法

    • String format(Date d),根据指定格式将d转化为字符串。
    • Date parse(String s),根据指定格式传入字符串,返回Date对象
    3. Calendar类

    A. 创建Calendar类对象方式

    • Calendar c = Calendar.getInstance(),获取日历对象

    B. 成员方法

    • int get(int field),获取当前日历对象的指定日历字段field的信息。
    • void set(int field,int val),将指定日历字段field设置为指定的值val
    • void add(int field,int val),将指定日历字段field增加/减少指定的值,由val的正负决定。
    • Date getTime(),将当前日历对象转化为Date对象。

    对于前三个方法的参数field,类似于每一个字段的索引,其在Calendar类中都是静态的变量,并使用final修饰,也就是说不可改变的:

    public static final int ERA = 0;
    public static final int YEAR = 1;
    public static final int MONTH = 2;
    public static final int WEEK_OF_YEAR = 3;
    public static final int WEEK_OF_MONTH = 4;
    ...
    

    所以我们传入的参数其实是得到每个字段的索引值,get()获取的是该索引对应的值,set设置该索引对应值的值。...

    相关文章

      网友评论

          本文标题:2020-08-18--Java--day01【Object类、

          本文链接:https://www.haomeiwen.com/subject/speljktx.html