常用类
主要内容
- 封装类
- String类
- StringBuffer和StringBuilder类
- Date类和DateFormat类
- Calendar类
- Math类和Random类
- 枚举
学习目标
知识点 | 要求 |
---|---|
引入封装类 | 理解 |
封装类的使用 | 掌握 |
自动装箱和自动拆箱 | 掌握 |
阅读封装类源码 | 理解 |
String的常用方法 | 掌握 |
阅读String类源码 | 理解 |
理解String的==和equals | 掌握 |
StringBuilder的使用 | 掌握 |
理解StringBuilder的原理 | 理解 |
Date类 | 掌握 |
DateFormat类 | 掌握 |
Calendar类 | 了解 |
Math类 | 了解 |
JDK8的日期类 | 了解 |
Random类 | 了解 |
一. 封装类
1. 封装类引入
1.1 什么是封装类
Java是面向对象的语言,但并不是“纯面向对象”的,因为我们经常用到的基本数据类型就不是对象。但我们在实际应用中经常需要将基本数据转化成对象,以便于操作。
为了解决这个不足,Java在设计类时为每个基本数据类型设计了一个对应的类进行代表,这样八个和基本数据类型对应的类统称为封装类(Wrapper Class)。
8种基本数据类型,分别对应一个封装类。封装类均位于java.lang包
基本数据类型 | 封装类 |
---|---|
byte | Byte |
boolean | Boolean |
short | Short |
char | Character |
int | Integer |
long | Long |
float | Float |
double | Double |
八个类名中,除了Integer和Character类以外,其它六个类的类名和基本数据类型一致,只是类名的第一个字母大写而已
八个类中,除了Character和Boolean以外,其他的都是“数字型“,“数字型”都是java.lang.Number的子类。
public class TestWrapper1 {
int num;
Integer in ;
public static void main(String[] args) {
//封装类的功能
System.out.println(Integer.SIZE);
System.out.println(Integer.MIN_VALUE);
System.out.println(Integer.MAX_VALUE);
System.out.println(Integer.toBinaryString(123));//2进制输出
System.out.println(Integer.toOctalString(123));//8进制输出
System.out.println(Integer.toHexString(123)); //16进制输出
//其他特别重要的功能:可以实现字符串和基本数据类型之间的转换
String str = "123"; //----123
int num2 = Integer.parseInt(str);
System.out.println(num2);
String str2 = "123.45";
double d = Double.parseDouble(str2);
System.out.println(d);
}
}
注意:
1. 封装类的对象需要占用栈内存和堆内存,而基本数据类型的(局部)变量只占用栈内存;基本数据类型的变量占用空间少,更简单,更灵活,更高效。
2. 作为成员变量,默认值不同。int 0;Integer null。
1.2 封装类的优点
-
某些方法的参数必须是对象,为了让基本数据类型的数据能作为参数,提供封装类。
-
封装类还可以提供更多的功能
-
其他特别重要的功能:比如可以实现字符串和基本数据类型之间的转换
2. 封装类的使用
2.1 自动装箱和自动拆箱
自动装箱和拆箱就是将基本数据类型和封装类之间进行自动的互相转换。JDK1.5后,Java引入了自动装箱(autoboxing)/拆箱(unboxing)。
自动装箱:基本类型的数据处于需要对象的环境中时,会自动转为“对象”, 没有必要显式调用valueOf()方法。
自动拆箱:每当需要一个值时,对象会自动转成基本数据类型,没必要显式调用intValue()、doubleValue()等转型方法。
如:
int i = 5; Integer j = i; 该过程就是自动装箱。
Integer i = 5; int j = i; 该过程就是自动拆箱。
我们可以用一句话总结自动装箱/拆箱:
自动装箱过程是通过调用封装类valueOf()方法实现的,而自动拆箱过程是通过调用封装类 xxxValue()方法实现的(xxx代表对应的基本数据类型,如intValue()、doubleValue()等)。
public static void main(String[] args) {
//1.自动装箱
Integer i = 10;
Integer i1 = Integer.valueOf(10);
//2.自动拆箱
Integer j = 10;
int j1 = j;
int j2 = j.intValue();
//2.== equals
Integer in3 = new Integer(56); Integer in4 = new Integer(56);
System.out.println(in3==in4); //false,比较二者引用地址,那肯定不等
System.out.println(in3.equals(in4));//true,比较二者值是否相等,相等
Integer in5 = 25;
Integer in6 = 25;
System.out.println(in5 ==in6);//true 在-128~127之间,直接获取指定值
System.out.println(in5.equals(in6));//true
Integer in7 = 256;
Integer in8 = 256;
System.out.println(in7 ==in8);//false 不在-128~127之间,通过new Integer()创建对象
System.out.println(in7.equals(in8));//true
}
2.2理解Integer源码
重点原码:
public final class Integer extends Number implements Comparable<Integer> {
public static final int MIN_VALUE = 0x80000000;
public static final int MAX_VALUE = 0x7fffffff;
private final int value;
public Integer(int value) {
this.value = value;
}
public int intValue() {
return value;
}
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
}
Integer类提供了一个静态内部类IntegerCache,对于定义一个静态数组cache,长度为256,赋值为-128—127。对于自动装箱时如果是-128—127范围内的数据,直接获取数组的指定值;对于这个范围之外的数据,通过new Integer()重新创建对象。这么做的目的是提高效率。
private static class IntegerCache {
static final int low = -128;
static final int high;
static final Integer cache[];
static {
// high value may be configured by property
int h = 127;
String integerCacheHighPropValue =
VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
if (integerCacheHighPropValue != null) {
try {
int i = parseInt(integerCacheHighPropValue);
i = Math.max(i, 127);
// Maximum array size is Integer.MAX_VALUE
h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
} catch( NumberFormatException nfe) {
// If the property cannot be parsed into an int, ignore it.
}
}
high = h;
cache = new Integer[(high - low) + 1];
int j = low;
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
// range [-128, 127] must be interned (JLS7 5.1.7)
assert IntegerCache.high >= 127;
}
private IntegerCache() {}
}
注意:
1. JDK1.5以后,增加了自动装箱与拆箱功能,如:Integer i = 100; int j = new Integer(100);
2. 自动装箱调用的是valueOf()方法,而不是new Integer()方法。
3. 自动拆箱调用的xxxValue()方法。
4. 封装类在自动装箱时为了提高效率,对于-128~127之间的值会进行缓存处理。超过范围后,对象之间不能再使用==进行数值的比较,而是使用equals方法。
二. 字符串相关类
String类、StringBuilder类、StringBuffer类是三个字符串相关类。String类代表不可变的字符序列,StringBuilder类和StringBuffer类代表可变字符序列。关于这三个类详细的用法,在笔试面试以及实际开发中经常用到,我们必须掌握好它们。
String与StringBuffer可以理解为常量和变量
String对象调用改变自身的方法,本身内容不会发送改变,重新赋值其实是两个对象。
StringBuffer对象调用改变自身的方法,自身内容会改变
1. String类的使用
String类的使用1
public class StringLearning {
public static void main(String[] args) {
//1.创建String对象
String str1 = "雅马哈Ll16";
String str2 = new String("雅马哈Ll16");
System.out.println(str1 == str2); //引用不等
System.out.println(str1.equals(str2)); //值相等
//2.操作String对象
//2.1常用方法
System.out.println(str1.length()); //输出str1的长度,一个中文字的长度也算1
System.out.println(str2.length()); //输出str1的长度,一个中文字的长度也算1
System.out.println(str1.toString()); //输出str1
System.out.println(str2.toString());
System.out.println(str1.startsWith("tj"));//判断str1是不是以tj开头
System.out.println(str2.startsWith("tj"));
System.out.println(str1.endsWith("16"));//判断str1是不是以16结尾
System.out.println(str2.endsWith("16"));
System.out.println(str1.toUpperCase()); //str1中的小写字母转成大写字母
System.out.println(str2.toUpperCase());
System.out.println(str1.toLowerCase()); //str1中的大写字母转成小写字母
System.out.println(str2.toLowerCase());
System.out.println(str1); //经历了上次转大小写,str1的值并没有改变
System.out.println(str2);
//2.2根据索引得到子串
System.out.println(str1.charAt(1)); //输出下标位置为1的字符。下标从0开始
System.out.println(str2.charAt(1)); //输出下标位置为1的字符。下标从0开始
System.out.println(str1.substring(1,4));//输出下标[1,4)字符,马哈L
System.out.println(str1.substring(4));//输出下标[4,最后]
//2.3根据子串得到索引
System.out.println(str1.indexOf("哈"));//输出"哈"的下标,2
System.out.println(str1.indexOf("马哈L"));//从第一个字符开始查找,返回找到的第一个匹配的子串的索引
System.out.println(str1.indexOf("马哈鬼"));//若不存在,则返回-1
System.out.println(str1.lastIndexOf("16"));// 返回"16"在此字符串中最后一次出现处的索引
System.out.println(str1.lastIndexOf("16",6));// 返回"16"在此字符串中最后一次出现处的索引,从指定的索引下标6开始反向搜索。
//2.4其他
byte[] b1 = str1.getBytes(); //将字符串转成byte数组
System.out.println(b1.length);//3*3 + 4*1 = 13,汉字占3byte,字母数字均占1byte
System.out.println(Arrays.toString(b1));
String str3 = new String(b1,9,3); //将byte数组转为字符串。第二个参数offset抵消了前面三个汉字 3*3=9,长度3
System.out.println(str1);
System.out.println(str3); //Ll1
boolean flag = str1.contains("马哈"); //判断str1中是否包含"马哈"
System.out.println(flag);
str1 = str1.concat("航天五院").concat("天津基地").concat("高新7路");//在原str1加上“航天五院天津基地高新7路”
System.out.println(str1);
str1 = str1.replace("航天五院","中国空间技术研究院"); //把str1中“航天五院”更换成“中国空间技术研究院”
System.out.println(str1);
String str4 = " tj bh ";
System.out.println(str4.length());
System.out.println(str4.trim());//返回字符串的副本,忽略前导空白(空格)和尾部空白(空格)。
String str5 = "abcdf";
String str6 = "abcde";
System.out.println(str5.compareTo(str6));//返回正数1,表示str5 > str6,数值1表示f比e大1;同理若返回负数表示str2 > str1
}
}
String类的使用2
public class TestString2 {
public static void main(String[] args) {
String str1 = "bjsxt";
String str2 = "bjsxt";
System.out.println(str1 == str2); //!!!true !!!!!!
System.out.println(str1.equals(str2));//true
String str3 = new String("bjsxt");
String str4 = new String("bjsxt");
System.out.println(str3 == str4); //false
System.out.println(str3.equals(str4));//true
String str5 = "";
String str6 = null;
System.out.println(str5.isEmpty());//true
//System.out.println(str6.isEmpty());//NullPointerException
}
}
toString()方法介绍
对象.toString() : 以字符串输出对象中的内容
toString()方法是 Object 类中的方法,toString() 方法源代码如下:
//(1)getClass().getName() 返回类的全类名(包名+类名)
//(2)Integer.toHexString(hashCode())将对象的hashCode值转成16进制字符串
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
Object类中的toString方法输出的结果是:
包名.类名+@+16进制的哈希值
改写toString()方法
由于 Object 类中的 toString() 方法并不好用,因此很多其他类中都重写了此方法。(子类对父类提供的方法不满意,所以重写以符合自己的需求)
由于toString改写的太多,已经有了固定的格式,直接generate的toString方法源代码:
该改写的toString方法目的是输出对象的属性值。
当直接输出一个对象时,toString方法会被默认的调用。
public String toString() { //重写后,默认一般是把对象的属性值输出
return “Monster{” +
“name='” + name + ‘’’ +
“, job='” + job + ‘’’ +
“, sal=” + sal +
‘}’;}
下面是例子:
package object;
public class ToString {
public static void main(String[] args) {
Monster monster = new Monster("小妖怪", "巡山", 1000);
System.out.println(monster.toString());
System.out.println(monster);
}
}
class Monster{
private String name;
private String job;
private double sal;
public Monster(String name, String job, double sal) {
this.name = name;
this.job = job;
this.sal = sal;
}
//重写toString方法,输出对象的属性
@Override
public String toString() { //重写后,默认一般是把对象的属性值输出
return "Monster{" +
"name='" + name + '\'' +
", job='" + job + '\'' +
", sal=" + sal +
'}';
}
}
输入结果如下:
Monster{name=‘小妖怪’, job=‘巡山’, sal=1000.0}
Monster{name=‘小妖怪’, job=‘巡山’, sal=1000.0}
小结:toString() 方法的作用,就像是介绍一下对象(像 monster 的属性都被说了一遍),一般子类对父类提供的 toString 都不满意,都要进行重写。
方法摘要
char | charAt(int index) 返回指定索引处的 char 值。 |
---|---|
int | compareTo(String anotherString) 按字典顺序比较两个字符串。并返回二者差值,若为正数,则前者大于后者,反之同理 |
String | concat(String str) 将指定字符串连接到此字符串的结尾。 |
boolean | contains(CharSequence s) 当字符串包含指定的 char 值序列时,返回 true。 |
boolean | endsWith(String suffix) 测试此字符串是否以指定的后缀结束。 |
boolean | equals(Object anObject) 将此字符串与指定的对象比较。 |
boolean | equalsIgnoreCase(String anotherString) 将此 String 与另一个 String 比较,不考虑大小写。 |
int | hashCode() 返回此字符串的哈希码。 |
int | indexOf(int ch) 返回指定字符在此字符串中第一次出现处的索引。 |
int | [indexOf](#indexOf(int, int))(int ch, int fromIndex) 返回在此字符串中第一次出现指定字符处的索引,从指定的索引开始搜索。 |
int | indexOf(String str) 返回指定子字符串在此字符串中第一次出现处的索引。 |
int | [indexOf](#indexOf(java.lang.String, int))(String str, int fromIndex) 返回指定子字符串在此字符串中第一次出现处的索引,从指定的索引开始。 |
boolean | isEmpty() 当且仅当 length() 为 0 时返回 true。 |
int | lastIndexOf(int ch) 返回指定字符在此字符串中最后一次出现处的索引。 |
int | [lastIndexOf](#lastIndexOf(int, int))(int ch, int fromIndex) 返回指定字符在此字符串中最后一次出现处的索引,从指定索引处开始进行反向搜索。 |
int | lastIndexOf(String str) 返回指定子字符串在此字符串中最右边出现处的索引。 |
int | [lastIndexOf](#lastIndexOf(java.lang.String, int))(String str, int fromIndex) 返回指定子字符串在此字符串中最后一次出现处的索引,从指定的索引开始反向搜索。 |
int | length() 返回此字符串的长度。 |
String | [replace](#replace(char, char))(char oldChar, char newChar) 返回一个新的字符串,它是通过用 newChar 替换此字符串中出现的所有 oldChar 得到的。 |
String | [replace](#replace(java.lang.CharSequence, java.lang.CharSequence))(CharSequence target, CharSequence replacement) 使用指定的字面值替换序列替换此字符串所有匹配字面值目标序列的子字符串。 |
String | [replaceAll](#replaceAll(java.lang.String, java.lang.String))(String regex, String replacement) 使用给定的 replacement 替换此字符串所有匹配给定的正则表达式的子字符串。 |
String[] | split(String regex) 根据给定正则表达式的匹配拆分此字符串。 |
boolean | startsWith(String prefix) 测试此字符串是否以指定的前缀开始。 |
boolean | [startsWith](#startsWith(java.lang.String, int))(String prefix, int toffset) 测试此字符串从指定索引开始的子字符串是否以指定前缀开始。 |
String | substring(int beginIndex) 返回一个新的字符串,它是此字符串的一个子字符串。 |
String | [substring](#substring(int, int))(int beginIndex, int endIndex) 返回一个新字符串,它是此字符串的一个子字符串。 |
String | toLowerCase() 使用默认语言环境的规则将此 String 中的所有字符都转换为小写。 |
String | toString() 返回此对象本身(它已经是一个字符串!)。 |
String | toUpperCase() 使用默认语言环境的规则将此 String 中的所有字符都转换为大写。 |
String | trim() 返回字符串的副本,忽略前导空白和尾部空白。 |
2. 理解String类源码
String类是一个final类,意味着该类不能再有子类。
String类底层是一个字节数组value。各种方法的操作其实都是对该数组的操作。
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
private final byte[] value;
public String() {
this.value = "".value;
this.coder = "".coder;
}
public String(String original) {
this.value = original.value;
this.coder = original.coder;
this.hash = original.hash;
}
public int length() {
return value.length >> coder();
}
public boolean isEmpty() {
return value.length == 0;
}
public char charAt(int index) {
if (isLatin1()) {
return StringLatin1.charAt(value, index);
} else {
return StringUTF16.charAt(value, index);
}
}
public String toString() {
return this;
}
}
String类的equals()方法其实就是比较底层的字符数组的各个元素是否相同,只要发现一个字符不相同,就返回false。如果所有字符都相同,返回true。但是如果两个变量指向了同一个字符数组,直接返回true。
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String aString = (String)anObject;
if (coder() == aString.coder()) {
return isLatin1() ? StringLatin1.equals(value, aString.value)
: StringUTF16.equals(value, aString.value);
}
}
return false;
}
String类的concat()是创建一个新的字符数组,存放原来字符数组和新加入的字符数组内容,然后以该新数组创建一个新的字符串。
public String concat(String str) {
if (str.isEmpty()) {
return this;
}
if (coder() == str.coder()) {
byte[] val = this.value;
byte[] oval = str.value;
int len = val.length + oval.length;
byte[] buf = Arrays.copyOf(val, len);
System.arraycopy(oval, 0, buf, val.length, oval.length);
return new String(buf, coder);
}
int len = length();
int olen = str.length();
byte[] buf = StringUTF16.newBytesFor(len + olen);
getBytes(buf, 0, UTF16);
str.getBytes(buf, len, UTF16);
return new String(buf, UTF16);
}
3. StringBuffer,StringBuilder类的使用
StringBuffer和StringBuilder非常类似,均代表可变的字符序列。这两个类都是抽象类AbstractStringBuilder的子类,方法与String几乎一模一样。
两个类的主要区别:
1. StringBuffer JDK1.0提供的类,线程安全,做线程同步检查,效率较低。
2. StringBuilder JDK1.5提供的类,线程不安全,不做线程同步检查,因此效率较高。 建议采用该类。
public class TestStringBuilder {
public static void main(String[] args) {
//String----StringBuilder
//StringBuilder builder = new StringBuilder("123");
StringBuffer builder = new StringBuffer("123");
builder.append("321");//在末尾追加子串
builder.append("abc");
builder.append("xyz");
String str =builder.toString();
System.out.println(str);
}
}
注意:
实际开发中StringBuilder的使用场合:字符串的拼接
StringBuffer | append(boolean b) 将 boolean 参数的字符串表示形式追加到序列。 |
---|---|
int | capacity() 返回当前容量。 |
char | charAt(int index) 返回此序列中指定索引处的 char 值。 |
StringBuffer | [delete](#delete(int, int))(int start, int end) 移除此序列的子字符串中的字符。 |
StringBuffer | deleteCharAt(int index) 移除此序列指定位置上的 char。 |
void | ensureCapacity(int minimumCapacity) 确保容量至少等于指定的最小值。 |
int | indexOf(String str) 返回第一次出现的指定子字符串在该字符串中的索引。 |
int | [indexOf](#indexOf(java.lang.String, int))(String str, int fromIndex) 从指定的索引处开始,返回第一次出现的指定子字符串在该字符串中的索引。 |
StringBuffer | [insert](#insert(int, boolean))(int offset, boolean b) 将 boolean 参数的字符串表示形式插入此序列中。 |
int | lastIndexOf(String str) 返回最右边出现的指定子字符串在此字符串中的索引。 |
int | [lastIndexOf](#lastIndexOf(java.lang.String, int))(String str, int fromIndex) 返回最后一次出现的指定子字符串在此字符串中的索引。 |
int | length() 返回长度(字符数)。 |
StringBuffer | [replace](#replace(int, int, java.lang.String))(int start, int end, String str) 使用给定 String 中的字符替换此序列的子字符串中的字符。 |
StringBuffer | reverse() 将此字符序列用其反转形式取代。 |
String | substring(int start) 返回一个新的 String,它包含此字符序列当前所包含字符的子序列。 |
String | [substring](#substring(int, int))(int start, int end) 返回一个新的 String,它包含此序列当前所包含字符的子序列。 |
String | toString() 返回此序列中数据的字符串表示形式。 |
注意:
-
String:不可变字符序列。
-
StringBuffer:可变字符序列,并且线程安全,但是效率低。
-
StringBuilder:可变字符序列,线程不安全,但是效率高(推荐使用)。
三. 日期类
“时间如流水,一去不复返”,时间是一个一维的东西。所以,我们需要一把刻度尺来表达和度量时间。在计算机世界,我们把1970 年 1 月 1 日 00:00:00定为基准时间,每个度量单位是毫秒(1秒的千分之一)
如图所示:
我们用long类型的变量来表示时间,从基准时间往前几亿年,往后几亿年都能表示。如果想获得现在时刻的“时刻数值”,可以使用:
long now = System.currentTimeMillis();
这个“时刻数值”是所有时间类的核心值,年月日都是根据这个“数值”计算出来的。
我们工作学习涉及的时间相关类有如下这些:
1. Date类
在标准Java类库中包含一个Date类。它的对象表示一个特定的瞬间,精确到毫秒。在网上商城下单时,在对报销单进行审核时,都需要获取当前的时间,通过Date类就可以完成。
1.1 Date类的使用
public static void main(String[] args) {
//获取当前的时间
Date now = new Date();
//输出当前的时间
System.out.println(now.toString());
System.out.println(now.toLocaleString());
System.out.println(now.getYear()); // 1900+122=2022
System.out.println(now.getMonth());// 0---11
System.out.println(now.getDate());//日
//星期几 星期日是0,一周是从星期日开始
System.out.println(now.getDay());
System.out.println(now.getHours());
System.out.println(now.getMinutes());
System.out.println(now.getSeconds());
//其他的方法
long l = now.getTime();
// 1970年1月1日 00:00:00 GMT以来的毫秒数。
System.out.println(l);
System.out.println(System.currentTimeMillis());
//java.sql.Date
java.sql.Date date = new java.sql.Date(System.currentTimeMillis());
System.out.println(date);
java.sql.Date date1 = java.sql.Date.valueOf("2022-1-1");
System.out.println(date1);
//java.sql.Date 转化为 java.util.Date
java.sql.Date date2 = new java.sql.Date(System.currentTimeMillis());
Date date3 = new Date(date2.getTime());
//java.util.Date 转化为 java.sql.Date
java.sql.Date date4 = new java.sql.Date(date3.getTime());
}
查看API文档大家可以看到其实Date类中的很多方法都已经过时了。JDK1.1之前的Date包含了:日期操作、字符串转化成时间对象等操作。JDK1.1之后,日期操作一般使用Calendar类,而字符串的转化使用DateFormat类。
1.2 理解Date类的源码
public class Date
implements java.io.Serializable, Cloneable, Comparable<Date>{
//表示相应时间对应的毫秒数
private transient long fastTime;
public Date() {
this(System.currentTimeMillis());
}
public Date(long date) {
fastTime = date;
}
public long getTime() {
return getTimeImpl();
}
private final long getTimeImpl() {
if (cdate != null && !cdate.isNormalized()) {
normalize();
}
return fastTime;
}
}
2. DateFormat类
DateFormat是一个抽象类,一般使用它的的子类SimpleDateFormat类来实现。主要作用就是把时间对象转化成指定格式的字符串。反之,把指定格式的字符串转化成时间对象。
需求1:网页注册,需要输入日期,在网页上输入的所有内容,xiaoming,23, 1999-12-23,1999/12/23,但是传送到后台接收到都是字符串 “xiaoming”, “23”, “1999-12-23”,“1999/12/23”,需要把字符串----->日期
需求2:注册成功后,在网页上显示日期,可以不同格式来显示"1999-12-23", “1999/12/23”,“1999年12月23日”,需要把日期----->字符串。
2.1 DateFormat类的使用
public class DateFormatLearning {
public static void main(String[] args) {
String str1 = "1999-12-23 09:23:45";
Date date = null;
try {
//把String类型转成Date类型
date = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").parse(str1);
} catch (ParseException e) {
e.printStackTrace();
}
System.out.println(date.toString());
System.out.println(date.toLocaleString());
System.out.println(new SimpleDateFormat("yyyy年MM月dd日 hh时mm分ss秒").format(date));
}
}
3. 日期和时间的表示
字母 | 日期或时间元素 | 表示 | 示例 |
---|---|---|---|
G | Era 标志符 | Text | AD |
y | 年 | Year | 1996; 96 |
M | 年中的月份 | Month | July; Jul; 07 |
w | 年中的周数 | Number | 27 |
W | 月份中的周数 | Number | 2 |
D | 年中的天数 | Number | 189 |
d | 月份中的天数 | Number | 10 |
F | 月份中的星期 | Number | 2 |
E | 星期中的天数 | Text | Tuesday; Tue |
a | Am/pm 标记 | Text | PM |
H | 一天中的小时数(0-23) | Number | 0 |
k | 一天中的小时数(1-24) | Number | 24 |
K | am/pm 中的小时数(0-11) | Number | 0 |
h | am/pm 中的小时数(1-12) | Number | 12 |
m | 小时中的分钟数 | Number | 30 |
s | 分钟中的秒数 | Number | 55 |
S | 毫秒数 | Number | 978 |
z | 时区 | General time zone | Pacific Standard Time; PST; GMT-08:00 |
Z | 时区 | RFC 822 time zone | -0800 |
4. Calendar类
Calendar 类是一个抽象类,为我们提供了关于日期计算的相关功能,比如:年、月、日、时、分、秒的展示和计算。GregorianCalendar 是 Calendar 的一个具体子类,提供了世界上大多数国家/地区使用的标准日历系统。
public static void main(String[] args) {
//创建Calendar对象
Calendar cal = new GregorianCalendar();
//输出日期中的各个部分
System.out.println(cal.get(Calendar.YEAR));
System.out.println(cal.get(Calendar.MONTH));
System.out.println(cal.get(Calendar.DATE));
System.out.println(cal.get(Calendar.HOUR));
System.out.println(cal.get(Calendar.MINUTE));
System.out.println(cal.get(Calendar.SECOND));
System.out.println(cal.get(Calendar.DAY_OF_WEEK));//一周中的第几天
//一个月中最大的天数
System.out.println(cal.getActualMaximum(Calendar.DATE));
//修改日期中各个部分
cal.set(Calendar.YEAR,2000);
cal.set(Calendar.MONTH,1);
cal.set(Calendar.DATE,1);
//Date--Calendar之间的转换
//Date ---->Calendar
Date now = new Date();
cal.setTime(now);
//Calendar---->Date
Date now2 = cal.getTime();
}
3.4.1 使用Calendar类实现万年历的功能
public static void main(String[] args) throws ParseException {
Scanner sc = new Scanner(System.in);
//1.提示语句
System.out.println("请输入日期, 格式为 2020-10-10");
//2.接收用户输入的日期(字符串)
String next = sc.next();
//3.将字符串日期转换为Date类型 SimpleDateFormat
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date date = sdf.parse(next); //Date类型
// System.out.println(date);
//4.操作日期 -> 日历类Calendar
GregorianCalendar calendar = new GregorianCalendar();
//将date类型的日期设置到calendar中
calendar.setTime(date);
//5.展示用户输入的月份和日期
int month = calendar.get(Calendar.MONTH) + 1;
int day = calendar.get(Calendar.DATE);
System.out.println(month + "月 " + day + "日");
//6.计算出用户输入的月份一共有多少天
int maxDay = calendar.getActualMaximum(Calendar.DATE);
//7.存储用户输入的日(目的: 将用户输入的日红色标注)
int oldDay = calendar.get(Calendar.DATE);
//8.将日历对象中的日期设置为1号(目的: 方便 换行等操作)
calendar.set(Calendar.DATE, 1);
//9.展示星期
System.out.println("日\t一\t二\t三\t四\t五\t六");
//10.获取1号为一周的第几天
int i1 = calendar.get(Calendar.DAY_OF_WEEK);
for (int i = 1; i < i1; i++) {
System.out.print("\t");
}
//11.遍历展示所有的日
for (int i = 0; i < maxDay; i++) {
if (oldDay == calendar.get(Calendar.DATE)) {
System.out.print(calendar.get(Calendar.DATE) + "!\t");
} else {
System.out.print(calendar.get(Calendar.DATE) + "\t");
}
//判断当前的日期是否为周六, 如果为周六换行
if (calendar.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY) {
System.out.println();
}
//日 +1
calendar.add(Calendar.DATE, 1);
}
}
四. 其他常用类
1. Math类
java.lang.Math提供了一系列静态方法用于科学计算;其方法的参数和返回值类型一般为double型。如果需要更加强大的数学运算能力,计算高等数学中的相关内容,可以使用apache commons下面的Math类库。
public static void main(String[] args) {
System.out.println(Math.PI);
System.out.println(Math.round(3.14));//四舍五入去掉小数点
System.out.println(Math.ceil(3.14));//向上取整,变成4.0
System.out.println(Math.floor(3.14));//向下取整,变成3.0
System.out.println(Math.sqrt(64));//开平方 得8.0
System.out.println(Math.pow(2,5));//幂 2^5 = 32
System.out.println(Math.abs(-5));//绝对值
System.out.println(Math.max(30,40));//最大值
System.out.println(Math.min(30,40));//最小值
System.out.println(Math.random());//[0.0,1.0)
}
2. Random类
Math类中虽然为我们提供了产生随机数的方法Math.random(),但是通常我们需要的随机数范围并不是[0, 1)之间的double类型的数据,这就需要对其进行一些复杂的运算。如果使用Math.random()计算过于复杂的话,我们可以使用例外一种方式得到随机数,即Random类,这个类是专门用来生成随机数的,并且Math.random()底层调用的就是Random的nextDouble()方法。
使用Random生成[10,40)之间的随机正数
public static void main(String[] args) {
//Random rand = new Random(10000);
Random rand = new Random();
System.out.println(rand.nextInt());
System.out.println(rand.nextInt(10));
System.out.println(rand.nextDouble());
System.out.println(rand.nextFloat());
for (int i = 0; i < 10; i++) {
System.out.print(rand.nextInt(10)+" ");
}
}
构造方法摘要
Random() | 创建一个新的随机数生成器。 |
---|---|
Random(long seed) | 使用单个 long 种子创建一个新的随机数生成器。 |
3. 枚举
JDK1.5引入枚举类型。枚举类型的定义包括枚举声明和枚举体。枚举体就是放置一些常量。
定义枚举要使用enum关键字。对于性别、季节、星期几等内容,如果定义为字符串类型,是很难限制其取值的。采用枚举可以轻松解决该问题。
3.1 性别
- 定义和使用性别枚举类
public enum Gender {
男,女
}
- 自定义类型
public class Person {
String name;
//String sex;
Gender sex; //枚举类型
int age;
}
- 测试
public static void main(String[] args) {
Person person = new Person();
person.sex = Gender.男;
System.out.println(person.getSex());
}
3.2 季节
- 定义枚举类型
public enum Season {
春,夏,秋,冬
}
- 使用枚举类型
public static void main(String[] args) {
Season season = Season.夏;
switch(season){
case 春 :
System.out.println("春暖花开 踏青 春游");
break;
case 夏 :
System.out.println("夏日炎炎 吃雪糕 游泳");
break;
case 秋 :
System.out.println("秋高气爽 收庄稼 赏月");
break;
case 冬 :
System.out.println("冬雪皑皑 泡温泉 打雪仗");
break;
}
}
3.3 总结
所有的枚举类型隐性地继承自 java.lang.Enum。枚举实质上还是类!而每个被枚举的成员实质就是一个枚举类型的实例,他们默认都是public static final修饰的。可以直接通过枚举类型名使用它们。
注意: 需要定义一组常量时,推荐使用枚举类型;