6. Java基础类库

以下是《疯狂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());
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,569评论 4 363
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,499评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,271评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,087评论 0 209
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,474评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,670评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,911评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,636评论 0 202
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,397评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,607评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,093评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,418评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,074评论 3 237
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,092评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,865评论 0 196
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,726评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,627评论 2 270

推荐阅读更多精彩内容

  • 集合框架: 1)特点:存储对象;长度可变;存储对象的类型可不同2)Collection(1)List:有序的;元素...
    Demo_Yang阅读 1,180评论 0 4
  • 下面的内容是对网上原有的Java面试题集及答案进行了全面修订之后给出的负责任的题目和答案,原来的题目中有很多重复题...
    独念白阅读 1,223评论 0 3
  • 转自:http://blog.csdn.net/jackfrued/article/details/4492194...
    王帅199207阅读 8,386评论 3 93
  • 从我记事起,我就嗜辣,几乎无辣不欢。 我妈妈说我小时候不吃辣椒,一丁点都不吃。 大概三岁左右的时候,我无辣不欢的爷...
    小伊森阅读 600评论 2 2
  • 表单(form) 网站怎样与用户进行交互?答案是使用HTML表单(form)。表单可以把浏览者输入的数据传送到服务...
    远山黛子阅读 294评论 0 0