15. API 工具类
API (Application Programming Interface) 应用程序接口
Java中的API,就是JDK提供的各种功能的Java类
JDK帮助文档
15.1 常用类介绍
- java.lang
- Java语言包,包含String、StringBuffer、Integer、Math、System。 任何类中,该包中的类都会被自动导入。
- java.util
- 包含一些实用的工具类( 包含list, calendar, date等类)
- java.io
- 提供多种输入/输出功能的类。
- java.net
- 提供网络应用功能的类。
15.2 Object类
- Object类是所有类的超类。Object是Java语言中唯一一个没有父类的类。
- 一个类可以不是Object类的直接子类,但一定是Object类的子类,Java中的每一个类都是从Object扩展来的。
- 在Object类中定义的方法,在所有类中都可以使用。
- public boolean equals(Object obj)
- 比较两个对象引用的值是否相等(比较哈希地址)
- public int hashCode()
- 返回十进制整数,唯一标识一个对象, hashcode生成参考连接
- public String toString()
- 返回 类名@hashcode
- public boolean equals(Object obj)
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也一样,你就可以这样实现。 但是hashcode的实现,一般要满足几个特征,比如 自反性,传递性什么的。
15.3 练习
编写一个商品类,包含品名和价格。创建商品对象,判断两个同名商品对象是否相同;判断两个同名同价格商品对象是否相同。
答案
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和基本数据类型之间相互转换的方法,还有一些处理这些基本数据类型时非常有用的属性和方法。
- 基本数据类型不是对象层次结构的组成部分。有时需要像处理对象一样处理这些基本数据类型,可通过相应的“包装类”来将其“包装”后使用。
- 基本数据类型和对应包装类
数据类型 | 包装类 |
---|---|
boolean | Boolean |
byte | Byte |
char | Character |
double | Double |
float | Float |
int | Integer |
long | Long |
short | Short |
整型最大值、最小值
类型 | 最大值 | 最小值 | ||
---|---|---|---|---|
属性 | 数值 | 属性 | 数值 | |
byte | Byte. MAX_VALUE | 127 | Byte.MIN_VALUE | -128 |
short | Short. MAX_VALUE | 32767 | Short.MIN_VALUE | -32768 |
int | Integer. MAX_VALUE | 0x7fffffff | Integer.MIN_VALUE | 0x80000000 |
long | Long. MAX_VALUE | 0x7fffffffffffffffL | Long.MIN_VALUE | 0x8000000000000000L |
使用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中的空格 |
字符串与基本数据类型、包装类型转换图
转换为包装类
基本数据类型转换为包装类
javaInteger 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 字符串
字符串是我们在编程中最常使用的一种数据类型,它的表现形式可以分为两种:
- String
- StringBuffer。
字符串不属于8种基本的数据类型,而是一种引用类型。
String对象代表一组不可改变的Unicode字符序列,对它的任何修改实际上又产生一个新的字符串,String类对象的内容一旦被初始化就不能再改变。
字符编码扩展 : https://baike.baidu.com/item/%E5%AD%97%E7%AC%A6%E7%BC%96%E7%A0%81
StringBuffer对象代表一组可改变的Unicode字符序列
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对象中的内容为该对象初始化。
连接操作符“+”,可以将其它各种类型的数据转换成字符串,并前后连接成新的字符串
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) | 测试此字符串是否以指定的后缀结束 |
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节省内存开销
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);
}
}
程序运行结果
"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) | 比较两个日期的相等性。 |
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 日期的年部分
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的实例
- SimpleDateFormat格式说明
字母 | 日期或时间元素 |
---|---|
y | 年 |
M | 年中的月份 |
d | 月份中的天数 |
E | 星期中的天数 |
a | Am/pm 标记 |
H | 一天中的小时数(0-23) |
h | am/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便是一个回文数。编写一个程序,从命令行得到一个整数,判断该数是不是回文数。 [选做题]
答案
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("不是回文数");
}
}
}
