[笔记] 疯狂JAVA讲义(第3版)第7章 Java基础类库

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
简介: [笔记] 疯狂JAVA讲义(第3版)第7章 Java基础类库

第7章 Java基础类库

Java 8 提供了4000多个基础类,对于合格的Java程序员,至少要熟悉JavaSE中70%的类。

7.1 与用户互动

7.1.1 运行Java程序的参数

回忆main()方法的签名:

public static void main(String[] args){…}

形参是谁赋值呢? 根据方法调用规则,谁调用谁赋值,JVM调用main()方法,因此JVM为其赋值。

public class ArgsTest

{
    public static void main(String[] args) {
        System.out.println(args.length);

        for(String s:args){
            System.out.println(s);

        }

    }

}
 

直接正常运行,程序输出0.

用 java ArgsTest Java Spring 运行,输出 2  Java Spring

可以看出JVM把后面的字符串赋值给了args数组

@如果字符串包含空格,应该用””括起来 “Java Spring”

7.1.2 使用 Scanner获取键盘输入

Scanner是一个基于正则表达式的文本扫描器,它可以从文件、输入流、字符串中解析出基本类型值和字符串值。

Scanner提供了多个构造器,用于接收文件、输入流、字符串。

Scanner主要提供了两个方法扫描输入。

hasNextXxx() :是否还有下一个输入项。Xxx可以是Int,Long等代表基本数据类型的字符串,如果是判断字符串,可以直接用hasNext()

nextXxx() : 获取下一个输入项。

默认情况下,Scanner使用空白作为多个输入项之间的分隔符。

import java.util.Scanner;

public class ScannerKeyBoardTest

{
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in); //System.in 代表标准输入,就是键盘输入

        //sc.useDelimiter("\n"); //将回车作为分隔符,每次读取一行

        while(sc.hasNext()){
            System.out.println("键盘输入:"+sc.next());

        }

    }

}
 

为Scanner设置分隔符使用userDelimiter(String pattern),参数为一个正则表达式。

Scanner还提供了两个方法逐行读取输入:

Boolean hasNextLine()

String nextLinr()

Scanner不仅可以读取字符串输入,还可以读入任意基本类型的输入项。

import java.util.Scanner;

public class ScannerKeyBoardTest

{
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in); //System.in 代表标准输入,就是键盘输入

        while(sc.hasNexLongt()){
            System.out.println("键盘输入:"+sc.nextLong());

        }

    }

}
 

Scanner还可以读取文件输入,只要在构造器中传入一个File对象

import java.util.Scanner;

import java.io.File;

public class ScannerFileTest

{
    public static void main(String[] args) throws Exception{
        Scanner sc = new Scanner(new File("D://TEST//java//ch7//ScannerFileTest.txt"));   //很奇怪就这个文件读取不显示,换成其他的都正常

        System.out.println("ScannerFileTest.txt文件内容如下:");

        while(sc.hasNextLine()){
            System.out.println(sc.nextLine());

        }

        System.out.println("ScannerFileTest.txt文件内容结束:");

    }

}

注意:1、main方法可能引发Io异常,所以要加上throws Exception

2、建议文件目录为绝对路径,使用相对路径可能出错

3、不知道为什么命令行下打开无法输出文件内容,只输出提示。而且把文件内容删除后,就正常。猜测是编码问题。

7.2 系统相关

获得和平台相关的属性。

7.2.1 System类

System类代表Java程序当前运动的运行平台,程序不能创建System类的对象,

System类提供了一些类成员和类方法,可以直接调用。

import java.io.FileOutputStream;

import java.util.Map;

import java.util.Properties;

 

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.store(new FileOutputStream("props.txt"), "System Properties");

        System.out.println(System.getProperty("os.name"));

    }

}
 

System类还有两个获取当前系统时间的方法:currentTimeMillis()和nanoTime(),

它们返回一个long型整数,值为当前时间和UTC1970年1月1日午夜的时间差,前者以毫秒为单位(常用),后者以纳秒为单位(少用)。

System类的in,out和err 分别代表系统标准输入,标准输出和错误输出流。

并提供setXx()方法来改变。

System类还提供identityHashCode(Object x)方法,返回对象根据地址计算的HashCode值。可以唯一标识对象。

7.2.2 Runtime类

Runtime类代表Java程序的运行时环境。

程序可以通过getRuntime()获取与之关联的Runtime对象。

Runtime也提供了gc()和runFinalization()方法通知系统进行垃圾回收。

提供load(String filename)和loadLibrary(String libname)加载文件和动态链接库。

public class RuntimeTest

{
    public static void main(String[] args) {
        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"); //运行记事本程序

    }

}

7.3 常用类

7.3.1 Object类

Object类是所有类、数组、枚举类的父类。

一个类没有指定父类时,默认继承Object类。

bool equals(Object obj):判断两个对象是否为同一个对象

protected void finalize():系统清理垃圾时自动调用

Class<?>getClass():返回对象运行时类

int hashCode():返回对象hashCode值。

String toString(): 返回对象的字符串表示,当print对象或对象和字符串拼接时,会自动调用该方法。

protected clone() :得到当前对象副本。

自定义类实现“克隆”的步骤:

1、实现Cloneable接口

2、实现clone()方法 ,实现clone()方法时调用super.clone(),并返回该对象。

例:

class User implements Cloneable

{
int age;

public User(int age)

{
this.age = age;

}

public User clone() throws CloneNotSupportedException

{
return (User) super.clone();

}

Object提供的Clone机制只是简单复制,如果实例变量是引用类型,则直接复制引用变量,而不是复制出一个对象。

 

7.3.2 Java 7 新增的Objects类

Object提供的Clone机制只是简单复制,如果实例变量是引用类型,则直接复制引用变量,而不是复制出一个对象。

@工具类命名习惯是添加一个s,如Arrays。

7.3.3 String、StringBuffer和StringBuilder类

字符串是一串字符,Java提供String和StringBuffer来封装字符串。

String类是不可变类,里面字符不可改变。

StringBuffer是字符序列可变的字符串,可以使用append,insert, reverse setCharAt,setLength等方法来改变字符串。

 使用toString()可以将其转换成String对象。

JDK1.5新增StringBuilder类,与StringBuffer类相似,只是StringBuild没有实现线程安全功能,性能略高。

通常考虑StringBuilder实现可变字符串。

 

String提供大量构造器来创建String对象。

String也提供了大量方法来操作字符串对象。

//这些方法都可以在API文档中查阅。

char CharAt(int index) :返回index位置的字符

int compareTo(Stirng s) :比较字符串大小,相等返回0,不相等时,返回第一个不等的字符差。当较长字符串正好前面是较短字符串,则返回长度差。

String concat(String srt) 拼接,功能同+

Boolean contentEquals(StringBuffer sb) :和StringBuffer对象比较

static String copyValueOf(char[]data) 将字符数组连成字符串。

static String copyValueOf(char[]data,int offset,int count) :连接数组中的部分元素

Boolean endsWith(String suffix): 是否以suffix结尾

Boolean equals(Object obj) 是否和对象字符序列相等

Boolean equalsIgnoreCase(Object obj) 是否和对象字符序列相等,忽略大小写

byte[] getBytes(): 转换成byte数组

void getChars(int srcBegin,int srcEnd, char[] dst,int dstBegin):复制到dst数组中

int indexOf(int ch) :ch第一次出现的位置

int indexOf(int ch,int fromIndex)

int indexOf(String str):str子串第一次出现的位置

int indexOf(String str, int fromIndex)

int lastIndexOf(int ch) :ch最后一次出现

int lastIndexOf(int ch,int fromIndex)

int lastIndexOf(String str)

int lastIndexOf(String str,int fromIndex)

int length()

String replace(char oldc,char newc); 将第一个oldc替换成newc

Boolean startsWith(String prefix) 是否以prefix开始

Boolean startsWith(String prefix,int toffset)

 

String substring(int beginIndex): 子串

String substring(int beginIndex, int endIndex)

char[] toCharrArray()

String toLowerCase()

String toUpperCase()

static String valueOf(X x), 将基本类型转换成字符串。

 

7.3.4 Math类

 

7.3.5 Java7 的ThreadLocalRandom和 Random

Random类用于生成一个伪随机数,它有两个构造器,一个使用默认的时间种子,另一个需要传入一个long型整数作为种子。

ThreadLocalRandom是Random的加强版,具有更好的线程安全性。

Random 用法

Random rand = new Random();

rand.nextXxx();

推荐使用当前时间作为Random种子

Random rand = new Random(System.currentTimeMillis());

 

ThreadLocalRandom用法和Random类似

ThreadLocalRandom rand = ThreadLocalRandom.current();

rand.nextXxx();

 

7.3.6 BigDecimal类

精确表示浮点数:

创建对象

BigDecimal(String val)

运算:提供了add() subtract() multiply() divide() pow()等方法

 

如果程序中要对浮点数进行运算,可以考虑将double保证成BigDecimal对象,然后进计算,再讲结果转换成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();

}

//剩下的三种类似,略

//除法使用的方法

// b1.divide(b2,DEF_DIV_SCALE,BigDecimal.ROUND_HALF_UP).doubleValue();

}

 

7.4 java8的日期、时间类

7.4.1 Date类

Date类从JDK1.0就存在了,大部分构造器方法都已经过时,不推荐使用了(Deprecated)

还可以使用的构造器:

Date() :返回当前时间

Date(long date):根据date生成Date对象,该参数data表示与GMT1970.1.1 00:00:00的时间差,单位毫秒

剩下的方法:

Boolean after(Date when)

Boolean before(Date when)

long getTime() 返回时间差

void setTime(long time) 设置时间

@总体上,Date是一个糟糕的类,不不推荐使用

7.4.2 Calendar类

Calender类用来取代Date类来处理日期和时间。

Calendar是一个抽象类,用来表示日历。

Java提供了一个GregorianCalendar类,代表公历。

Calendar是抽象类,不能根据根据构造器创建Calendar对象,但可以通过getInstance()方法获取Calendar对象。

Calendar calendar = Calendar.getInstance();

Calendar提供大量访问、修改日期的方法

void add(int field, int amount)

int get(int field);

void set(int field,int value)

void set(int year,int month,int date)

void set(int year,int month,int date,int h,int m, int s);

field是Calendar的类变量,如Calendar.YEAR,需要注意的是

Calendar.MONTH 月份的起始值是0.

设置Calendar的兼容性

setLenient(true|false) ,默认为true,具有容错性,当参数异常是不会报错。

false时参数异常会报错。

3、set()方法延迟修改

,Calendar代表的时间在下次调用get()等方法时才会重新计算。

 

7.4.3Java8 新增的日期、时间包

java.time

该包包含了如下的类:

Clock: 获取指定时区的当前日期时间

Duration:持续时间

Instant:某个具体的时刻

LocalDate:不带时区的日期

LocalTime: 不带时区的时间

LocalDateTime:日期、时间

MonthDay:月日

Year:年

ZonedDateTime:时区化的日期时间

ZonedID:时区

7.5 正则表达式

字符串处理工具,用于对字符串进行查找,提取,分割,替换等。

String类提供了关于正则的方法:

Boolean matches(String regex):判断字符串是否匹配正则表达式

String replaceAll(String regex, String replacement) 将所有匹配regex的子串 替换成replacement

Strubg replaceFirst(String regex, String replacement);

String[] split(String regex) :以regex作为分隔符

7.5.1 创建正则表达式

正则表达式是一个用于匹配字符串的模板。

正则表达式本身就是一个特殊的字符串。

正则表达式支持的字符:

字符     解释

x            字符x(合法的任何字符)

\t            制表

\n           换行

\r           回车

特殊字符:

特殊字符       说明

$                   匹配一行的结尾。

^                   匹配一行的开头

()                   标记子表达式的开始和结束

[]                   确定中括号表达式的开始和结束

{}                  标记前面子表达式出现频度

*               前面子表达式可以出现任意次          

+                   前面子表达式可以出现一次或多次

?           前面子表达式可以出现0次或1次

.            匹配出换行以外的单字符

\           转义字符

|                    两项中任选一项


通配符:可以匹配多个字节的特殊字符

字符              说明

.                    匹配任何字符

\d               0~9的数字

\D                 非数字

\s                空白

\S                  非空白

\w                 单词(包括0-9,26个字母,下划线)

\W                非单词


方括号表达式

表示枚举              如[abc],表示a,b,c任意一个字符

表示范围-            如[a-f],表示a-f范围任意一个字符,范围可枚举可以结合使用:[a-cx-z]表示a-c,x-z内的任意字符

表示求否^            如[^abc] 表示非abc的字符,[^a-f]不在a-f范围内的字符

表示与 &&          如[a-z&&[def]] a-z和[def]的交集 def

表示并                  类似枚举,如[a-d[m-p]] 等价[a-dm-p]


圆括号表达式

将多个表达式组合成一个,可以使用|符号。例如”((public)|(protected)|(private))” 可以匹配访问控制符的任意一个。


边界匹配符

^    开头

$    结尾

\b   单词边界

\B

\A    输入开头

\G   前一个匹配的结尾

\Z    输入的结尾,仅用于最后的结束符

\z    输入的结尾


数量标识符

数量标识符3中模式:

1、Greedy模式:默认采用贪婪模式。贪婪模式的表达式会一直匹配下去,直到无法匹配。

2、Relunctant(勉强)模式:用?后缀表示,匹配最少的字符,也称最小匹配模式。

3、Possessive(占有)模式:用+后缀表示。



7.5.2 使用正则表达式

Pattern 对象是正则表达式编译后在内存中的表示形式,正则表达式必须先编译为Pattern对象,再使用Pattern对象创建Match对象。

Pattern p = Pattern.compile(“a*b)”);

Match m = p.matcher(“aaaaab”);

Boolean b = m.matches();

//前两步可以合并

Match m = Pattern.compile(“(a*b)”).matcher(“aaaab”);


find():返回是否包含匹配的子串

group():返回上一次匹配的子串。

Matcher类提供的find()方法和group()方法可以从目标字符串中一次提取特定子串。

比如提取电话号码:

import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class FindGroup
{
    public static void main(String[] args) {
        String str = "求购一本<java>,有意者联系13500006666"+"交朋友,电话号码13611112222"
        +"出售二手书,有意联系15822223333";
        //创建Pattern对象,匹配13x,15x的手机号,并用其建立Matcher对象。
        Matcher m = Pattern.compile("((13\\d)|(15\\d))\\d{8}").matcher(str);
        while(m.find()){
            System.out.println(m.group());
        }
    }
}



@由于Java字符串本身反斜杠需要转义,所以两个\\相当于一个\。

()

{}

+ * . |


7.6 国际化与格式化

全球化意味着同一版本能适应不同地区的市场。


7.6.1 Java国际化的思路

将程序中的标签,提示灯信息放在资源文件中,程序需要支持哪些国家,语言,就提供对应的资源文件。

资源文件是key-value对,每个资源文件的key是不变的,value随国家语言改变。



Java程序的国际化主要通过3个类完成:

java.util.ResourceBundle:用于加载资源包

java.util.Locale :用于封装特定的国家/区域,语言环境

java.text.MessageFormat: 用于格式化带占位符的字符串。


为了实现程序的国际化,首先要提供需要的资源文件(key-value对)。

资源文件的key 是程序使用的部分,value是程序界面显示的字符串。

资源文件的命名有如下三种形式:

baseName_language_country.properties

baseName_language.properties

baseName.properties

baseName是资源文件的基本名,由用户指定,language和country不可随意变化,必须是Java支持的语言和国家。


7.6.2 Java支持的国家和语言

通过Locale 类提供的方法可以得到Java支持的国家和语言:


import java.util.Locale;
public class LocalList
{
    public static void main(String[] args) {
        Locale[] localList =  Locale.getAvailableLocales();
        for(Locale l:localList){
            System.out.println(l.getDisplayCountry()+
            "="+l.getCountry()+" "
            +l.getDisplayLanguage()
            +"="+l.getLanguage());
        }
    }
}



7.6.3 完成程序国际化


1、有如下程序

public class RawHello
{
public static void main(String[] args) {
  System.out.println("Hello,world");}
}


直接执行永远只是输出Hello,world


为了让输出的字符串随运行环境改变,应该将要输出的字符串定义在资源包里。

为上面程序提供两个文件:

mess.properties

内容:

hello=你好!

mess_en_US.properties

内容:

hello=Welcome You!


//JDK9 以上支持UTF-8 ,不需要这个转换了。

对于包含非西欧字符的资源文件,Java提供native2ascii工具处理,语法:native2ascii 原资源文件 目的资源文件

在命令行输入:native2ascii mess.properties mess_zh_CN.properties


所以我这里直接将前面的mess.properties改名为mess_zh_CN.properties


import java.util.Locale;
import java.util.ResourceBundle;
public class Hello
{
    public static void main(String[] args) {
        //获得系统默认的国家/语言
        Locale myLocale = Locale.getDefault(Locale.Category.FORMAT);
        ResourceBundle bundle = ResourceBundle.getBundle("mess",myLocale);
        System.out.println(bundle.getString("hello"));
    }
}


然后运行,报错

java.util.MissingResourceException: Can't find bundle for base name mess, locale zh_CN

//后来发现还是编码问题

全都用UTF-8编码,文件放在和Hello.java同一目录下。

编译时javac -encoding UTF-8 Hello.java,再执行就可以了。


7.6.4 使用MessageFormat 处理包含占位符的字符串

MessageFormat包含一个静态方法format(String pattern,Object…values); 返回后面多个参数值填充前面的pattern字符串。pattern是一个带占位符的字符串。

msg = Hello,{0}! Today is {1}/

System.out.println(MessageFormat.format(msg,”yeeku”,new Date());


7.6.5 使用类文件代替资源文件

允许使用类文件代替资源文件。

类名必须是 baseName_language_country

必须继承ListResourceBundle,并重写getContents(),该方法返回Object数组,数组每一项都是key-value对。

import java.util.ListResourceBundle;
public class myMess_zh_CN extends ListResourceBundle
{
    private final Object myData[][]=
    {
        {"msg","{0},你好!今天的日期是{1}"}
    };
    public Object[][] getContents()
    {
        return myData;
    }
}



可以替换对应的properties文件。


7.6.6 使用NumberFormat 格式化数字

NumberFormat 和 DateFormat 都包含format()和parse()方法。

用于格式化为字符串和解析字符串。

NumberFormat是一个抽象基类,它提供了几个类方法来获得NumberFormat对象。

getCuttencyInstance():返回默认Locale的货币各时期

getIntergerInstance()

getNumberInstance()

getPercentInstance()

获得NumberFormat对象后,就可以使用它的format()方法格式化数值。



7.6.7 使用DateFormat格式化日期、时间

getDateInstance()

getTimeInstance()

getDateTimeInstance()


7.6.8 使用SimpleDateFormat 格式化日期

SimpleDateFormat可以灵活地格式化Date,也可以用于解析各种格式的日期字符串。创建时传入一个pattern日期模板字符串。


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

7.7.1 使用DateTimeFormat 完成格式化

7.7.2 使用DateTimeFormat 解析字符串


相关文章
|
23天前
|
Java 开发工具 Android开发
Kotlin语法笔记(26) -Kotlin 与 Java 共存(1)
本系列教程笔记详细讲解了Kotlin语法,适合需要深入了解Kotlin的开发者。若需快速学习Kotlin,建议查看“简洁”系列教程。本期重点介绍了Kotlin与Java的共存方式,包括属性、单例对象、默认参数方法、包方法、扩展方法以及内部类和成员的互操作性。通过这些内容,帮助你在项目中更好地结合使用这两种语言。
40 1
|
24天前
|
Java 开发工具 Android开发
Kotlin语法笔记(26) -Kotlin 与 Java 共存(1)
Kotlin语法笔记(26) -Kotlin 与 Java 共存(1)
32 2
|
1月前
|
Java 开发工具 Android开发
Kotlin教程笔记(26) -Kotlin 与 Java 共存(一)
Kotlin教程笔记(26) -Kotlin 与 Java 共存(一)
|
10天前
|
Java 大数据 API
14天Java基础学习——第1天:Java入门和环境搭建
本文介绍了Java的基础知识,包括Java的简介、历史和应用领域。详细讲解了如何安装JDK并配置环境变量,以及如何使用IntelliJ IDEA创建和运行Java项目。通过示例代码“HelloWorld.java”,展示了从编写到运行的全过程。适合初学者快速入门Java编程。
|
14天前
|
安全 Java 编译器
Kotlin教程笔记(27) -Kotlin 与 Java 共存(二)
Kotlin教程笔记(27) -Kotlin 与 Java 共存(二)
|
14天前
|
Java 开发工具 Android开发
Kotlin教程笔记(26) -Kotlin 与 Java 共存(一)
Kotlin教程笔记(26) -Kotlin 与 Java 共存(一)
|
14天前
|
Java 编译器 Android开发
Kotlin教程笔记(28) -Kotlin 与 Java 混编
Kotlin教程笔记(28) -Kotlin 与 Java 混编
|
23天前
|
Java 编译器 Android开发
Kotlin语法笔记(28) -Kotlin 与 Java 混编
本系列教程详细讲解了Kotlin语法,适合需要深入了解Kotlin的开发者。对于希望快速学习Kotlin的用户,推荐查看“简洁”系列教程。本文档重点介绍了Kotlin与Java混编的技巧,包括代码转换、类调用、ProGuard问题、Android library开发建议以及在Kotlin和Java之间互相调用的方法。
20 1
|
23天前
|
安全 Java 编译器
Kotlin语法笔记(27) -Kotlin 与 Java 共存(二)
本教程详细讲解Kotlin语法,适合希望深入了解Kotlin的开发者。若需快速入门,建议查阅“简洁”系列教程。本文重点探讨Kotlin与Java共存的高级话题,包括属性访问、空安全、泛型处理、同步机制及SAM转换等,助你在项目中逐步引入Kotlin。
20 1
|
24天前
|
Java 编译器 Android开发
Kotlin语法笔记(28) -Kotlin 与 Java 混编
Kotlin语法笔记(28) -Kotlin 与 Java 混编
25 2