Skip to content

15. API 工具类

API (Application Programming Interface) 应用程序接口

Java中的API,就是JDK提供的各种功能的Java类

JDK帮助文档

  1. 官网
  2. 中文

15.1 常用类介绍

  1. java.lang
    • Java语言包,包含String、StringBuffer、Integer、Math、System。 任何类中,该包中的类都会被自动导入。
  2. java.util
    • 包含一些实用的工具类( 包含list, calendar, date等类)
  3. java.io
    • 提供多种输入/输出功能的类。
  4. java.net
    • 提供网络应用功能的类。

15.2 Object类

  1. Object类是所有类的超类。Object是Java语言中唯一一个没有父类的类。
  2. 一个类可以不是Object类的直接子类,但一定是Object类的子类,Java中的每一个类都是从Object扩展来的。
  3. 在Object类中定义的方法,在所有类中都可以使用。
    1. public boolean equals(Object obj)
      • 比较两个对象引用的值是否相等(比较哈希地址)
    2. public int hashCode()
      • 返回十进制整数,唯一标识一个对象, hashcode生成参考连接
    3. public String toString()
      • 返回 类名@hashcode
java
package com.neusoft.utils;

/**
 * 项目:      javaadvice
 * 类名:       MyObject
 * 创建时间:  2020/11/18  8:46
 * 描述 :     Object说明
 * 作者 :     张金山
 * QQ :     314649444
 * Site:      https://jshand.gitee.io
 */
public class MyObject  {



    private String name ="xx";
    private Integer age = 10;


    @Override
    public String toString() {
        return "MyObject{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    @Override
    public boolean equals(Object obj) {
        if(! (obj instanceof MyObject)){
            return  false;
        }

        MyObject that = (MyObject) obj;

        return age == age && that.name.equals(this.name);

    }

    @Override
    public int hashCode() {
        return name.hashCode();
    }

    public static void main(String[] args) {

        MyObject myObject = new MyObject();
        MyObject myObject2 = new MyObject();

        //toString 转换成字符串的表现形式,
        System.out.println(myObject);//打印对象默认调用的是toString方法
        System.out.println(myObject.toString());


        //hashCode
        System.out.println("myObject.hashCode():"+myObject.hashCode());
        System.out.println("myObject.hashCode():"+myObject.hashCode());
        System.out.println("myObject2.hashCode():"+myObject2.hashCode());


        //equals
        System.out.println("myObject.equals(myObject2):"+myObject.equals(myObject2));
        
    }
}
  • 注意:覆盖equals( )方法同时,还要记得覆盖hashCode( )方法。需要说明,如果equals( )返回两个对象不等,它们的hashCode( )也可以返回相同的整数。但是最好让它们的hashCode( )返回不同的整数,这有利于提高Hash类型集合的性能。
  • 重写equals方法时,一定要重写hashcode()方法吗?
    • hashcode的调用的条件:
      • 想往map里面放一个类作为map的键值,这个类又是自己设计的;
      • 虽然类不是自己写的,但是你修改了这个类的equals方法;
    • 如果满足上述调用条件,就要注意重写hashcode方法。 这样 当你往map里放值得时候,系统会调用这个对象的.hashcode()方法来生成相应的hash值,来映射相应的对象。
  • 如果同一个类的两个对象的属性值相等,那么他们的hashcode一定相等吗?
    • 这个要看你具体如何实现你的hashcode,如果你希望他们的值一样hashcode也一样,你就可以这样实现。 但是hashcode的实现,一般要满足几个特征,比如 自反性,传递性什么的。

15.3 练习

编写一个商品类,包含品名和价格。创建商品对象,判断两个同名商品对象是否相同;判断两个同名同价格商品对象是否相同。

答案

java
package com.neusoft.utils;

import com.neusoft.ex.Pro;

/**
 * 项目:      javaadvice
 * 类名:       Product
 * 创建时间:  2020/11/18  9:46
 * 描述 :      产品
 * 作者 :     张金山
 * QQ :     314649444
 * Site:      https://jshand.gitee.io
 */
public class Product {
    private String name;
    private Double price;


    //ALT+INSERT


    //构造器 无参、全参
    public Product() {
    }
    public Product(String name, Double price) {
        this.name = name;
        this.price = price;
    }


    //public setter  getter
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Double getPrice() {
        return price;
    }

    public void setPrice(Double price) {
        this.price = price;
    }


    //toString

    @Override
    public String toString() {
        return "Product{" +
                "name='" + name + '\'' +
                ", price=" + price +
                '}';
    }


    public static void main(String[] args) {


        Product p1 = new Product("铅笔刀",4.5);
        Product p2 = new Product("儿童画册",30.0);
        Product p3 = new Product("儿童画册",30.0);


        System.out.println("p1:"+p1);
        System.out.println("p2:"+p2);
        System.out.println("p1==p2\t"+(p1 ==p2));

        System.out.println("p1.getName():"+p1.getName());
        System.out.println("p2.getName():"+p2.getName());

        System.out.println("p1.getName() == p2.getName(): \t"+(p1.getName() == p2.getName()));
        System.out.println("p1.getName().equals( p2.getName()): \t"+(p1.getName().equals(p2.getName())));

        System.out.println("p2.getName() == p3.getName(): \t"+(p2.getName() == p3.getName()));
        System.out.println("p2.getName().equals( p3.getName()): \t"+(p2.getName().equals(p3.getName())));


        //String 字符串类的
        String str1 = "abc";
        String str2 = "abc";
        String str3 = "ab"+"c";
        String str4 = new String("abc");

        System.out.println("str1 == str2\t"+(str1 == str2)); // true
        System.out.println("str2 == str3\t"+(str2 == str3)); // true
        System.out.println("str2 == str4\t"+(str2 == str4)); // false


    }


}

15.4 包装类

  • Java编程语言不把基本数据类型看作对象。Java 编程语言提供包装类来将基本数据类型看作对象。
  • 在功能上包装类能够完成数据类型之间(除boolean)的相互转换,尤其是基本数据类型和String类型的转换。
  • 包装类中包含了对应基本数据类型的值,封装了String和基本数据类型之间相互转换的方法,还有一些处理这些基本数据类型时非常有用的属性和方法。
  • 基本数据类型不是对象层次结构的组成部分。有时需要像处理对象一样处理这些基本数据类型,可通过相应的“包装类”来将其“包装”后使用。
  • 基本数据类型和对应包装类
数据类型包装类
booleanBoolean
byteByte
charCharacter
doubleDouble
floatFloat
intInteger
longLong
shortShort

整型最大值、最小值

类型最大值最小值
属性数值属性数值
byteByte. MAX_VALUE127Byte.MIN_VALUE-128
shortShort. MAX_VALUE32767Short.MIN_VALUE-32768
intInteger. MAX_VALUE0x7fffffffInteger.MIN_VALUE0x80000000
longLong. MAX_VALUE0x7fffffffffffffffLLong.MIN_VALUE0x8000000000000000L

使用Character对字符判断

Character方法作用
static boolean isDigit(char ch)判断字符ch是否为数字
static boolean isLetter(char ch)判断字符ch是否为字母
static boolean isLowerCase(char ch)判断字符ch是否为小写字母
static boolean isSpaceChar(char ch)判断字符ch是否为Unicode中的空格

字符串与基本数据类型、包装类型转换图

转换为包装类

  • 基本数据类型转换为包装类

    java
    Integer integer = new Integer(100);
    
    double db = 3.56;
    Double dbWrap = new Double(db);

    字符串转换为包装类

    • 字符串通过构造方法转换为包装类
    • 字符串通过包装类的valueOf(String s)转换为包装类
    • 注意:字符串不能通过以上两种方式转换为Character
    java
    //字符串转换成包装类
    String  num1 = "100";
    Integer wrapNum1 = new Integer(num1);
    System.out.println("wrapNum1\t"+wrapNum1);
    
    Integer wrapNum2 = Integer.valueOf(num1);
    System.out.println("wrapNum2\t"+wrapNum2);

包装类转换为其他类型

  • 包装类通过xxxValue()方法转换为基本数据类型

    java
    //包装类型转基础类型
    Integer integer1 = new Integer(500);
    int num2 = integer1.intValue();
    System.out.println(++num2);
  • 包装类转换为字符串 ,包装类通过toString()方法转换为字符串

    java
    //包装类型转换成String
    System.out.println("integer1.toString().length():"+integer1.toString().length());
  • 字符串转换为 通过parseXXX(String s)方法转换为基本数据类型

//通过包装类的 parseXXX方法将字符串转换成 基础类型
String  num3 = "998";
int num4 = Integer.parseInt(num3);
double num5 = Double.parseDouble(num3);

自动拆装箱

自动的装箱和自动拆箱

  • 在进行基本数据类型和对应的包装类转换时,系统将自动进行

  • JDK自从5.0版本后引入

  • 方便程序的编写

    java
    //jdk 1.5 自动装箱(包装类型<--基础类型)、拆箱(包装类型-->基础类型)
    Integer num6 = new Integer(50);
    System.out.println(++num6);
    
    int num7 = new Integer(60);
    Integer num8 = num7;

15.5练习

从控制台得到字符串作为整数,判断该字符串能否转换为数字

15.5 字符串

  1. 字符串是我们在编程中最常使用的一种数据类型,它的表现形式可以分为两种:

    • String
    • StringBuffer。
  2. 字符串不属于8种基本的数据类型,而是一种引用类型。

  3. String对象代表一组不可改变的Unicode字符序列,对它的任何修改实际上又产生一个新的字符串,String类对象的内容一旦被初始化就不能再改变。

    字符编码扩展 : https://baike.baidu.com/item/%E5%AD%97%E7%AC%A6%E7%BC%96%E7%A0%81

  4. StringBuffer对象代表一组可改变的Unicode字符序列

  5. String类是final类型的类。

15.5.1 String的创建

String的创建:有两种方式:

  • 静态方式(常用)。像是给变量直接赋值一样来使用。如:String s1 = “abc”; String s2 = “abc”;

  • 动态方式。动态的内存分配,使用new运算符。

    如:String s3= new String(“abc”); String s4= new String(“abc”);

    java
    //1 使用字面常量
    String  str = "abcd";
    
    //2 构造器创建String
    String str2 = new String("abcd");
    
    char[] cs = {'a','b','c'};
    String str3 = new String(cs);
    
    String str4 = new String(cs,1,2);
    System.out.println("str3:"+str3);
    System.out.println("str4:"+str4);
    
    StringBuffer stringBuffer = new StringBuffer("def");
    String str5 = new String(stringBuffer);
    System.out.println("str5:"+str5);

两种方式创建的字符串区别:

  • 使用静态方式创建的字符串,在方法区的常量池中只会产生唯一一个字符串对象,使用该方式产生同样一个字符串时,内存中不再开辟另外一块空间,而是两个引用变量指向同一个字符串对象。
  • 使用动态方式创建的字符串,在堆内存中会产生出不同的对象。

String类构造方法较多,常用的有:

  • String s = new String() 初始化一个新创建的String对象,表示一个空字符串(“ ”);注意空字符串与null的区别:空字符串表示String对象的内容为空,而null表示String类的变量不指向任何的String 对象。
  • String( String original) 创建一个String对象,并用original为该对象初始化。
  • String( char chars[ ]) 使用一个字符数组创建一个String对象。
  • String( char chars[ ], int startIndex, int numChars) 使用一个字符数组创建一个String对象,startIndex表示数组的偏移量,numChars表示由多少个字符创建。参数偏移量可以省略。
  • String( byte asciiChars[ ]) 使用一个字节数组创建一个String对象。
  • String( byte asciiChars[ ], int startIndex, int numChars) 同上。
  • String(StringBuffer buffer) 使用StringBufffer对象中的内容为该对象初始化。

连接操作符“+”,可以将其它各种类型的数据转换成字符串,并前后连接成新的字符串

java
package com.neusoft.utils;

/**
 * 项目:      javaadvice
 * 类名:       MyString
 * 创建时间:  2020/11/18  11:29
 * 描述 :
 * 作者 :     张金山
 * QQ :     314649444
 * Site:      https://jshand.gitee.io
 */
public class MyString {
    public static void main(String[] args) {


        //String 创建
        //1 使用字面常量
        String  str = "abcd";

        //2 构造器创建String
        String str2 = new String("abcd");

        char[] cs = {'a','b','c'};
        String str3 = new String(cs);

        String str4 = new String(cs,1,2);
        System.out.println("str3:"+str3);
        System.out.println("str4:"+str4);

        StringBuffer stringBuffer = new StringBuffer("def");
        String str5 = new String(stringBuffer);
        System.out.println("str5:"+str5);


        Integer num1= 100;
        Integer num6= 100;

        Integer num2 = new Integer(100);
        Integer num3 = new Integer(100);
        Integer num4 = new Integer(500);
        Integer num5 = new Integer(500);

        Integer num7= -129;
        Integer num8= -129;


        System.out.println(num6 == num1); // true
        System.out.println(num1 == num2); // false
        System.out.println(num2 == num3); // false
        System.out.println(num4 == num5); // fasle
        System.out.println(num7 == num8); //  false


    }
}

15.5.2 字符串类特点

String类的特点:

  • 任何一个String对象在创建之后都不能对它的内容作出任何改变(immutable)
  • 连接、获得子串和改变大小写等操作,如果返回值同原字符串不同,实际上是产生了一个新的String对象
  • 在程序的任何地方,相同的字符串字面常量都是同一个对象
  • String类重置了equals方法,用于比较两个字符串的内容

15.5.3 String类中常用的方法

方法含义
boolean equals(String)判断两个字符串对象的内容是否相等
boolean equalsIgnoreCase(String)比较两个字符串的内容是否相等,忽略大小写
String toUpperCase( )将String对象中的所有字符都转换为大写
String toLowerCase( )将String对象中的所有字符都转换为小写
char charAt(int)返回指定索引处的 char 值
String substring(int begin)返回一个新字符串,该字符串是从begin开始的字符串的内容
String substring(int begin,int end)返回一个新字符串,该字符串是从begin开始到end-1结束的字符串的内容
方法含义
int indexOf/lastIndexOf(char)返回指定字符在此字符串中第一次/最后一次出现处的索引。
int indexOf/lastIndexOf(char,int)从指定的索引开始搜索,返回在此字符串中第一次/最后一次出现指定字符处的索引
int indexOf/lastIndexOf(String)返回第一次出现的指定子字符串在此字符串中的索引
int indexOf/lastIndexOf(String,int)从指定的索引开始搜索,返回在此字符串中第一次/最后一次出现指定字符串处的索引
String trim( )返回新的字符串,忽略前导空白和尾部空白
int length( )返回此字符串的长度
方法含义
String concat(String str)将指定字符串连接到此字符串的结尾
byte[] getBytes()使用平台的默认字符集将此 String 编码为 byte 序列,并将结果存储到一个新的 byte 数组中
byte[] getBytes(Charset charset)使用给定的 charset将此 String 编码到 byte 序列,并将结果存储到新的 byte 数组
String[] split(String regex)根据给定正则表达式的匹配拆分此字符串。
String replace(char oldChar, char newChar)返回一个新的字符串,它是通过用 newChar 替换此字符串中出现的所有 oldChar 得到的
boolean startsWith(String prefix)测试此字符串是否以指定的前缀开始
boolean endsWith(String suffix)测试此字符串是否以指定的后缀结束
java
package com.neusoft.utils;

/**
 * 项目:      javaadvice
 * 类名:       MyString
 * 创建时间:  2020/11/18  11:29
 * 描述 :
 * 作者 :     张金山
 * QQ :     314649444
 * Site:      https://jshand.gitee.io
 */
public class MyString {
    public static void main(String[] args) {

        //字符串的比较  equlas
        String str1 = "abc";
        String str2 = new String("abc");
        String str3 = "aBc";

        System.out.println(str1 == str2);
        System.out.println("str1.equals(str2) \t"+str1.equals(str2));
        System.out.println("str1.equalsIgnoreCase(str3) \t"+str1.equalsIgnoreCase(str3));

        str1 = null;

        // equals把常量放前面调用
        if("abc".equals(str1)){
            System.out.println("str1 和abc 相等");
        }

        //
        System.out.println("\"abc\".toUpperCase():\t"+"abc".toUpperCase());
        System.out.println("\"aBC\".toLowerCase():\t"+"aBC".toLowerCase());


        //length() 字符串长度
        //charAt(index) 返回索引位置的 字符
        String str4 = "abcdef";
        int len = str4.length();

        System.out.println("长度为:"+len);
        System.out.println("str4.charAt(0)\t"+str4.charAt(0));

        for (int i = 0; i <len ; i++) {
            char c = str4.charAt(i);
            System.out.printf("charAt(%d):  %c\r\n",i,c);
        }


        //substring 截取字符串
        System.out.println("\"abcdef\".substring(2)\t"+"abcdef".substring(2));
        System.out.println("\"abcdef\".substring(2,2)\t"+"abcdef".substring(2,4));


        //indexOf/lastIndexOf(char)
        System.out.println("\"hello world\".indexOf('l')\t"+"hello world".indexOf('l'));
        System.out.println("\"hello world\".lastIndexOf('l')\t"+"hello world".lastIndexOf('l'));

        String str5 = " hello ";
        System.out.println("str5.length\t"+str5.length()); //7
        System.out.println("str5.trim.length\t"+str5.trim().length()); //5 str5.trim()产生新字符串,对str5没有影响
        System.out.println("str5.length\t"+str5.length()); // 7


        System.out.println(str5.concat(" world !")); //产生新字符串
        System.out.println("str5\t"+str5);// str5 没有变化


        //getBytes  byte[]  getBytes(Charset charset)
        byte[] bts = "abc".getBytes();
        System.out.println(bts);

        //split
        String[] splitS = "abc,def,qqq".split(",");
        for (String split : splitS) {
            System.out.println("item:\t"+split);
        }


        //replace
        String str6 = "祝大家新年快乐!!";
        System.out.println(str6.replace('新','小'));
        System.out.println(str6.replace("新年","中秋"));


        String fileName = "01xxxxxx.txt";

        if(fileName.endsWith("txt")){
            System.out.println("文件是txt文档");
        }

        if(fileName.startsWith("0")){
            System.out.println("文件是带编号的");
        }
        //获取扩展名
        System.out.println(fileName.substring(fileName.lastIndexOf(".")+1));

    }
}

15.5.4 StringBuffer类

  • StringBuffer类用于内容可以改变的字符串
    • 可以使用StringBuffer来对字符串的内容进行动态操作,不会产生额外的对象
  • StringBuffer对象的创建
    • 构造一个其中不带字符的字符串缓冲区,其初始容量为 16 个字符
    • 构造一个不带字符,但具有指定初始容量的字符串缓冲区
    • 构造一个字符串缓冲区,并将其内容初始化为指定的字符串内容。

15.5.5 StringBuffer类常用方法

方法含义
int capacity( )返回当前容量
int length( )返回长度(字符数)
StringBuffer reverse( )将此字符序列用其反转形式取代
void setCharAt(int,char)将给定索引处的字符设置为 ch
StringBuffer delete(int begin,int end)移除此序列的子字符串中的字符
char charAt(int)返回此序列中指定索引处的 char 值
String toString( )将StringBuffer对象转换成相应的String
方法含义
StringBuffer append(String str)将指定的字符串追加到此字符序列
StringBuffer append(int num)将 int 参数的字符串表示形式追加到此序列
StringBuffer append(Object o)追加 Object 参数的字符串表示形式
StringBuffer insert(int index,String str)将字符串插入此字符序列中
StringBuffer insert(int index,char ch)将字符插入此字符序列中
StringBuffer insert(int index,Object o)将 Object 参数的字符串表示形式插入此字符序列中

如何判断StringBuffer相等

​ 想要判断两个StringBuffer变量的内容是否相等,应先用toString()将他们转换成String对象。

StringBuffer优势 :StrigBuffer节省内存开销

java
package com.neusoft.utils;

/**
 * 项目:      javaadvice
 * 类名:       StringBuffer
 * 创建时间:  2020/11/18  15:28
 * 描述 :
 * 作者 :     张金山
 * QQ :     314649444
 * Site:      https://jshand.gitee.io
 */
public class MyStringBuffer {

    public static void main(String[] args) {
        //StringBuffer
        //创建一个空的字符序列
        StringBuffer sbuffer1 = new StringBuffer();

        //使用50初始化容器的长度
        StringBuffer sbuffer2= new StringBuffer(50);


        //使用String CharSequence初始化
        StringBuffer sbuffer3 = new StringBuffer("hello");
        StringBuffer sbuffer4 = new StringBuffer(sbuffer3);

        System.out.println("-----------------------------------------------------------");
        //获取容器的容量 capacity
        System.out.println("sbuffer1.capacity\t"+sbuffer1.capacity()); // 16
        System.out.println("sbuffer2.capacity\t"+sbuffer2.capacity()); // 50
        System.out.println("sbuffer3.capacity\t"+sbuffer3.capacity()); //21


        System.out.println("-----------------------------------------------------------");
        //长度
        System.out.println("sbuffer1.length\t"+sbuffer1.length());  // 0
        System.out.println("sbuffer2.capacity\t"+sbuffer2.length()); //0
        System.out.println("sbuffer3.capacity\t"+sbuffer3.length()); // 5

        System.out.println("-----------------------------------------------------------");
        //向字符串中追加内容
        StringBuffer returnStringBuffer = sbuffer1.append("hello");  //向原有StringBuffer追加
        //sbuffer1.append("hello");  //向原有StringBuffer追加

        System.out.println("retuStringBuffer.toString \t"+returnStringBuffer);
        System.out.println(sbuffer1 == returnStringBuffer); //  true

        System.out.println("-----------------------------------------------------------");
        //追加之后,append 触发扩容
        System.out.println("sbuffer1.length\t"+sbuffer1.length());  //5
        sbuffer1.append("abcdef123456"); //追加12个字符  + 5 =  len: 17
        System.out.println("sbuffer1.capacity\t"+sbuffer1.capacity()); //



        //insert 插入字符串
        System.out.println("-----------------------------------------------------------");
        StringBuffer sbuffer5 = new StringBuffer("hello world ");
        sbuffer5.insert(5,"insert"); //helloinsert world
        System.out.println(sbuffer5);

        //delete 删除一部分字符串
        System.out.println("-----------------------------------------------------------");
        System.out.println("sbuffer5.delete(5,11)\t"+sbuffer5.delete(5,11));  // >=5 <11


        //reverse 翻转字符串
         System.out.println("-----------------------------------------------------------");
         StringBuffer sbuffer6 = new StringBuffer("大家好");

        System.out.println("sbuffer6.reverse()\t"+sbuffer6.reverse());
        sbuffer6.reverse();//

        //setCharAt
        sbuffer6.setCharAt(1,'Q');
        System.out.println("sbuffer6 \t"+sbuffer6);

    }
}

程序运行结果

java
"D:\Program Files\Java\jdk1.8.0_181\bin\java.exe" "
-----------------------------------------------------------
sbuffer1.capacity	16
sbuffer2.capacity	50
sbuffer3.capacity	21
-----------------------------------------------------------
sbuffer1.length	0
sbuffer2.capacity	0
sbuffer3.capacity	5
-----------------------------------------------------------
retuStringBuffer.toString 	hello
true
-----------------------------------------------------------
sbuffer1.length	5
sbuffer1.capacity	34
-----------------------------------------------------------
helloinsert world 
-----------------------------------------------------------
sbuffer5.delete(5,11)	hello world 
-----------------------------------------------------------
sbuffer6.reverse()	好家大
sbuffer6 	大Q好

Process finished with exit code 0

15.5.5 StringBuilder类

  • StringBuilder类是一个可变的字符序列。
    • JDK自从5.0版本后引入
    • StringBuilder类被设计用作 StringBuffer 的一个简易替换,用在字符串缓冲区被单个线程使用的时候 。
  • StringBuilder对象的创建
    • 构造一个不带任何字符的字符串生成器,其初始容量为 16 个字符。
    • 构造一个不带任何字符的字符串生成器,其初始容量由 capacity 参数指定。
    • 构造一个字符串生成器,并初始化为指定的字符串内容

15.5.6 StringBuilder常用方法

方法含义
int capacity( )返回当前容量
int length( )返回长度(字符数)
StringBuilder reverse( )将此字符序列用其反转形式取代
void setCharAt(int index,char ch)将给定索引index处的字符设置为 ch
StringBuilder delete(int begin,int end)移除此序列的子字符串中的字符
char charAt(int index)返回此序列中指定索引处的 char 值
String toString( )将StringBuilder对象转换成相应的String
方法含义
StringBuilder append(String str)将指定的字符串追加到此字符序列
StringBuilder append(int num)将 int 参数的字符串表示形式追加到此序列
StringBuilder append(Object o)追加 Object 参数的字符串表示形式
StringBuilder insert(int index,String str)将字符串插入此字符序列中
StringBuilder insert(int index,char ch)将字符插入此字符序列中
StringBuilder insert(int index,Object o)将 Object 参数的字符串表示形式插入此字符序列中

15.5.7 String类与StringBuilder类的比较

  • Java中定义了String与StringBuffer两个类来封装对字符串的各种操作
  • String类与StringBuffer类都被放到了java.lang包中
  • 两者的主要区别在于
    • String类对象中的内容初始化不可以改变
    • StringBuffer类对象中的内容可以改变

15.5.8 StringBuffer与StringBuilder的比较

  • StringBuffer和StringBuilder都是长度可变的字符串。
  • 两者的操作基本相同。
  • 两者的主要区别在于
    • StringBuffer类是线程安全的;
    • StringBuilder类是线程不安全的。 StringBuffer在JDK1.0中就有,而StringBuilder是在JDK5.0后才出现的。
    • StringBuilder的一些方法实现要比StringBuffer快 些。

15.6 日期类

15.6.1 Date

java.util.Date。

  • ​ Date 类表示指定的时间信息,可以精确到毫秒。
  • ​ 不支持国际化。
  • ​ 该类的许多方法已过时。
  • ​ 获取当前系统时间:

注意:现在我们更应该多使用 Calendar 类实现日期和时间字段之间转换,使用 DateFormat 类来格式化和分析日期字符串;Date 中的相应方法已废弃

15.6.2 Date类常用方法

方法含义
boolean after(Date when)测试此日期是否在指定日期之后
boolean before(Date when)测试此日期是否在指定日期之前
int compareTo(Date anotherDate)比较两个日期的顺序。如果参数 Date 等于此 Date,则返回值 0;如果此 Date 在 Date 参数之前,则返回小于 0 的值;如果此 Date 在 Date 参数之后,则返回大于 0 的值。
boolean equals(Object obj)比较两个日期的相等性。
java
package com.neusoft.datetime;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * 项目:      javaadvice
 * 类名:       MyDate
 * 创建时间:  2020/11/19  14:08
 * 描述 :
 * 作者 :     张金山
 * QQ :     314649444
 * Site:      https://jshand.gitee.io
 */
public class MyDate {
    public static void main(String[] args) {


        //使用无参构造器创建日期表示当前时间
        Date now = new Date();
        Date time1 = new Date(1605766222982L);
        Date time2 = new Date(2020-1900,10,19);
        Date time3 = new Date(2020-1900,10,19,14,13);
        Date time4 = new Date(2020-1900,10,19,14,13,50);




        //获取毫秒数
        System.out.println("time:"+now.getTime());
        //获取日期字段

        System.out.printf("%d-%d-%d %d:%d:%d\r\n",
                now.getYear() +1900,
                now.getMonth()+1,
                now.getDate(),
                now.getHours(),
                now.getMinutes(),
                now.getSeconds()
        );


        now.setHours(22);

        //格式化日的方式
        String formatter = "yyyy-MM-dd HH:mm:ss";
        SimpleDateFormat sdf = new SimpleDateFormat(formatter);

        System.out.println(sdf.format(now));

        //1      16000000000

        Date com1 = new Date(2020-1900,10,19,14,13,50);
        Date com2 = new Date(2020-1900,10,20,14,13,50);


        //before  after 比较
        System.out.println("com1.before(com2)\t"+com1.before(com2));
        System.out.println("com1.after(com2)\t"+com1.after(com2));

        System.out.println("com1.compareTo(com1)\t"+com1.compareTo(com1));
        System.out.println("com1.compareTo(com2)\t"+com1.compareTo(com2));
        System.out.println("com2.compareTo(com1)\t"+com2.compareTo(com1));

        //equals 比较
        System.out.println("com1.equals(com1)\t"+com1.equals(com1));
        System.out.println("com1.equals(com2)\t"+com1.equals(com2));
        
    }
}

15.6.3 Calendar类

Calendar类

  • ​ java.util.Calendar。 ​ java.util.GregorianCalendar

  • 常用的日期处理的对象。可以设置自己的时区和国际化格式。 是一个抽象类。

  • Calendar 抽象类定义了足够的方法,让我们能够表述日历的规则 。

  • 获取Calendar对象的实例:

    • Calendar c = Calendar.getInstance();
  • 设置Calendar实例所表示的时间

    • c.set(2011,6,16);
  • 获取指定的时间属性

    • c.get(Calendar.YEAR);
  • Calendar类常用属性

    属性含义
    static int HOUR小时时间
    static int MINUTE分时间
    static int SECOND秒时间
    static int DATE日期的Date部分
    static int MONTH日期的Month部分
    static int YEAR日期的年部分
java
package com.neusoft.datetime;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.TimeZone;

/**
 * 项目:      javaadvice
 * 类名:       MyCalender
 * 创建时间:  2020/11/19  14:36
 * 描述 :
 * 作者 :     张金山
 * QQ :     314649444
 * Site:      https://jshand.gitee.io
 */
public class MyCalender {

    public static void main(String[] args) {

        Calendar now = Calendar.getInstance();


        //获取字段
        System.out.println("年:"+now.get(Calendar.YEAR));
        System.out.println("月:"+now.get(Calendar.MONTH));
        System.out.println("日:"+now.get(Calendar.DATE));
        System.out.println("日DAY_OF_MONTH:"+now.get(Calendar.DAY_OF_MONTH));
        System.out.println("日DAY_OF_WEEK:"+now.get(Calendar.DAY_OF_WEEK));
        System.out.println("日DAY_OF_YEAR:"+now.get(Calendar.DAY_OF_YEAR));

        System.out.println("时:"+now.get(Calendar.HOUR));  // 12小时制
        System.out.println("时:"+now.get(Calendar.HOUR_OF_DAY)); // 12小时制
        System.out.println("分:"+now.get(Calendar.MINUTE));
        System.out.println("秒:"+now.get(Calendar.SECOND));


        //设置字段
        now.set(Calendar.HOUR,3);
        System.out.println("update->时:"+now.get(Calendar.HOUR_OF_DAY));


        //compare
        Calendar now2 = Calendar.getInstance();
        System.out.println("now2.compareTo(now):\t"+now2.compareTo(now));


        System.out.println("now.before(now2)\t"+now.before(now2));
        System.out.println("now.after(now2)\t"+now.after(now2));
        String formatter = "yyyy-MM-dd HH:mm:ss";
        SimpleDateFormat sdf = new SimpleDateFormat(formatter);

        //
        System.out.println("sdf.format(now2.getTime())\t"+sdf.format(now2.getTime()));


        //时区
        String[] avTimeZoneIds = TimeZone.getAvailableIDs();
        for (String avTimeZoneId : avTimeZoneIds) {
//            System.out.println("有效的时区:avTimeZoneId\t"+avTimeZoneId);
        }
        Calendar now3 = Calendar.getInstance(TimeZone.getTimeZone("Etc/GMT-11"));
//
        System.out.println("now3:"+sdf.format(now3.getTime()));


    }

}

15.6.4 SimpleDateFormat类

  • SimpleDateFormat类 :java.text.SimpleDateFormat
    • 一个以与语言环境相关的方式来格式化和分析日期的具体类。是抽象类java.text.DateFormat类的子类。
    • SimpleDateFormat使得可以选择任何用户定义的日期-时间格式的模式。
  • SimpleDateFormat类的使用
    • 获取SimpleDateFormat的实例
      • SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    • 将日期格式成指定的字符串
      • sdf.format(new Date());
    • 将格式化的字符串转换成日期对象
      • sdf.parse(“2011-07-16”);
  • SimpleDateFormat格式说明
字母日期或时间元素
y
M年中的月份
d月份中的天数
E星期中的天数
aAm/pm 标记
H一天中的小时数(0-23)
ham/pm 中的小时数(1-12)
m小时中的分钟数
s分钟中的秒数
S毫秒数
package com.neusoft.datetime;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * 项目:      javaadvice
 * 类名:       MyFormatter
 * 创建时间:  2020/11/19  14:54
 * 描述 :
 * 作者 :     张金山
 * QQ :     314649444
 * Site:      https://jshand.gitee.io
 */
public class MyFormatter {
    public static void main(String[] args) throws ParseException {

        //1 日期转字符串
        Date now = new Date();

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        System.out.println(sdf.format(now));


        //2 字符串转换成日期
        String time = "2020-11-19 15:55:54";
        Date date1 = sdf.parse(time);
        System.out.println("parse :"+date1.getHours());
    }
}

15.6.5 练习

编写一个方法,找到两个日期格式的字符串的最大值

15.7 章节练习

  • 编写一个程序,实现从命令行参数输入两个字符串类型的数值,并计算输出两个数值的和。 [必做题]
  • 编写一个程序,实现从命令行参数输入一字符串,统计该字符串中字符“e”出现的次数。(识点:String中常用的方法) [必做题]
  • 生成十个0~100之间的随机数,放到数组中,然后排序输出。(知识点:Math类取整,获得随机数等) [必做题]
  • 巴黎时间比北京时间晚7个小时,纽约时间比北京时间晚12个小时,试编写一程序,根据输入的北京时间输出相应的巴黎和纽约时间。[选做题]
  • 解析一个邮箱地址是否合法,如果合法则打印出用户名部分和该邮箱所属的网站域名,如果邮箱地址不合法则显示不合法的原因 [选做题]
  • 分别在控制台输入字符串和子字符串,并计算字符串中子字符串出现的次数。 [选做题]
  • 有一个字符串,其中包含中文字符、英文字符和数字字符,请统计和打印出各个字符的个数。 [选做题]
  • 有一种数叫回文数,正读和反读都一样,如12321便是一个回文数。编写一个程序,从命令行得到一个整数,判断该数是不是回文数。 [选做题]

答案

java
package com.neusoft.utils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Random;
import java.util.Scanner;

/**
 * 项目:      javaadvice
 * 类名:       Work
 * 创建时间:  2020/11/18  17:03
 * 描述 :     课后作业
 * 作者 :     张金山
 * QQ :     314649444
 * Site:      https://jshand.gitee.io
 */
public class Work {

    public static void main(String[] args) throws ParseException {

        //编写一个程序,实现从命令行参数输入两个字符串类型的数值,并计算输出两个数值的和
//        work1();

        //编写一个程序,实现从命令行参数输入一字符串,统计该字符串中字符“e”出现的次数。(识点:String中常用的方法)
//        work2();

        //生成十个0~100之间的随机数,放到数组中,然后排序输出
//        work3();

        //生成十个0~100之间的随机数,放到数组中,然后排序输出
//        work4();

        //解析一个邮箱地址是否合法,如果合法则打印出用户名部分和该邮箱所属的网站域名,如果邮箱地址不合法则显示不合法的原因
//        work5();

        //分别在控制台输入字符串和子字符串,并计算字符串中子字符串出现的次数,
        //测试 字符串[abcabcabcabc ab]
//        work6();


        /**
         *
         * 有一个字符串,其中包含中文字符、英文字符和数字字符,请统计和打印出各个字符的个数
         * 请输入一个字符串>abcdef123456!@#$
         * 字母出现的个数:[6],数字出现的个数:[6],其他字符的个数:[4]
         */
//        work7();


        /**
         * 有一种数叫回文数,正读和反读都一样,如12321便是一个回文数。编写一个程序,从命令行得到一个整数,判断该数是不是回文数
         */
        work8();

    }


    /**
     * 编写一个程序,实现从命令行参数输入两个字符串类型的数值,并计算输出两个数值的和
     */
    static void work1() {

        Scanner sc = new Scanner(System.in);
        System.out.print("请输入一个数>");
        String str1 = sc.nextLine();
        System.out.print("请输入另一个数>");
        String str2 = sc.nextLine();

        int num1 = Integer.valueOf(str1);
        int num2 = Integer.valueOf(str2);

        System.out.println("两个数的和:\t" + (num1 + num2));

    }

    /**
     * 编写一个程序,实现从命令行参数输入一字符串,统计该字符串中字符“e”出现的次数。(识点:String中常用的方法)
     */
    static void work2() {
        Scanner sc = new Scanner(System.in);
        System.out.print("请输入一个字符串>");
        String str1 = sc.nextLine();
        int len = str1.length();
        int eCount = 0;
        for (int i = 0; i < len; i++) {
            char c = str1.charAt(i);
            if (c == 'e') {
                eCount++;
            }
        }
        System.out.printf("您输入的字符串中e的个数为%d\t", eCount);

    }

    /**
     * 生成十个0~100之间的随机数,放到数组中,然后排序输出
     */
    static void work3() {

        Random rnd = new Random();
        int[] rndNums = new int[10];
        //生成10个随机数
        for (int i = 0; i < rndNums.length; i++) {
            rndNums[i] = rnd.nextInt(100);
        }

        for (int i = 0; i < rndNums.length; i++) {
            for (int j = i + 1; j < rndNums.length; j++) {
                if (rndNums[i] > rndNums[j]) {
                    int tmp = rndNums[i];
                    rndNums[i] = rndNums[j];
                    rndNums[j] = tmp;
                }
            }
        }

        System.out.println("-----------------输出排序后的数组内容-----------------------------");
        for (int rndNum : rndNums) {
            System.out.print(rndNum + "\t");
        }

    }

    /**
     * 测试日期 2020-02-28 01:02:03
     * 巴黎时间比北京时间晚7个小时,纽约时间比北京时间晚12个小时,试编写一程序,根据输入的北京时间输出相应的巴黎和纽约时间
     */
    static void work4() throws ParseException {
        String formatter = "yyyy-MM-dd HH:mm:ss";
        SimpleDateFormat sdf = new SimpleDateFormat(formatter);


        System.out.printf("请出入北京时间:格式如下(%s)", formatter);

        String time = new Scanner(System.in).nextLine();

        Date beijingTime = sdf.parse(time);

        Calendar calendar = Calendar.getInstance();
        calendar.setTime(beijingTime);


        calendar.add(Calendar.HOUR, -7);
        System.out.printf("巴黎时间:%s\r\n", sdf.format(calendar.getTime()));

        calendar.add(Calendar.HOUR, 19);
        System.out.printf("纽约时间:%s", sdf.format(calendar.getTime()));
        ;

    }


    /**
     * 解析一个邮箱地址是否合法,如果合法则打印出用户名部分和该邮箱所属的网站域名,如果邮箱地址不合法则显示不合法的原因
     * 2.1.1邮箱地址中不包含@或.
     * 2.1.2邮箱地址中含有多了@或.
     * 2.1.3邮箱地址中.出现在@的前面
     * 2.1.4用户名里有其他字符
     */
    static void work5() {

        System.out.print("请输入一个邮箱>");

        String email = new Scanner(System.in).nextLine();

        boolean validate = true;
        StringBuffer msg = new StringBuffer();
        int errorCount = 0;

        if (!email.contains("@")) {
            validate = false;
            msg.append((++errorCount) + ":地中不包含@\r\n");
        }

        if (!email.contains(".")) {
            validate = false;
            msg.append((++errorCount) + ":地中不包含.\r\n");
        }

        //@的 的indexOf 和lastIndexOf 值不一致说明至少有两个以上的@
        if (email.indexOf("@") != email.lastIndexOf("@")) {
            validate = false;
            msg.append((++errorCount) + ":地址中含有多个@\r\n");
        }

        // .的 的indexOf 和lastIndexOf 值不一致说明至少有两个以上的.
        if (email.indexOf(".") != email.lastIndexOf(".")) {
            validate = false;
            msg.append((++errorCount) + ":地址中含有多了.\r\n");
        }

        // 地址中有 . 和@ 校验 顺序
        if (email.indexOf(".") != -1
                && email.indexOf("@") != -1
                && email.lastIndexOf(".") < email.lastIndexOf("@")) {
            validate = false;
            msg.append((++errorCount) + ":地址中.出现在@的前面\r\n");
        }

        //如果包含@
        if (email.contains("@")) {
            String username = email.split("@")[0];
            for (int i = 0; i < username.length(); i++) {
                char c = username.charAt(i);
                if (!Character.isDigit(c)
                        && !Character.isLetter(c)) {
                    validate = false;
                    msg.append((++errorCount) + ":用户名里有其他字符\r\n");
                    break;
                }
            }
        }

        if (!validate) {
            System.out.println(msg.toString());
        } else {
            System.out.println("合法的地址");
        }

    }

    /**
     * 分别在控制台输入字符串和子字符串,并计算字符串中子字符串出现的次数
     * 测试 字符串[abcabcabcabc ab]
     */
    static void work6() {

        System.out.print("请输入字符串和子字符串中间用一个空格隔开>");

        String strAll = new Scanner(System.in).nextLine();
        String longStr = strAll.split(" ")[0];
        String shortStr = strAll.split(" ")[1];

        int count = 0;
        for (int i = 0; i < longStr.length(); ) {
            System.out.println("查找的开始位置为" + i);
            int index = longStr.indexOf(shortStr, i);
            if (index != -1) {//如果找到了,则下次
                count++;
                i = index + shortStr.length();
            } else {
                break;
            }
        }

        System.out.printf("子字符串一共出现【%d】次", count);
    }

    /**
     * 有一个字符串,其中包含中文字符、英文字符和数字字符,请统计和打印出各个字符的个数。
     */
    static void work7() {

        int letterCount = 0;
        int numCount = 0;
        int otherCount = 0;


        System.out.print("请输入一个字符串>\r");
        String letters = new Scanner(System.in).nextLine();

        int len = letters.length();
        for (int i = 0; i < len; i++) {
            char c = letters.charAt(i);
            if (Character.isLetter(c)) {
                letterCount++;
            } else if (Character.isDigit(c)) {
                numCount++;
            } else {
                otherCount++;
            }
        }
        System.out.printf("字母出现的个数:[%d],数字出现的个数:[%d],其他字符的个数:[%d]", letterCount, numCount, otherCount);
    }

    /**
     * 有一种数叫回文数,正读和反读都一样,如12321便是一个回文数。编写一个程序,从命令行得到一个整数,判断该数是不是回文数
     */
    static void work8() {
        System.out.print("请输入一串数字>\r");
        String nums = new Scanner(System.in).nextLine();
        //
        if (nums.length() % 2 == 0) {
            System.out.println("数字不是回文数");
            return;
        }


        boolean isPalindrome = true;
        char[] chars = nums.toCharArray();
        int middle = chars.length / 2; //中间字符的位置
        for (int i = 0; i <=chars.length / 2 ; i++) {
            if(chars[i] != chars[chars.length-i-1]){
                isPalindrome = false;
                break;
            }
        }


        if(isPalindrome){
            System.out.println("是回文数");
        }else{
            System.out.println("不是回文数");
        }

    }
}

Released under the MIT License.