java基础(6)常用API

1 Object类

`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.1 toString方法

toSttring方法:`public String toString()`:返回该对象的字符串表示。

toString方法返回该对象的字符串表示,其实该字符串内容就是对象的类型+@+内存地址值。

由于toString方法返回的结果是内存地址,没有什么意义。

而在开发中,经常需要按照对象的属性得到相应的字符串表现形式,因此也需要重写它。

//自定义一个名为toString的类
public class toString {
    String name;
    int id;

//重写toString方法 @Override
public String toString(){ return "toString{name="+name+",id="+id+"}";//返回值是一个字符串,按照自己的需要拼接成自定义的该类的字符串信息 } } //测试 public class testToSring { public static void main(String[] args) { System.out.println(new toString()); } }

//Output
toString{name=null,id=0}
//这个是编译器自动重载所写的toString,可以看到就是字符串拼接,拼接类的名字和成员变量信息
@Override
    public String toString() {
        return "toString{" +
                "name='" + name + '\'' +
                ", id=" + id +
                '}';
    }

1.2 equals方法

public boolean equals(Object obj)

1.2.1 默认地址比较:

如果自定义类中没有覆盖重写equals方法,那么Object类中默认进行`==`运算符的对象地址比较,只要不是同一个对象,结果必然为false。

public class myEquals {
    String name;
    int age;
}

public class myEquealsTest {
    public static void main(String[] args) {
        myEquals m1 = new myEquals();
        myEquals m2 = new myEquals();

        System.out.println(m1.equals(m2));
        System.out.println("=========");
        m2 = m1;//将m1赋予m2
        System.out.println(m1.equals(m2));
    }
}

//Output
false
=========
true

1.2.2 重写equals方法-对象内容比较

比如String类就重写了该方法:

//Java 源码,对字符串的内容进行比较
public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        }
        if (anObject instanceof String) {
            String anotherString = (String)anObject;
            int n = value.length;
            if (n == anotherString.value.length) {
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = 0;
                while (n-- != 0) {
                    if (v1[i] != v2[i])
                        return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }

 

如果我自定义了一个Person类,需要进行内容比较,也需要重写equals方法

public class Person {    
    private String name;
    private int age;
    
    @Override//IDEA中按住alt+Insert选择重写equals方法
    public boolean equals(Object o) {
        // 如果对象地址一样,则认为相同
        if (this == o)
            return true;
        // 如果参数为空,或者类型信息不一样,则认为不同。使用反射技术,判断o是否为Person类型
        if (o == null || getClass() != o.getClass())
            return false;
        // 转换为当前类型
        Person person = (Person) o;
        // 要求基本类型相等,并且将引用类型交给java.util.Objects类的equals静态方法取用结果
        return age == person.age && Objects.equals(name, person.name);
    }
}

上述代码充分考虑了对象是否为本身、为空、类型不一致等问题。

注意:

代码中有这句话:
Objects.equals(name, person.name)

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

在比较两个对象的时候,Object的equals方法容易抛出空指针异常,而Objects类中的equals方法就优化了这个问题。

Objects类的作用:String类的两个对象比较的时候,防止抛出空指针异常。

~~~java源码
public static boolean equals(Object a, Object b) {  
    return (a == b) || (a != null && a.equals(b));  
}
~~~
源码解读:

为什么上述源码只判断了Object a是否为空呢?

首先: null是不能调用方法的(null表示没有创建对象,没有在队内存中分配空间),会抛出空指针异常。

所以源码中先判断a不为空,再用a来调用equals方法,所以不需要判断b是否为空。

 

下面是一个例子:

import java.util.Objects;

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);
        /*
            Objects类的equals方法:对两个对象进行比较,防止空指针异常
            public static boolean equals(Object a, Object b) {
                return (a == b) || (a != null && a.equals(b));
            }
         */
        boolean b2 = Objects.equals(s1, s2);
        System.out.println(b2);

    }
}

2 Date类

2.1 Date类概述

/*
    java.util.Date:表示日期和时间的类
    类 Date 表示特定的瞬间,精确到毫秒。
    毫秒:千分之一秒 1000毫秒=1秒
    特定的瞬间:一个时间点,一刹那时间
    2088-08-08 09:55:33:333 瞬间
    2088-08-08 09:55:33:334 瞬间
    2088-08-08 09:55:33:334 瞬间
    ...
    毫秒值的作用:可以对时间和日期进行计算
    2099-01-03 到 2088-01-01 中间一共有多少天
    可以日期转换为毫秒进行计算,计算完毕,在把毫秒转换为日期

    把日期转换为毫秒:
        当前的日期:2088-01-01
        时间原点(0毫秒):1970 年 1 月 1 日 00:00:00(英国格林威治)
        就是计算当前日期到时间原点之间一共经历了多少毫秒 (3742767540068L)
    注意:
        中国属于东八区,会把时间增加8个小时
        1970 年 1 月 1 日 08:00:00

    把毫秒转换为日期:
        1 天 = 24 × 60 × 60 = 86400 秒  = 86400 x 1000 = 86400000毫秒
 */
public class Demo01Date {
    public static void main(String[] args) {
        System.out.println(System.currentTimeMillis());//获取当前系统时间到1970 年 1 月 1 日 00:00:00经历了多少毫秒
    }
}

2.2 Date类的构造方法

2.2.1 空参数构造

public class MyDateTest {
    public static void main(String[] args) {
        System.out.println(System.currentTimeMillis());

        demo01();
    }

    /*
       Date类的空参数构造方法
       Date() 获取当前系统的日期和时间
    */
    private static void demo01() {
        Date date = new Date();
        System.out.println(date);//Sun Jan 20 16:57:40 CST 2019,直接打印date,不是一个地址,说明Date类重写了toString方法

    }
}

2.2.2 带参数构造

public class MyDateTest {
    public static void main(String[] args) {
        System.out.println(System.currentTimeMillis());

        demo02();
    }

    /*
        Date类的带参数构造方法
        Date(long date) :传递毫秒值,把毫秒值转换为Date日期
     */
    private static void demo02() {
        Date date = new Date(1547974660147L);
        System.out.println(date);// Sun Jan 20 17:00:23 CST 2019
    }
}

2.2.3 getTime方法


////

Date类中的多数方法已经过时,常用的方法有: * `public long getTime()` 把日期对象转换成对应的时间毫秒值。


public
class MyDateTest { public static void main(String[] args) { System.out.println(System.currentTimeMillis()); demo03(); } /* 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); } }

2.3 DateFormate类和SimpleDateFormate类

DateFormat 是日期/时间格式化子类的抽象类,它以与语言无关的方式格式化并解析日期或时间。

日期/时间格式化子类(如 SimpleDateFormat)允许进行格式化(也就是日期 -> 文本)、解析(文本-> 日期)和标准化。

将日期表示为 Date 对象,或者表示为从 GMT(格林尼治标准时间)1970 年 1 月 1 日 00:00:00 这一刻开始的毫秒数。 


DateFormat类:是一个抽象类

要格式化一个当前语言环境下的日期,可使用某个静态工厂方法:


  myString = DateFormat.getDateInstance().format(myDate);

//
使用示例 Date date = new Date();//可以不填参数,默认为系统当前时间 String myString = DateFormat.getDateInstance().format(date); System.out.println(myString);//2019-1-20 Date date2 = new Date(10120133110L);//也可以传入毫秒值 String myString2 = DateFormat.getDateInstance().format(date2); System.out.println(myString2);//1970-4-28

 

由于DateFormat为抽象类,不能直接使用,所以需要常用的子类`java.text.SimpleDateFormat`。

这个类需要一个模式(格式)来指定格式化或解析的标准。构造方法为:

* `public SimpleDateFormat(String pattern)`:用给定的模式和默认语言环境的日期格式符号构造SimpleDateFormat。

//SimpleDateFormat的格式化方法使用示例
public class MyDateFormateTest1 {
    public static void main(String[] args) {
        // 第1步.创建SimpleDateFormat对象,构造方法中传递指定的模式
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd/ HH/mm/ss/");//第一种格式
        SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒");//第二种格式

        //第2步.创建Date对象,将其传入SimpleDateFormat的format方法,按照构造方法中指定的模式,将Date对象转换成符合模式的字符串(文本)
        Date date = new Date();
        Date date2 = new Date(123456789L);
        String myString1 = sdf.format(date);
        String myString2 = sdf2.format(date2);
        System.out.println(myString1);//   2019/01/20/ 19/56/07/
        System.out.println(myString2);//   1970年01月02日 18时17分36秒
    }
}

 

//SimpleDateFormat的解析方法parse使用示例

//Java中该parse方法的源码,按照该源码写代码
public Date parse(String source) throws ParseException
    {
        ParsePosition pos = new ParsePosition(0);
        Date result = parse(source, pos);
        if (pos.index == 0)
            throw new ParseException("Unparseable date: \"" + source + "\"" ,
                pos.errorIndex);
        return result;
    }

//使用parse方法的步骤:
//第一步:创建SimpleDateFormat对象,构造方法中传递指定的模式 SimpleDateFormat sdf3 = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss"); //第二步:String format(Date date) 按照指定的模式,把Date日期,格式化为符合模式的字符串 String source = new String("1990-10-10 10-20-20");//如果这里输入的字符串的模式不符合上面的模式,就会抛出异常 Date returnDate = new Date(); try { returnDate = sdf3.parse(source); } catch (ParseException e) { e.printStackTrace(); } System.out.println(returnDate);

2.4 Calendar类

2.4.1 Calendar抽象类获取对象的方法

Calendar 类是一个抽象类,无法创建对象使用。里面有一个静态方法getInstance(),该方法返回了一个Calendar子类对象:

public class myCalendar {
    public static void main(String[] args) {
        Calendar calendar = Calendar.getInstance();//Calendar.getInstance()直接返回一个Calendar的子类对象。
                                                    // 父类,接收子类对象,存在多态
        System.out.println(calendar);
        //java.util.GregorianCalendar[time=1547987922275,areFieldsSet=true,areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="Asia/Shanghai",offset=28800000,dstSavings=0,useDaylight=false,transitions=19,lastRule=null],firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=2019,MONTH=0,WEEK_OF_YEAR=4,WEEK_OF_MONTH=4,DAY_OF_MONTH=20,DAY_OF_YEAR=20,DAY_OF_WEEK=1,DAY_OF_WEEK_IN_MONTH=3,AM_PM=1,HOUR=8,HOUR_OF_DAY=20,MINUTE=38,SECOND=42,MILLISECOND=275,ZONE_OFFSET=28800000,DST_OFFSET=0]
    }
}

//返回了一组诸如 YEAR,MONTH,DAY_OF_MONTH,HOUR等的日历字段

 

2.4.2 Calendar类的常用成员方法

根据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对象。

//field: Calendar类中提供很多成员常量,代表给定的日历字段: | 字段值 | 含义 | | ------------ | -------------------- | | YEAR | 年 | | MONTH | 月(从0开始,可以+1使用) | | DAY_OF_MONTH | 月中的天(几号) | | HOUR | 时(12小时制) | | HOUR_OF_DAY | 时(24小时制) | | MINUTE | 分 | | SECOND | 秒 | | DAY_OF_WEEK | 周中的天(周几,周日为1,可以-1使用) |
//使用示例

public class MyCalendar2 {
    public static void main(String[] args) {
        //获取日历对象对应的的日期
        Calendar c = Calendar.getInstance();
        int year = c.get(Calendar.YEAR);
        int month = c.get(Calendar.MONTH)+1;
        int day = c.get(Calendar.DAY_OF_MONTH);
        System.out.println(year +"月" +month+"月" +day+"日");//2019月1月20日

        //设置日历中某个字段的值
        c.set(1234,2,5);
        year = c.get(Calendar.YEAR);
        month = c.get(Calendar.MONTH)+1;
        day = c.get(Calendar.DAY_OF_MONTH);
        System.out.println(year +"月" +month+"月" +day+"日");//1234月3月5日

        //在日历对象上增加年月日
        c.add(Calendar.YEAR,23);
        c.add(2,1);
        year = c.get(Calendar.YEAR);
        month = c.get(Calendar.MONTH)+1;
        day = c.get(Calendar.DAY_OF_MONTH);
        System.out.println(year +"月" +month+"月" +day+"日");//1257月4月5日

        //获取日历对象对应的日期
        Date date = c.getTime();
        System.out.println(date);//Thu Apr 05 21:02:53 CST 1257
    }
}

3 System类

import java.util.Arrays;

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

    //System.currentTimeMillis()方法
    private static void demo01() {
        long t0 = System.currentTimeMillis();
        for (int i = 0; i < 1000; i++) {
            System.out.println(i);
        }
        long t1 = System.currentTimeMillis();

        System.out.println(t1-t0);
    }
    
    //System.arraycopy()方法
    private static void demo02() {
        int[] src = new int[]{1,2,3,4,5};
        int[] dest = new int[]{6,7,8,9,10};
        System.out.println("复制后"+Arrays.toString(dest));
        System.arraycopy( src, 1, dest, 0, 3);
        for (int i = 0; i < dest.length; i++) {
            System.out.println(dest[i]);
        }//2 3 4 9 10
        //还可以使用Arrays类中的toString方法打印
        System.out.println("复制后"+Arrays.toString(dest));//复制后[2, 3, 4, 9, 10]
    }
}

4 StringBuilder类

4.1 字符串拼接问题

由于String类的对象内容不可改变,所以每当进行字符串拼接时,总是会在内存中创建一个新的对象。例如:

~~~java
public class StringDemo {
public static void main(String[] args) {
String s = "Hello";
s += "World";
System.out.println(s);
}
}
~~~
其实总共产生了三个字符串,即`"Hello"`、`"World"`和`"HelloWorld"`。引用变量s首先指向`Hello`对象,最终指向拼接出来的新字符串对象,即`HelloWord` 。

在API中对String类有这样的描述:字符串是常量,它们的值在创建后不能被更改。底层是一个被final修饰的量。

如果对字符串进行拼接操作,每次拼接,都会构建一个新的String对象,既耗时,又浪费空间。为了解决这一问题,可以使用`java.lang.StringBuilder`类。

 

4.2  StringBuilder概述

StringBuilder是个字符串的缓冲区,即它是一个容器,容器中可以装很多字符串。并且能够对其中的字符串进行各种操作。

底层也是一个数组,但是没有被final修饰,可以改变长度。

 

4.3 构造方法

根据StringBuilder的API文档,常用构造方法有2个:

- `public StringBuilder()`:构造一个空的StringBuilder容器。
- `public StringBuilder(String str)`:构造一个StringBuilder容器,并将字符串添加进去。

 

public class MyStringBuilder {
    public static void main(String[] args) {
        StringBuilder sb1 = new StringBuilder();
        System.out.println("不带参数构造字符串:"+sb1);

        StringBuilder sb2 = new StringBuilder("abssssweweweweeeeeeee");
        System.out.println("带参数构造字符串:"+sb2);
    }
}

//Output

不带参数构造字符串:
带参数构造字符串:abssssweweweweeeeeeee

4.4 Append方法和toString方法

public static void main(String[] args) {
        //创建对象
        StringBuilder builder = new StringBuilder();
        //public StringBuilder append(任意类型)
        StringBuilder builder2 = builder.append("hello");
        //对比一下
        System.out.println("builder:"+builder);
        System.out.println("builder2:"+builder2);
        System.out.println(builder == builder2); //true
        // 可以添加 任何类型
        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);
    }

 

public class Demo16StringBuilder {
    public static void main(String[] args) {
        // 链式创建
        StringBuilder sb = new StringBuilder("Hello").append("World").append("Java");
        // 调用方法
        String str = sb.toString();
        System.out.println(str); // HelloWorldJava
    }
}

5 包装类

 5.1 包装类概述

Java提供了两个类型系统,基本类型与引用类型,使用基本类型在于效率,然而很多情况,会创建对象使用,因为对象可以做更多的功能,

如果想要我们的基本类型像对象一样操作,就可以使用基本类型对应的包装类。

| 基本类型    | 对应的包装类(是某一种位于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 值。
                传递的字符串,必须是基本类型(int double等是基本类型,String不是基本类型)的字符串,否则会抛出异常 "100" 正确  "a" 抛异常
        静态方法:
            static Integer valueOf(int i) 返回一个表示指定的 int 值的 Integer 实例。
            static Integer valueOf(String s) 返回保存指定的 String 的值的 Integer 对象。
    拆箱:在包装类中取出基本类型的数据(包装类->基本类型的数据)
        调用Integer类的成员方法:
            int intValue() 以 int 类型返回该 Integer 的值。
 */
public class Demo01Integer {
    public static void main(String[] args) {
        //装箱:把基本类型的数据,包装到包装类中(基本类型的数据->包装类)
        //构造方法
        Integer in1 = new Integer(1);//方法上有横线,说明方法过时了
        System.out.println(in1);//1 重写了toString方法

        Integer in2 = new Integer("1");
        System.out.println(in2);//1

        //静态方法
        Integer in3 = Integer.valueOf(1);
        System.out.println(in3);

        //Integer in4 = Integer.valueOf("a");//NumberFormatException数字格式化异常
        Integer in4 = Integer.valueOf("1");
        System.out.println(in4);

        //拆箱:在包装类中取出基本类型的数据(包装类->基本类型的数据)
        int i = in1.intValue();
        System.out.println(i);
    }
}

5.3 自动装箱和自动拆箱

import java.util.ArrayList;

/*
    自动装箱与自动拆箱:基本类型的数据和包装类之间可以自动的相互转换
    JDK1.5之后出现的新特性
 */
public class Demo02Ineger {
    public static void main(String[] args) {
        /*
            自动装箱:直接把int类型的整数赋值包装类
            Integer in = 1; 就相当于 Integer in = new Integer(1);
         */
        Integer in = 1;

        /*
            自动拆箱:in是包装类,无法直接参与运算,可以自动转换为基本数据类型,再进行计算
            in+2;就相当于 in.intVale() + 2 = 3
            in = in.intVale() + 2 = 3 又是一个自动装箱
         */
        in = in+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)(三种方法)
        1.基本类型的值+""  最简单的方法(常用)
        2.包装类的静态方法toString(参数),不是Object类的toString() 重载
            static String toString(int i) 返回一个表示指定整数的 String 对象。
        3.String类的静态方法valueOf(参数)
            static String valueOf(int i) 返回 int 参数的字符串表示形式。
    二、字符串(String)->基本类型
    包装类都具有parseXxx静态方法可以将字符串参数转换为对应的基本类型: 使用包装类的静态方法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);//字符串和数字直接相加,是把数字当成了字符串,这是JAVA的装箱机制,最终相当于字符串的连接,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); //s1应该是一个基本数据类型,而不能是字符串 System.out.println(i-10);//90 int a = Integer.parseInt("a");//NumberFormatException, 传入的应该是一个基本数据类型,而不能是字符串
      System.out.println(a); }

注意:如果字符串参数的内容无法正确转换为对应的基本类型,则会抛出`java.lang.NumberFormatException`异常。

posted @ 2019-01-20 23:08  JohnTesla  阅读(368)  评论(0编辑  收藏  举报