Java基础 - 实用类


枚举

枚举(Enum)是一种由确定取值区间的数据类型,其本质是一种类,具有简洁、安全、方便等特点。枚举的值被约束到一个特定的范围,只能取这个范围以内的值。

枚举的定义与类很相似,实用enum关键字来描述,语法如下。需要注意的是枚举中的常量实用逗号进行分割。

public enum Week {
    MONDAY,TUESDAY,WEDNESDAY,THURSDAY,FRIDAY,SATURDAY,SUNDAY;
}

枚举中的每一个常量都对应的是一个枚举实例,只不过表示的含义不同。拿上面这个例子来说,Java在编译期会帮我们生成一个 Week 类,并且继承自java.lang.Enum,被 final 修饰,表示该类不可被继承。同时还生成了7个 Week 的实例对象分别对应枚举中定义的7个日期,因为枚举的静态常量直接对应其实例化对象,所以对于枚举的使用如下所示。

public class Main {
    public static void main(String[] args) {
        System.out.println(Week.MONDAY);
    }
}

Math

Math类为开发者提供了一系列的数学方法,同时还提供了两个静态常量E(自然对数的底数)和 PI(圆周率)。Math类中的所有方法全部都是静态的,通过类名直接调用。使用方法如下所示。

public class Main {
    public static void main(String[] args) {
        System.out.println("圆周率 = " + Math.PI);
        System.out.println("自然常数 = " + Math.E);
        System.out.println("9的平方根 = " + Math.sqrt(9));
        System.out.println("64的立方根 = " + Math.cbrt(64));
        System.out.println("2的4次方 = " + Math.pow(2,4));
        System.out.println("两数中的最大数:" + Math.max(10,20));
        System.out.println("两数中的最小数:" + Math.min(10,20));
        System.out.println("-10.5的绝对值 = " + Math.abs(-10.5));
        System.out.println("大于10.01的最大整数" + Math.ceil(10.01));
        System.out.println("小于10.99的最小整数" + Math.floor(10.99));
        System.out.println("随机数" + Math.random());
        System.out.println("5.6四舍五入:" + Math.rint(5.6));
        System.out.println("5.6f 四舍五入:" + Math.round(5.6f));
        System.out.println("5.6四舍五入:" + Math.round(5.6));
    }
}
// 输出
圆周率 = 3.141592653589793
自然常数 = 2.718281828459045
9的平方根 = 3.0
64的立方根 = 4.0
24次方 = 16.0
两数中的最大数:20
两数中的最小数:10
-10.5 的绝对值 = 10.5
大于10.01的最大整数11.0
小于10.99的最小整数10.0
随机数0.7027884654726971
5.6 四舍五入:6.0
5.6f 四舍五入:6
5.6 四舍五入:6

Random

Random 是用来产生一个随机数的类,并且可以任意指定一个区间,在此区间内产生一个随机数。

方法 描述
public Random() 创建一个无参的随机数构造器,使用系统时间(ms)作为默认种子
public Random(long seed) 使用long数据类型的种子创建一个随机数构造器
public boolean nextBoolean() 返回下一个伪随机数,它取自此随机数生成器序列的boolean值
public double nextDouble() 返回下一个伪随机数,它取自此随机数生成器序列的,在0.0 和 1.0 之间均匀分布的double值
public float nextFloat() 返回下一个伪随机数,它取自此随机数生成器序列的,在0.0 和 1.0 之间均匀分布的float值
public int nextInt() 返回下一个伪随机数,它取自此随机数生成器的序列中均匀分布的int值(int取值范围内)
public int nextInt(int n) 返回下一个伪随机数,它取自此随机数生成器序列的,在 0 和 n 之间均匀分布的int值
public long nextLong() 返回下一个伪随机数,它取自此随机数生成器的序列中均匀分布的long值(long取值范围内)
public synchronized void setSeed(long sedd) 使用单个long种子设置此随机数生成器的种子
public class Main {
    public static void main(String[] args) {
        Random random = new Random();
        for (int i = 0; i < 3; i++) {
            System.out.println("第" + i + "个 boolean 随机数:" + random.nextBoolean());
        }
        System.out.println(" ");
        for (int i = 0; i < 3; i++) {
            System.out.println("第" + i + "个 double 随机数:" + random.nextDouble());
        }
        System.out.println(" ");
        for (int i = 0; i < 3; i++) {
            System.out.println("第" + i + "个 float 随机数:" + random.nextFloat());
        }
        System.out.println(" ");
        for (int i = 0; i < 3; i++) {
            System.out.println("第" + i + "个 int 随机数:" + random.nextInt());
        }
        System.out.println(" ");
        for (int i = 0; i < 3; i++) {
            System.out.println("第" + i + "个 int 随机数:" + random.nextInt(100));
        }
        System.out.println(" ");
        for (int i = 0; i < 3; i++) {
            System.out.println("第" + i + "个 long 随机数:" + random.nextLong());
        }
    }
}

// 输出0boolean 随机数:false1boolean 随机数:true2boolean 随机数:false0double 随机数:0.55821851211667581double 随机数:0.15187927052628282double 随机数:0.362106952411382130float 随机数:0.343937341float 随机数:0.341969972float 随机数:0.194098230int 随机数:4133902151int 随机数:9797536802int 随机数:18397874330int 随机数:581int 随机数:202int 随机数:450long 随机数:64571046260973179211long 随机数:81034793635595815862long 随机数:-8593379668973925522

String

String是开发中使用频率很高的类,Java通过String类来创建和操作字符串数据。

String实例化

String类对象的实例化方式有两种,第一种是直接赋值的方式,第二种是通过构造函数创建实例化对象的方式。

public class Main {
    public static void main(String[] args) {
        // 第一种方式
        String str1 = "hello";
        // 第二种方式
        String str2 = new String("hello");
        System.out.println(str1);
        System.out.println(str2);
    }
}

// 输出
hello
hello

通过下面的代码比较两种方式的不同。

public class Main {
    public static void main(String[] args) {
        String str1 = "hello";
        String str2 = "hello";
        String str3 = new String("hello");
        String str4 = new String("hello");
        System.out.println(str1 == str2);
        System.out.println(str3 == str4);
    }
}
// 输出
true
false

通过运行结果可以发现,str1所引用的内存地址和str2所引用的内存地址相同,即str1和str2指向堆内存中的同一块位置。而str3和str4则指向堆内存中不同的位置。

造成这两种不同情况的原因是:第一种直接赋值的方式如“String str1 = “hello””,会首先在栈内存中开辟一块空间来保存变量str1,同时在堆内存中开辟一块空间存储“hello”,然后将堆内存的地址赋给栈内存中的str1,即str1存储的是“hello”的内存地址。Java同时在堆内存中提供一个字符串常量池,专门用来存储String类型的对象。在实例化一个String对象时,首先会在字符串常量池中查找 如果该字符已经创建,则直接返回它的内存地址。如果字符串常量池不存在该字符串,就先创建再返回,即字符串常量池中不会创建重复的字符串对象。所有第一种创建的方式返回值是true。字符串常量池只适用于直接赋值的方式。

第二种创建对象的方式底层原理则是:通过构造函数创建对象会在堆内存中开辟对应的空间来存储,通过 new String(“hello”) 和 new String(“hello”) 创建了两个对象,虽然值相等,但是会开辟两块内存空间来存储。所有内存地址是不同的。

String字符串通过 “==” 是判断两个字符串对象的内存地址是否相等。判断两个字符串对象的值是否相等,可以调用String的 equals()方法。

public class Main {
    public static void main(String[] args) {
        String str3 = new String("hello");
        String str4 = new String("hello");
        System.out.println(str3.equals(str4));
    }
}
// 输出
true

实际上 String 类在存储字符串时,会将字符串的值保存在byte类型的数组中,数组一旦创建,其长度就是不可改变的。既然长度不可改变,也就意味着byte类型所存储的字符串值不可修改。一旦修改,就会重新创建一个 String 对象,用新对象的byte数组来存储修改之后的字符串。即如果修改了String对象的值,它就已经不是之前的对象了,而是一个新的对象。

public class Main {
    public static void main(String[] args) {
        String str3 = new String("hello");
        String str4 = new String("hello");
        System.out.println("修改前str3的内存地址:" + System.identityHashCode(str3));
        System.out.println("修改前str4的内存地址:" + System.identityHashCode(str4));
        str3 += "world";
        System.out.println("修改后str3的内存地址:" + System.identityHashCode(str3));
        System.out.println("修改后str4的内存地址:" + System.identityHashCode(str4));
    }
}
// 输出
修改前str3的内存地址:1956725890
修改前str4的内存地址:356573597
修改后str3的内存地址:1735600054
修改后str4的内存地址:356573597
方法 描述
public String() 创建一个值为空的对象
public String(String str) 创建一个值为str的对象
public String(char value[]) 将一个char型数组转为字符串对象
public String(char value[], int offset, int count) 将一个指定范围的char型数组转为字符串对象
public String(byte[] bytes) 将一个byte型数组转为字符串对象
public String(byte[] bytes, int offset, int length) 将一个指定范围的byte型数组转为字符串对象
public int length() 返回字符串的长度
public boolean isEmpty() 判断字符串是否为空
public char charAt(int index) 返回字符串中指定位置的字符
public byte[] getBytes() 将字符串转为byte型数组
public boolean equals(Object anObject) 判断两个字符串是否相等
public boolean equalsIgnoreCase(String anotherString) 判断两个字符串是否相等并且忽略大小写
public int compareTo(String anotherString) 对两个字符串进行排序
public boolean startsWith(String prefix) 判断是否以指定的值开头
public boolean endsWith(String suffix) 判断是否以指定的值结尾
public int hashCode() 获取字符串的散列值
public int indexOf(String str) 从头开始查找指定字符的位置
public int indexOf(String str, int fromIndex) 从指定位置开始查找指定字符的位置
public String substring(int beginIndex) 截取字符串从指定位置开始到结尾
public String substring(int beginIndex, int endIndex) 截取字符串从指定位置开始到指定位置结束
public String concat(String str) 追加字符串
public String replaceAll(String regex, String replacement) 替换字符串
public String[] split(String regex) 用指定的字符串对目标字符进行分割,返回数组
public String toLowerCase() 将字符串转为小写
public String toUpperCase() 将字符串转为大写
public char[] toCharArray() 将字符串转为char型数组

StringBuffer

String的底层是用数组来存值的,如果开发中需要对某个字符串进行频繁的修改,由于数组长度不可改变,所以使用String就不合适了,会造成内存空间的浪费。因此可以使用StringBuffer来解决这个问题。

StringBuffer 和 String 类似,底层也是用一个数组来存储字符串的值,并且数组的默认长度为16,即一个空的StringBuffer对象,数组长度为16。

当我们调用有参构造创建一个StringBuffer对象时,数组长度就不是16了,而是根据当前对象的值来决定数组的长度,“值得长度 + 16”作为数组得长度。

所以一个 StringBuffer 创建完成之后,有16字节的空间可以对其值进行修改。如果修改的值范围超出了16字节,则调用ensureCapacityInternal()方法继续对底层数组进行扩容,并且保持引用不变。

public class Main {
    public static void main(String[] args) {
        StringBuffer str3 = new StringBuffer("hello");
        StringBuffer str4 = new StringBuffer("hello");
        System.out.println("修改前str3的内存地址:" + System.identityHashCode(str3));
        System.out.println("修改前str4的内存地址:" + System.identityHashCode(str4));
        str3.append("world");
        System.out.println("修改后str3的内存地址:" + System.identityHashCode(str3));
        System.out.println("修改后str4的内存地址:" + System.identityHashCode(str4));
    }
}
// 输出
修改前str3的内存地址:1956725890
修改前str4的内存地址:356573597
修改后str3的内存地址:1956725890
修改后str4的内存地址:356573597

StringBuffer 常用方法如下

方法 描述
public StringBuffer() 无参构造,创建一个空得 StringBuffer
public StringBuffer(String str) 有参构造
public synchronized int length() 返回StringBuffer的长度
public synchronized char charAt(int index) 返回字符串中指定位置的字符
public synchronized StringBuffer append(String str) 追加字符
public synchronized StringBuffer delete(int start, int end) 删除指定区间内的字符串
public synchronized StringBuffer deleteCharAt(int index) 删除指定位置的字符
public synchronized StringBuffer replace(int start, int end, String str) 将指定区间内的值替换为str
public synchronized String substring(int start) 截取字符串从指定位置开始到结尾
public synchronized String substring(int start, int end) 截取字符串从指定位置开始到指定位置结束
public synchronized StringBuffer insert(int offset, String str) 向指定位置插入str
public int indexOf(String str) 从头开始查找指定字符的位置
public int indexOf(String str, int fromIndex) 从指定的位置开始查找指定字符的位置
public synchronized StringBuffer reverse() 进行反转
public synchronized String toString() 返回StringBuffer对应的String

日期类

实际开发中对日期的使用是必不可少的,Java对日期的使用也提供了良好的封装,主要包括java.util.Date和java.util.Calendar。

Date

Date类直接通过构造函数实例化其对象即可。Date对象表示当前的系统时间。

public class Main {
    public static void main(String[] args) {
        Date date = new Date();
        System.out.println(date);
    }
}

从运行结果可以看到,已经获取了当前的系统时间,但是显示的格式并不符合我们平时使用的格式,可以通过 java.text.SimpleDateFormat类对 Date对象进行格式化,将日期格式转换为熟悉的格式。

标记 描述
y 年,yyyy表示 4 位数的年份信息
M 月,MM表示 2 位数的月份信息
m 分钟,mm表示 2 位数的分钟信息
d 天,dd表示 2 位数的天信息
H 小时,HH表示 2 位数的 24 小时制下的小时信息
h 小时,hh表示 2 位数的 12 小时制下的小时信息
s 秒,ss表示 2 位数的秒信息
S 毫秒,SSS表示 3 位数的毫秒信息。
public class Main {
    public static void main(String[] args) {
        Date date = new Date();
        System.out.println(date);
        // 格式化时间
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
        System.out.println(simpleDateFormat.format(date));
    }
}

Calendar

通过Date类可以获取当前系统时间,如果想要对日期数据进行逻辑操作,例如计算从当前时间算起15天后的日期是几月几号,Date是没有办法实现的。因此可以通过Calendar类来完成日期数据的逻辑运算。

使用Calendar进行日期运算的基本思路是先将日期数据赋给Calendar,再调用Calendar的方法完成相关运算。Calendar类提供了很大静态常量,用来记录日期数据。

常量 描述
public static final int YEAR
public static final int MONTH
public static final int DAY_OF_MONTH 天,以月为单位,即当天是该月中的第几天
public static final int DAY_OF_YEAR 天,以年为单位,即当天是该年中第几天
public static final int HOUR_OF_DAY 小时
public static final int MINUTE 分钟
public static final int SECOND
public static final int MILLISECOND 毫秒

Calendar常用方法

方法 描述
public static Calendar getInstance() 获取系统对应的Calendar实例化对象
public void set(int field, int value 给静态常量赋值
public int get(int field) 取出静态常量
public final Date getTime() 获取Calendar对应的Date对象
public class Main {
    public static void main(String[] args) {
        Calendar calendar = Calendar.getInstance();
        // 判断某一天在一年中属于第几天
        calendar.set(Calendar.YEAR, 2000);
        calendar.set(Calendar.MONTH, 11);   // 1月为0,12月为11
        calendar.set(Calendar.DAY_OF_MONTH, 31);
        int day = calendar.get(Calendar.DAY_OF_YEAR);
        System.out.println("2000年12月31日是所在年的第 " + day + " 天");

        // 计算2000年12月31日往后推12天的日期
        calendar.set(Calendar.DAY_OF_YEAR, calendar.get(Calendar.DAY_OF_YEAR) + 12);
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        System.out.println("12天后的日期:" + simpleDateFormat.format(calendar.getTime()));

        // 计算2001年1月12日往前推10天的日期
        calendar.set(Calendar.DAY_OF_YEAR, calendar.get(Calendar.DAY_OF_YEAR) - 10);
        System.out.println("12天前的日期:" + simpleDateFormat.format(calendar.getTime()));
    }
}
// 输出
20001231日是所在年的第 36612天后的日期:2001-01-12
12天前的日期:2001-01-02

文章作者: zerollone
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 zerollone !
  目录