美文网首页
6. Java基础类库

6. Java基础类库

作者: hainingwyx | 来源:发表于2017-06-03 23:15 被阅读50次

    以下是《疯狂Java讲义》中的一些知识,如有错误,烦请指正。

    与用户互动

    Java程序的参数
    如果运行Java程序时在类名后紧跟一个或多个字符串(多个字符串之间以空格隔开),JVM就会把这些字符串依次赋给args数组元素。
    如果某参数本身包含了空格,则应该将该参数用双引号(")括起来,否则JVM会把这个空格当成参数分隔符,而不是当成参数本身。

    使用Scanner获取键盘输入
    使用Scanner类可以很方面地获取用户的键盘输入,Scanner是一个基于正则表达式的文本扫描器,它可以从文件、输入流、字符串中解析出基本类型值和字符串值。Scanner类提供了多个构造器,不同的构造器可接受文件、输入流、字符串作为数据源,用于从文件、输入流、字符串中解析数据。
    Scanner主要提供了两个方法来扫描输入:

    • hasNextXxx():是否还有下一个输入项,其中Xxx可以是Int、Long等代表基本数据类型的字符串。如果需要判断是否包含下一个字符串,则可以省略Xxx。
    • nextXxx():获取下一个输入项。Xxx的含义与前一个方法中Xxx相同。
    import java.util.*;
    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());
            }
        }
    }
    

    获取任意类型的输入项

    import java.util.*;
    public class ScannerLongTest
    {
        public static void main(String[] args)
        {
            // System.in代表标准输入,就是键盘输入
            Scanner sc = new Scanner(System.in);
            // 判断是否还有下一个long型整数
            while(sc.hasNextLong())
            {
                // 输出输入项
                System.out.println("键盘输入的内容是:"
                    + sc.nextLong());
            }
        }
    }
    

    文件读取

    import java.util.*;
    import java.io.*;
    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类提供了代表标准输入、标准输出和错误输出的类属性;并提供了一些静态方法用于访问环境变量、系统属性的方法;还提供了加载文件和动态链接库的方法。下面程序通过System类来访问操作的环境变量和系统属性。

    import java.io.*;
    import java.util.*;
    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"));
        }
    }
    

    如果两个对象的相同,一定是同一个对象。

    
    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类

    Runtime类代表Java程序的运行时环境,每个Java程序都有一个与之对应的Runtime实例,应用程序通过该对象与其运行时环境相连。
    应用程序不能创建自己的Runtime实例,但可以通过getRuntime()方法获取与之关联的Runtime对象。
    Runtime类代表Java程序的运行时环境,可以访问JVM的相关信息,如处理器数量,内存信息等。

    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");
        }
    }
    

    常用类

    Object类
    Object类是所有类、数组、枚举类的父类,也就是说,Java允许把所有任何类型的对象赋给Object类型的变量。当定义一个类时没有使用extends关键字为它显式指定父类,则该类默认继承Object父类。

    Object还提供了一个protected修饰的clone()方法,程序员可重写该方法来实现“浅克隆”。
    自定义类实现“浅克隆”的步骤:

    1. 自定义类实现Cloneable接口。
    2. 自定义类实现clone()方法。
    3. 在clone()方法中通过super.clone()调用Object的clone()方法来实现“浅克隆”。
    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);      //false
            // 判断u1、u2的address是否相同
            //不会对引用类型的成员变量值所引用的对象进行深克隆
            System.out.println(u1.address == u2.address);     //true
        }
    }
    

    复制出来的只是原有对象的副本,只是一种浅克隆,只克隆该对象的所有成员变量值,不会对引用类型的成员变量值所引用的对象进行深克隆。深克隆需要开发者子集进行递归克隆。

    Objects类
    题外话:工具类命名习惯是添加s,如Arrays、Collections。
    hashCode():返回指定对象的hashCode值。
    toString:返回指定对象的“描述性”字符串。
    requiredNonNull:检查对象是否为null。主要用于对方法形参进行输入校验。

    import java.util.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!"));
        }
    }
    

    String、StringBuffer和StringBuilder

    字符串就是一连串的字符序列,Java提供了String和StringBuffer两个类来封装对字符串,并提供了系列方法来操作字符串对象。
    String类是不可变类的,
    StringBuffer对象则代表一个字符序列可变的字符串,当一个StringBuffer被创建以后,通过StringBuffer提供的append、insert、reverse、setCharAt、setLength等方法可以改变这个字符串对象的字符序列。一旦通过StringBuffer生成了最终想要的字符串,就可以调用它的toString方法将其转换为一个String对象。
    JDK1.5又新增了一个StringBuilder类,它也代表了字符串对象。StringBuilder是线程不安全的。

    public class StringBuilderTest
    {
        public static void main(String[] args)
        {
            StringBuilder sb = new StringBuilder();
            // 追加字符串
            sb.append("java");//sb = "java"
            // 插入
            sb.insert(0 , "hello "); // sb="hello java"
            // 替换
            sb.replace(5, 6, ","); // sb="hello, java"
            // 删除
            sb.delete(5, 6); // sb="hellojava"
            System.out.println(sb);
            // 反转
            sb.reverse(); // sb="avajolleh"
            System.out.println(sb);
            System.out.println(sb.length()); // 输出9
            System.out.println(sb.capacity()); // 输出16
            // 改变StringBuilder的长度,将只保留前面部分
            sb.setLength(5); // sb="avajo"
            System.out.println(sb);
        }
    }
    

    Math 类
    Math类是一个工具类,它的构造器被定义成private的,因此无法创建Math类的对象;Math类中所有方法都是类方法,可以直接通过类名来调用它们。

    Random与ThreadLocalRandom
    Random类专门用于生成一个伪随机数,它有两个构造器:一个构造器使用默认的种子,另一个构造器需要程序员显式传入一个long型整数的种子。
    相对于Math的random()方法而言,Random类的提供了更多方法来生成各种伪随机数,它不仅可以生成浮点类型的伪随机数,也可以生成整数类型的伪随机数,还可以指定生成随机数的范围。
    ThreadLocalRandom是Java7新增的,它可以在多线程环境下代替Random减少多线程资源竞争,从而提供更好的线程安全。

    import java.util.*;
    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());
        }
    }
    

    BigDecimal
    float、double两种基本浮点类型的浮点数容易引起精度丢失。
    程序中需要对double浮点数进行加、减、乘、除基本运算,则需要先将double类型数值包装成BigDecimal对象,调用BigDecimal对象的方法执行运算后再将结果转换成double型变量。

    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));
        }
    }
    

    注意:创建BigDecimal对象时,不要直接使用double浮点数作为构造器参数调用BigDecimal构造器
    。否则会有精度损失。

    日期时间类

    Date类
    Date类从JDK1.0起就开始存在了。但正因为它历史悠久,所以它的大部分构造器、方法都已经过时,不再推荐使用了

    Calender类
    因为Date类的设计上存在一些缺陷,Java提供了Calendar类来更好地处理日期和时间。Calendar是一个抽象类,它用于表示日历。
    Calendar本身是一个抽象类,它是所有日历类的模板,并提供了一些所有日历通用的方法,但它本身不能直接实例化。程序只能创建Calendar子类的实例,Java本身提供了一个GregorianCalendar类,一个代表Gregorian Calendar的子类,它代表了我们通常所说的公历。
    开发者可以开发自己的Calendar子类。

    import java.util.*;
    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());
        }
    }
    

    相关文章

      网友评论

          本文标题:6. Java基础类库

          本文链接:https://www.haomeiwen.com/subject/vwomfxtx.html