Java基础类库

Java基础类库

使用Scanner获得键盘输入:

public class ScannerKeyBoardTest
{
    public static void main(String[] args)
    {
        // System.in代表标准输入,就是键盘输入
        Scanner sc = new Scanner(System.in);
        // 增加下面一行将只把回车作为分隔符
        // sc.useDelimiter("\n");
        // 判断是否还有下一个输入项
        while(sc.hasNext())
        {
            // 输出输入项
            System.out.println("键盘输入的内容是:"
                + sc.next());
        }
    }
}

读取文件内容:

public class ScannerFileTest
{
    public static void main(String[] args)
        throws Exception
    {
        // 将一个File对象作为Scanner的构造器参数,Scanner读取文件内容
        Scanner sc = new Scanner(new File("ScannerFileTest.java"));
        System.out.println("ScannerFileTest.java文件内容如下:");
        // 判断是否还有下一行
        while(sc.hasNextLine())
        {
            // 输出文件中的下一行
            System.out.println(sc.nextLine());
        }
    }
}

System类:

通过System类访问操作的环境变量和系统属性:

public class SystemTest
{
    public static void main(String[] args) throws Exception
    {
        // 获取系统所有的环境变量
        Map<String,String> env = System.getenv();
        for (String name : env.keySet())
        {
            System.out.println(name + " ---> " + env.get(name));
        }
        // 获取指定环境变量的值
        System.out.println(System.getenv("JAVA_HOME"));
        // 获取所有的系统属性
        Properties props = System.getProperties();
        // 将所有系统属性保存到props.txt文件中
        props.store(new FileOutputStream("props.txt")
                , "System Properties");
        // 输出特定的系统属性
        System.out.println(System.getProperty("os.name"));
    }
}

通过 identityHashCode 判断是否同一个对象:

public class IdentityHashCodeTest
{
    public static void main(String[] args)
    {
        // 下面程序中s1和s2是两个不同对象
        String s1 = new String("Hello");
        String s2 = new String("Hello");
        // String重写了hashCode()方法——改为根据字符序列计算hashCode值,
        // 因为s1和s2的字符序列相同,所以它们的hashCode方法返回值相同
        System.out.println(s1.hashCode()
                + "----" + s2.hashCode());
        // s1和s2是不同的字符串对象,所以它们的identityHashCode值不同
        System.out.println(System.identityHashCode(s1)
                + "----" + System.identityHashCode(s2));
        String s3 = "Java";
        String s4 = "Java";
        // s3和s4是相同的字符串对象,所以它们的identityHashCode值相同
        System.out.println(System.identityHashCode(s3)
                + "----" + System.identityHashCode(s4));
    }
}

Runtime类代表java程序运行时环境:

public class RuntimeTest
{
    public static void main(String[] args)
    {
        // 获取Java程序关联的运行时对象
        Runtime rt = Runtime.getRuntime();
        System.out.println("处理器数量:"
                + rt.availableProcessors());
        System.out.println("空闲内存数:"
                + rt.freeMemory());
        System.out.println("总内存数:"
                + rt.totalMemory());
        System.out.println("可用最大内存数:"
                + rt.maxMemory());
    }
}

Runtime类可以直接单独启动一个进程来运行操作系统的命令:

public class ExecTest
{
    public static void main(String[] args)
            throws Exception
    {
        Runtime rt = Runtime.getRuntime();
        // 运行记事本程序
        rt.exec("notepad.exe");
    }
}

通过 ProcessHandle (Java 9) 获取进程的相关信息:

import java.util.concurrent.*;

public class ProcessHandleTest
{
    public static void main(String[] args)
        throws Exception
    {
        Runtime rt = Runtime.getRuntime();
        // 运行记事本程序
        Process p = rt.exec("notepad.exe");
        ProcessHandle ph = p.toHandle();
        System.out.println("进程是否运行: " + ph.isAlive());
        System.out.println("进程ID: " + ph.pid());
        System.out.println("父进程: " + ph.parent());
        // 获取ProcessHandle.Info信息
        ProcessHandle.Info info = ph.info();
        // 通过ProcessHandle.Info信息获取进程相关信息
        System.out.println("进程命令: " + info.command());
        System.out.println("进程参数: " + info.arguments());
        System.out.println("进程启动时间: " + info.startInstant());
        System.out.println("进程累计运行时间: " + info.totalCpuDuration());
        // 通过CompletableFuture在进程结束时运行某个任务
        CompletableFuture<ProcessHandle> cf = ph.onExit();
        cf.thenRunAsync(()->{
            System.out.println("程序退出");
        });
        Thread.sleep(5000);
    }
}

常用类:

Object类:

调用Object实现的clone()方法来得到给对象的副本,并返回该副本。如下实现“自我克隆”:

/**
 * Description:
 * 网站: <a href="http://www.crazyit.org">疯狂Java联盟</a><br>
 * Copyright (C), 2001-2018, Yeeku.H.Lee<br>
 * This program is protected by copyright laws.<br>
 * Program Name:<br>
 * Date:<br>
 * @author Yeeku.H.Lee kongyeeku@163.com
 * @version 1.0
 */

class Address
{
    String detail;
    public Address(String detail)
    {
        this.detail = detail;
    }
}
// 实现Cloneable接口
class User implements Cloneable
{
    int age;
    Address address;
    public User(int age)
    {
        this.age = age;
        address = new Address("广州天河");
    }
    // 通过调用super.clone()来实现clone()方法
    public User clone()
        throws CloneNotSupportedException
    {
        return (User)super.clone();
    }
}
public class CloneTest
{
    public static void main(String[] args)
        throws CloneNotSupportedException
    {
        User u1 = new User(29);
        // clone得到u1对象的副本。
        User u2 = u1.clone();
        // 判断u1、u2是否相同
        System.out.println(u1 == u2);      //①
        // 判断u1、u2的address是否相同
        System.out.println(u1.address == u2.address);     //②
    }
}

Java7新增的Objects类:

public class ObjectsTest
{
    // 定义一个obj变量,它的默认值是null
    static ObjectsTest obj;
    public static void main(String[] args)
    {
        // 输出一个null对象的hashCode值,输出0
        System.out.println(Objects.hashCode(obj));
        // 输出一个null对象的toString,输出null
        System.out.println(Objects.toString(obj));
        // 要求obj不能为null,如果obj为null则引发异常
        System.out.println(Objects.requireNonNull(obj
                , "obj参数不能是null!"));
    }
}

Math类:

public class MathTest
{
    public static void main(String[] args)
    {
        /*---------下面是三角运算---------*/
        // 将弧度转换角度
        System.out.println("Math.toDegrees(1.57):"
                + Math.toDegrees(1.57));
        // 将角度转换为弧度
        System.out.println("Math.toRadians(90):"
                + Math.toRadians(90));
        // 计算反余弦,返回的角度范围在 0.0 到 pi 之间。
        System.out.println("Math.acos(1.2):" + Math.acos(1.2));
        // 计算反正弦;返回的角度范围在 -pi/2 到 pi/2 之间。
        System.out.println("Math.asin(0.8):" + Math.asin(0.8));
        // 计算反正切;返回的角度范围在 -pi/2 到 pi/2 之间。
        System.out.println("Math.atan(2.3):" + Math.atan(2.3));
        // 计算三角余弦。
        System.out.println("Math.cos(1.57):" + Math.cos(1.57));
        // 计算值的双曲余弦。
        System.out.println("Math.cosh(1.2 ):" + Math.cosh(1.2 ));
        // 计算正弦
        System.out.println("Math.sin(1.57 ):" + Math.sin(1.57 ));
        // 计算双曲正弦
        System.out.println("Math.sinh(1.2 ):" + Math.sinh(1.2 ));
        // 计算三角正切
        System.out.println("Math.tan(0.8 ):" + Math.tan(0.8 ));
        // 计算双曲正切
        System.out.println("Math.tanh(2.1 ):" + Math.tanh(2.1 ));
        // 将矩形坐标 (x, y) 转换成极坐标 (r, thet));
        System.out.println("Math.atan2(0.1, 0.2):" + Math.atan2(0.1, 0.2));
        /*---------下面是取整运算---------*/
        // 取整,返回小于目标数的最大整数。
        System.out.println("Math.floor(-1.2 ):" + Math.floor(-1.2 ));
        // 取整,返回大于目标数的最小整数。
        System.out.println("Math.ceil(1.2):" + Math.ceil(1.2));
        // 四舍五入取整
        System.out.println("Math.round(2.3 ):" + Math.round(2.3 ));
        /*---------下面是乘方、开方、指数运算---------*/
        // 计算平方根。
        System.out.println("Math.sqrt(2.3 ):" + Math.sqrt(2.3 ));
        // 计算立方根。
        System.out.println("Math.cbrt(9):" + Math.cbrt(9));
        // 返回欧拉数 e 的n次幂。
        System.out.println("Math.exp(2):" + Math.exp(2));
        // 返回 sqrt(x2 +y2)
        System.out.println("Math.hypot(4 , 4):" + Math.hypot(4 , 4));
        // 按照 IEEE 754 标准的规定,对两个参数进行余数运算。
        System.out.println("Math.IEEEremainder(5 , 2):"
                + Math.IEEEremainder(5 , 2));
        // 计算乘方
        System.out.println("Math.pow(3, 2):" + Math.pow(3, 2));
        // 计算自然对数
        System.out.println("Math.log(12):" + Math.log(12));
        // 计算底数为 10 的对数。
        System.out.println("Math.log10(9):" + Math.log10(9));
        // 返回参数与 1 之和的自然对数。
        System.out.println("Math.log1p(9):" + Math.log1p(9));
        /*---------下面是符号相关的运算---------*/
        // 计算绝对值。
        System.out.println("Math.abs(-4.5):" + Math.abs(-4.5));
        // 符号赋值,返回带有第二个浮点数符号的第一个浮点参数。
        System.out.println("Math.copySign(1.2, -1.0):"
                + Math.copySign(1.2, -1.0));
        // 符号函数;如果参数为 0,则返回 0;如果参数大于 0,
        // 则返回 1.0;如果参数小于 0,则返回 -1.0。
        System.out.println("Math.signum(2.3):" + Math.signum(2.3));
        /*---------下面是大小相关的运算---------*/
        // 找出最大值
        System.out.println("Math.max(2.3 , 4.5):" + Math.max(2.3 , 4.5));
        // 计算最小值
        System.out.println("Math.min(1.2 , 3.4):" + Math.min(1.2 , 3.4));
        // 返回第一个参数和第二个参数之间与第一个参数相邻的浮点数。
        System.out.println("Math.nextAfter(1.2, 1.0):"
                + Math.nextAfter(1.2, 1.0));
        // 返回比目标数略大的浮点数
        System.out.println("Math.nextUp(1.2 ):" + Math.nextUp(1.2 ));
        // 返回一个伪随机数,该值大于等于 0.0 且小于 1.0。
        System.out.println("Math.random():" + Math.random());
    }
}

Java7的ThreadLoaclRandom和Random

ThreadLoaclRandom是Java7新增,是Random的增强版,在并发访问情况下,使用ThreadLoaclRandom代替Random可以减少多线程资源竞争,保证系统具有更好的线程安全性。

Random类用法:

public class RandomTest
{
    public static void main(String[] args)
    {
        Random rand = new Random();
        System.out.println("rand.nextBoolean():"
                + rand.nextBoolean());
        byte[] buffer = new byte[16];
        rand.nextBytes(buffer);
        System.out.println(Arrays.toString(buffer));
        // 生成0.0~1.0之间的伪随机double数
        System.out.println("rand.nextDouble():"
                + rand.nextDouble());
        // 生成0.0~1.0之间的伪随机float数
        System.out.println("rand.nextFloat():"
                + rand.nextFloat());
        // 生成平均值是 0.0,标准差是 1.0的伪高斯数
        System.out.println("rand.nextGaussian():"
                + rand.nextGaussian());
        // 生成一个处于int整数取值范围的伪随机整数
        System.out.println("rand.nextInt():" + rand.nextInt());
        // 生成0~26之间的伪随机整数
        System.out.println("rand.nextInt(26):" + rand.nextInt(26));
        // 生成一个处于long整数取值范围的伪随机整数
        System.out.println("rand.nextLong():" +  rand.nextLong());
    }
}

Random使用一个48位的种子,如果这个类的两个实例使用同一个种子创建的,对他们以同样的顺序调用方法,则他们会产生相同的数字序列。

public class SeedTest
{
    public static void main(String[] args)
    {
        Random r1 = new Random(50);
        System.out.println("第一个种子为50的Random对象");
        System.out.println("r1.nextBoolean():\t" + r1.nextBoolean());
        System.out.println("r1.nextInt():\t\t" + r1.nextInt());
        System.out.println("r1.nextDouble():\t" + r1.nextDouble());
        System.out.println("r1.nextGaussian():\t" + r1.nextGaussian());
        System.out.println("---------------------------");
        Random r2 = new Random(50);
        System.out.println("第二个种子为50的Random对象");
        System.out.println("r2.nextBoolean():\t" + r2.nextBoolean());
        System.out.println("r2.nextInt():\t\t" + r2.nextInt());
        System.out.println("r2.nextDouble():\t" + r2.nextDouble());
        System.out.println("r2.nextGaussian():\t" + r2.nextGaussian());
        System.out.println("---------------------------");
        Random r3 = new Random(100);
        System.out.println("种子为100的Random对象");
        System.out.println("r3.nextBoolean():\t" + r3.nextBoolean());
        System.out.println("r3.nextInt():\t\t" + r3.nextInt());
        System.out.println("r3.nextDouble():\t" + r3.nextDouble());
        System.out.println("r3.nextGaussian():\t" + r3.nextGaussian());
    }
}

为了避免两个Random序列产生相同的数字序列,通常推荐使用当前时间作为Random对象的种子。

BigDecimal类:

使用基本类型的浮点数float、double容易引起数据丢失:

public class DoubleTest
{
    public static void main(String args[])
    {
        System.out.println("0.05 + 0.01 = " + (0.05 + 0.01));
        System.out.println("1.0 - 0.42 = " + (1.0 - 0.42));
        System.out.println("4.015 * 100 = " + (4.015 * 100));
        System.out.println("123.3 / 100 = " + (123.3 / 100));
    }
}

为此,Java提供了BigDecimal类,该类提供了大量构造器用于创建BigDecimal对象,包括把所有的基本数值类型变量转换成一个BigDecimal对象,也包括利用数字字符串、数字字符数组来创建BigDecimal对象,查看BigDecimal(double val)不推荐使用该构造器,因为使用该构造器有一定的不可预知性。

BigDecimal的基本运算:

public class BigDecimalTest
{
    public static void main(String[] args)
    {
        BigDecimal f1 = new BigDecimal("0.05");
        BigDecimal f2 = BigDecimal.valueOf(0.01);
        BigDecimal f3 = new BigDecimal(0.05);
        System.out.println("使用String作为BigDecimal构造器参数:");
        System.out.println("0.05 + 0.01 = " + f1.add(f2));
        System.out.println("0.05 - 0.01 = " + f1.subtract(f2));
        System.out.println("0.05 * 0.01 = " + f1.multiply(f2));
        System.out.println("0.05 / 0.01 = " + f1.divide(f2));
        System.out.println("使用double作为BigDecimal构造器参数:");
        System.out.println("0.05 + 0.01 = " + f3.add(f2));
        System.out.println("0.05 - 0.01 = " + f3.subtract(f2));
        System.out.println("0.05 * 0.01 = " + f3.multiply(f2));
        System.out.println("0.05 / 0.01 = " + f3.divide(f2));
    }
}

为了避免程序中对于double运算的繁琐,可以以BigDecimal基础定义一个Arith工具类:

public class Arith
{
    // 默认除法运算精度
    private static final int DEF_DIV_SCALE = 10;
    // 构造器私有,让这个类不能实例化
    private Arith()    {}
    // 提供精确的加法运算。
    public static double add(double v1,double v2)
    {
        BigDecimal b1 = BigDecimal.valueOf(v1);
        BigDecimal b2 = BigDecimal.valueOf(v2);
        return b1.add(b2).doubleValue();
    }
    // 提供精确的减法运算。
    public static double sub(double v1,double v2)
    {
        BigDecimal b1 = BigDecimal.valueOf(v1);
        BigDecimal b2 = BigDecimal.valueOf(v2);
        return b1.subtract(b2).doubleValue();
    }
    // 提供精确的乘法运算。
    public static double mul(double v1,double v2)
    {
        BigDecimal b1 = BigDecimal.valueOf(v1);
        BigDecimal b2 = BigDecimal.valueOf(v2);
        return b1.multiply(b2).doubleValue();
    }
    // 提供(相对)精确的除法运算,当发生除不尽的情况时.
    // 精确到小数点以后10位的数字四舍五入。
    public static double div(double v1,double v2)
    {
        BigDecimal b1 = BigDecimal.valueOf(v1);
        BigDecimal b2 = BigDecimal.valueOf(v2);
        return b1.divide(b2 , DEF_DIV_SCALE
            , RoundingMode.HALF_UP).doubleValue();
    }
    public static void main(String[] args)
    {
        System.out.println("0.05 + 0.01 = "
            + Arith.add(0.05 , 0.01));
        System.out.println("1.0 - 0.42 = "
            + Arith.sub(1.0 , 0.42));
        System.out.println("4.015 * 100 = "
            + Arith.mul(4.015 , 100));
        System.out.println("123.3 / 100 = "
            + Arith.div(123.3 , 100));
    }
}

日期时间

 Date类

已经过时的Date

public class DateTest
{
    public static void main(String[] args)
    {
        Date d1 = new Date();
        // 获取当前时间之后100ms的时间
        Date d2 = new Date(System.currentTimeMillis() + 100);
        System.out.println(d2);
        System.out.println(d1.compareTo(d2));
        System.out.println(d1.before(d2));
    }
}

Calendar类是一个抽象类,他代表日历:

public class CalendarTest
{
    public static void main(String[] args)
    {
        Calendar c = Calendar.getInstance();
        // 取出年
        System.out.println(c.get(YEAR));
        // 取出月份
        System.out.println(c.get(MONTH));
        // 取出日
        System.out.println(c.get(DATE));
        // 分别设置年、月、日、小时、分钟、秒
        c.set(2003 , 10 , 23 , 12, 32, 23); //2003-11-23 12:32:23
        System.out.println(c.getTime());
        // 将Calendar的年前推1年
        c.add(YEAR , -1); //2002-11-23 12:32:23
        System.out.println(c.getTime());
        // 将Calendar的月前推8个月
        c.roll(MONTH , -8); //2002-03-23 12:32:23
        System.out.println(c.getTime());


        Calendar cal1 = Calendar.getInstance();
        cal1.set(2003, 7, 23, 0, 0 , 0); // 2003-8-23
        cal1.add(MONTH, 6); //2003-8-23 => 2004-2-23
        System.out.println(cal1.getTime());


        Calendar cal2 = Calendar.getInstance();
        cal2.set(2003, 7, 31, 0, 0 , 0); // 2003-8-31
        // 因为进位到后月份改为2月,2月没有31日,自动变成29日
        cal2.add(MONTH, 6); // 2003-8-31 => 2004-2-29
        System.out.println(cal2.getTime());


        Calendar cal3 = Calendar.getInstance();
        cal3.set(2003, 7, 23, 0, 0 , 0); //2003-8-23
        // MONTH字段“进位”,但YEAR字段并不增加
        cal3.roll(MONTH, 6); //2003-8-23 => 2003-2-23
        System.out.println(cal3.getTime());


        Calendar cal4 = Calendar.getInstance();
        cal4.set(2003, 7, 31, 0, 0 , 0); //2003-8-31
        // MONTH字段“进位”后变成2,2月没有31日,
        // YEAR字段不会改变,2003年2月只有28天
        cal4.roll(MONTH, 6); //2003-8-31 => 2003-2-28
        System.out.println(cal4.getTime());
    }
}

Java 8专门新增了一个java.time包,该包下包含了如下常用类:  Clock、Duration、LocalDate、LocalTime、LocalDateTime、MonthDay、Year、YearMonth、DayOfWeek、Month。

public class NewDatePackageTest
{
    public static void main(String[] args)
    {
        // -----下面是关于Clock的用法-----
        // 获取当前Clock
        Clock clock = Clock.systemUTC();
        // 通过Clock获取当前时刻
        System.out.println("当前时刻为:" + clock.instant());
        // 获取clock对应的毫秒数,与System.currentTimeMillis()输出相同
        System.out.println(clock.millis());
        System.out.println(System.currentTimeMillis());
        // -----下面是关于Duration的用法-----
        Duration d = Duration.ofSeconds(6000);
        System.out.println("6000秒相当于" + d.toMinutes() + "分");
        System.out.println("6000秒相当于" + d.toHours() + "小时");
        System.out.println("6000秒相当于" + d.toDays() + "天");
        // 在clock基础上增加6000秒,返回新的Clock
        Clock clock2 = Clock.offset(clock, d);
        // 可看到clock2与clock1相差1小时40分
        System.out.println("当前时刻加6000秒为:" +clock2.instant());
        // -----下面是关于Instant的用法-----
        // 获取当前时间
        Instant instant = Instant.now();
        System.out.println(instant);
        // instant添加6000秒(即100分钟),返回新的Instant
        Instant instant2 = instant.plusSeconds(6000);
        System.out.println(instant2);
        // 根据字符串中解析Instant对象
        Instant instant3 = Instant.parse("2014-02-23T10:12:35.342Z");
        System.out.println(instant3);
        // 在instant3的基础上添加5小时4分钟
        Instant instant4 = instant3.plus(Duration
            .ofHours(5).plusMinutes(4));
        System.out.println(instant4);
        // 获取instant4的5天以前的时刻
        Instant instant5 = instant4.minus(Duration.ofDays(5));
        System.out.println(instant5);
        // -----下面是关于LocalDate的用法-----
        LocalDate localDate = LocalDate.now();
        System.out.println(localDate);
        // 获得2014年的第146天
        localDate = LocalDate.ofYearDay(2014, 146);
        System.out.println(localDate); // 2014-05-26
        // 设置为2014年5月21日
        localDate = LocalDate.of(2014, Month.MAY, 21);
        System.out.println(localDate); // 2014-05-21
        // -----下面是关于LocalTime的用法-----
        // 获取当前时间
        LocalTime localTime = LocalTime.now();
        // 设置为22点33分
        localTime = LocalTime.of(22, 33);
        System.out.println(localTime); // 22:33
        // 返回一天中的第5503秒
        localTime = LocalTime.ofSecondOfDay(5503);
        System.out.println(localTime); // 01:31:43
        // -----下面是关于localDateTime的用法-----
        // 获取当前日期、时间
        LocalDateTime localDateTime = LocalDateTime.now();
        // 当前日期、时间加上25小时3分钟
        LocalDateTime future = localDateTime.plusHours(25).plusMinutes(3);
        System.out.println("当前日期、时间的25小时3分之后:" + future);
        // 下面是关于Year、YearMonth、MonthDay的用法示例-----
        Year year = Year.now(); // 获取当前的年份
        System.out.println("当前年份:" + year); // 输出当前年份
        year = year.plusYears(5); // 当前年份再加5年
        System.out.println("当前年份再过5年:" + year);
        // 根据指定月份获取YearMonth
        YearMonth ym = year.atMonth(10);
        System.out.println("year年10月:" + ym); // 输出XXXX-10,XXXX代表当前年份
        // 当前年月再加5年,减3个月
        ym = ym.plusYears(5).minusMonths(3);
        System.out.println("year年10月再加5年、减3个月:" + ym);
        MonthDay md = MonthDay.now();
        System.out.println("当前月日:" + md); // 输出--XX-XX,代表几月几日
        // 设置为5月23日
        MonthDay md2 = md.with(Month.MAY).withDayOfMonth(23);
        System.out.println("5月23日为:" + md2); // 输出--05-23
    }
}

变量处理和方法处理

Java9增强的MethidHandle

public class MethodHandleTest
{
    // 定义一个private的类方法
    private static void hello()
    {
        System.out.println("Hello world!");
    }
    // 定义一个private的实例方法
    private String hello(String name)
    {
        System.out.println("执行带参数的hello" + name);
        return name + ",您好";
    }
    public static void main(String[] args) throws Throwable
    {
        // 定义一个返回值为void、不带形参的方法类型
        MethodType type = MethodType.methodType(void.class);
        // 使用MethodHandles.Lookup的findStatic获取类方法
        MethodHandle mtd = MethodHandles.lookup()
                .findStatic(MethodHandleTest.class, "hello", type);
        // 通过MethodHandle执行方法
        mtd.invoke();
        // 使用MethodHandles.Lookup的findVirtual获取实例方法
        MethodHandle mtd2 = MethodHandles.lookup()
                .findVirtual(MethodHandleTest.class, "hello",
                        // 指定获取返回值为String, 形参为String的方法类型
                        MethodType.methodType(String.class, String.class));
        // 通过MethodHandle执行方法,传入主调对象和参数
        System.out.println(mtd2.invoke(new MethodHandleTest(), "孙悟空"));
    }
}

Java9增强的VarHandle

VarHandle主要用于动态操作数组的元素或对象的成员变量。

class User
{
    String name;
    static int MAX_AGE;
}
public class VarHandleTest
{
    public static void main(String[] args)throws Throwable
    {
        String[] sa = new String[]{"Java", "Kotlin", "Go"};
        // 获取一个String[]数组的VarHandle对象
        VarHandle avh = MethodHandles.arrayElementVarHandle(String[].class);
        // 比较并设置:如果第三个元素是Go,则该元素被设为Lua
        boolean r = avh.compareAndSet(sa, 2, "Go", "Lua");
        // 输出比较结果
        System.out.println(r); // 输出true
        // 看到第三个元素被替换成Lua
        System.out.println(Arrays.toString(sa));
        // 获取sa数组的第二个元素
        System.out.println(avh.get(sa, 1)); // 输出Kotlin
        // 获取并设置:返回第三个元素,并将第三个元素设为Swift
        System.out.println(avh.getAndSet(sa, 2, "Swift"));
        // 看到第三个元素被替换成Swift
        System.out.println(Arrays.toString(sa));

        // 用findVarHandle方法获取User类中名为name,
        // 类型为String的实例变量
        VarHandle vh1 = MethodHandles.lookup().findVarHandle(User.class,
            "name", String.class);
        User user = new User();
        // 通过VarHandle获取实例变量的值,需要传入对象作为调用者
        System.out.println(vh1.get(user)); // 输出null
        // 通过VarHandle设置指定实例变量的值
        vh1.set(user, "孙悟空");
        // 输出user的name实例变量的值
        System.out.println(user.name); // 输出孙悟空
        // 用findVarHandle方法获取User类中名为MAX_AGE,
        // 类型为Integer的类变量
        VarHandle vh2 = MethodHandles.lookup().findStaticVarHandle(User.class,
            "MAX_AGE", int.class);
        // 通过VarHandle获取指定类变量的值
        System.out.println(vh2.get()); // 输出0
        // 通过VarHandle设置指定类变量的值
        vh2.set(100);
        // 输出User的MAX_AGE类变量
        System.out.println(User.MAX_AGE); // 输出100
    }
}

Java9改进的国际化和格式化

获取Java所支持的国家和语言:

public class LocaleList
{
    public static void main(String[] args)
    {
        // 返回Java所支持的全部国家和语言的数组
        Locale[] localeList = Locale.getAvailableLocales();
        // 遍历数组的每个元素,依次获取所支持的国家和语言
        for (int i = 0; i < localeList.length ; i++ )
        {
            // 输出出所支持的国家和语言
            System.out.println(localeList[i].getDisplayCountry()
                    + "=" + localeList[i].getCountry()+ " "
                    + localeList[i].getDisplayLanguage()
                    + "=" + localeList[i].getLanguage());
        }
    }
}

Java8新增的日期、时间格式器

使用DateTimeFormatter完成格式化:

public class NewFormatterTest
{
    public static void main(String[] args)
    {
        DateTimeFormatter[] formatters = new DateTimeFormatter[]{
                // 直接使用常量创建DateTimeFormatter格式器
                DateTimeFormatter.ISO_LOCAL_DATE,
                DateTimeFormatter.ISO_LOCAL_TIME,
                DateTimeFormatter.ISO_LOCAL_DATE_TIME,
                // 使用本地化的不同风格来创建DateTimeFormatter格式器
                DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL, FormatStyle.MEDIUM),
                DateTimeFormatter.ofLocalizedDate(FormatStyle.LONG),
                // 根据模式字符串来创建DateTimeFormatter格式器
                DateTimeFormatter.ofPattern("Gyyyy%%MMM%%dd HH:mm:ss")
        };
        LocalDateTime date = LocalDateTime.now();
        // 依次使用不同的格式器对LocalDateTime进行格式化
        for(int i = 0 ; i < formatters.length ; i++)
        {
            // 下面两行代码的作用相同
            System.out.println(date.format(formatters[i]));
            System.out.println(formatters[i].format(date));
        }
    }
}

使用DateTimeFormatter解析字符串

public class NewFormatterParse
{
    public static void main(String[] args)
    {
        // 定义一个任意格式的日期时间字符串
        String str1 = "2014==04==12 01时06分09秒";
        // 根据需要解析的日期、时间字符串定义解析所用的格式器
        DateTimeFormatter fomatter1 = DateTimeFormatter
                .ofPattern("yyyy==MM==dd HH时mm分ss秒");
        // 执行解析
        LocalDateTime dt1 = LocalDateTime.parse(str1, fomatter1);
        System.out.println(dt1); // 输出 2014-04-12T01:06:09
        // ---下面代码再次解析另一个字符串---
        String str2 = "2014$$$4月$$$13 20小时";
        DateTimeFormatter fomatter2 = DateTimeFormatter
                .ofPattern("yyy$$$MMM$$$dd HH小时");
        LocalDateTime dt2 = LocalDateTime.parse(str2, fomatter2);
        System.out.println(dt2); // 输出 2014-04-13T20:00

    }
}

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏aCloudDeveloper

LeetCode:1_Two_Sum | 两个元素相加等于目标元素 | Medium

题目: Given an array of integers, find two numbers such that they add up to a spec...

213100
来自专栏cmazxiaoma的架构师之路

Java数据结构和算法(2)--《Java数据结构和算法》第二版 Robert lafore第二章【数组】编码作业

22130
来自专栏老马说编程

(35) 泛型 (上) - 基本概念和原理 / 计算机程序的思维逻辑

之前章节中我们多次提到过泛型这个概念,从本节开始,我们就来详细讨论Java中的泛型,虽然泛型的基本思维和概念是比较简单的,但它有一些非常令人费解的语法、细节、以...

24080
来自专栏mukekeheart的iOS之旅

No.015 3Sum

15. 3Sum Total Accepted: 131800 Total Submissions: 675028 Difficulty: Medium   G...

24580
来自专栏java初学

hashMap原理(java8)

384170
来自专栏分布式系统和大数据处理

C#理解泛型(译)

Visual C# 2.0 的一个最受期待的(或许也是最让人畏惧)的一个特性就是对于泛型的支持。这篇文章将告诉你泛型用来解决什么样的问题,以及如何使用它们来提高...

8830
来自专栏函数式编程语言及工具

Scalaz(18)- Monad: ReaderWriterState-可以是一种简单的编程语言

  说道FP,我们马上会联想到Monad。我们说过Monad的代表函数flatMap可以把两个运算F[A],F[B]连续起来,这样就可以从程序的意义上形成一种串...

20670
来自专栏Java架构

Java 8简明教程

25450
来自专栏皮皮之路

【JDK1.8】JDK1.8集合源码阅读——IdentityHashMap

40590
来自专栏恰童鞋骚年

剑指Offer面试题:14.链表的倒数第k个节点

PS:这是一道出境率极高的题目,记得去年参加校园招聘时我看到了3次,但是每次写的都不完善。

12640

扫码关注云+社区

领取腾讯云代金券