Oracle为Java提供了丰富的基础类库,Java8提供了4000多个基础类(包括集合框架)
通过这些基础类库,可以提高开发效率,降低开发难度。
Java提供了String、StringBuffer和StringBuilder来处理字符串,它们之间有少许差别。
Java还提供了Date和Calendar来处理,但通常推荐用Calendar来处理日期时间。
正则表达式是一个强大的文本处理工具,通过正则表达式可以对文本内容进行查找、替换、分割等操作。从JDK1.4以后,Java也增加了对正则表达式的支持,包括新增的Pattern和Matcher两个类,并改写了String类,让String类增加了正则表达式的支持,增加了正则表达式功能后的String类更加强大
Java还提供了简单的国际化支持,Java使用Locale封装一个国家、语言环境,再使用ResourceBundle根据Locale加载语言资源包加载语言资源包,当ResourceBundle加载了指定Locale对应资源文件,ResourceBundle加载了指定Locale对应的语言资源文件后,ResourceBundle对象就可以调用getString方法来取出指定key所对应的消息字符串。
使用Scanner获取键盘输入
运行Java程序时传入参数只能在程序开始运行之前就设定几个固定的参数,使用Scanner类可以很方便的获取用户的键盘输入,Scanner是一个基于正则表达式的文本扫描器。
它可以从文件、输入流、字符串中解析出基本类型值和字符串值。Scanner类提供了多个构造器。
Scanner主要提供了两个方法来扫描输入项
hasNextXxx是否还有下一个输入项
nextXxx是否还有下一个输入项
默认情况下,Scanner使用空白作为多个输入项之间的分隔符。
也可以读文件。
System类代表当前Java的程序的运行平台,程序不能创建System类的对象。System类提供了一些类变量和类方法,允许直接通过System类来调用这些类变量和类方法。
System类提供了代表标准输入、标准输出和错误输出的类的变量,并提供了一些静态方法用于访问环境变量、系统属性的方法,还提供了加载文件和动态链接库的方法。
加载文件和动态链接库主要对native方法有用,对于一些特殊的功能(如访问操作系统的底层设备)Java程序无法实现,必须借助C语言来为Java方法提供实现,其实现步骤如下。
1、Java程序中声明native修饰的方法,类似于abstract方法,只有方法签名,没有实现。编译该Java程序生成一个class文件。
2、javah编译第一步生成的class文件,将产生一个.h文件
3、写一个.cpp文件实现实现native方法,这一步需要包含第二部生成的.h文件
4、将第三步的cpp编译成动态链接库
5、在Java中用System类的loadLibrary()或Runtime类的loadLibrary方法加载动态链接库文件,Java程序中就可以调用这个native方法了。
System类提供了通知系统进行垃圾回收的gc方法,以及通知系统进行资源清理的runFinalization方法。
System类还有两个获取系统当前时间的方法:currentTimeMillis和nanaTime,它们都返回一个long型整数值,实际上都返回的是UTC1970年1月1日的时间差,前者以毫秒作为单位,后者以纳秒作为单位。
nanoTime很少用,因为大部分操作系统都不支持使用纳秒作为计时单位。
除此之外System类的in、out、err分别代表,标注输入(通常是键盘)、标准输出(通常是显示器) 和错误输出流,并提供了setIn、setOut和seterr来改变系统的标准输入、标准输出和标准错误输出流。
System类还提供了一个identityHashCode方法,该方法返回对象的精确hashCode值,也就是根据该对象的地址计算得到的hashCode。
当某个类的hashCode方法被重写后,该类的实例hashCode方法就不能唯一标识该对象。但identityHashCode方法返回 的依然是通过地址得到的hashCode值。所以两个对象的identityHashCode值相同,两个对象绝对是同一个对象。
Runtime类代表Java运行时环境,每个Java程序都有一个与之对应的Runtime实例,应用程序通过该对象与运行时环境相连。
应用程序不能创建自己的Runtime实例,但可以通过getRuntime方法获取与之相关的Runtime对象。
Runtime类代表Java程序运行时环境,可以访问jvm相关信息:处理器数量、内存信息
runtime还可以直接启动一个进程来运行操作系统的命令
常用类:
Object类
Object类是所有类、数组、枚举类的父类。
也就是说Java允许把任何对象赋值给Object类的变量。
当定义一个类时没有用extends关键字为它显式指定父类,则该类默认继承Object类。
因为所有的Java类都是Object类的子类,所以任何Java对象都可以调用Object类的方法
equals方法、finalize方法、getclass方法、hashcode方法,tostring方法
除此之外还有wait、notify、notifyAll方法
Java还提供一个protected修饰的clone方法,该方法用于帮助其他对象来实现克隆,所谓的克隆就是得到当前对象的副本,而且二者之间完全隔离。
自定义类实现克隆的步骤如下:
1自定义类实现Cloneable接口,这是一个标记性的接口,实现该接口可以实现自我克隆,接口里没有定义任何方法
2自定义类实现clone方法
3实现clone方法时。通过super.clone调用Object实现的clone方法来得到该对象的副本,并返回该副本。
需要指出的是,Object类的clone方法虽然简单易用,但它只是一种浅克隆,只克隆该对象的所有成员变量值,不会对引用类型的成员变量值送引用的对象进行克隆。如果开发者需要对对象进行深克隆,需要开发者自己进行递归克隆,保证所有引用类型的成员变量值引用的对象都被复制了。
字符串就是一连串的字符序列
Java提供了String、StringBuffer两个类来封装字符串,并提供了一些列方法来操作字符串对象。
String类是不可变类,一个String对象被创建后,包含在这个对象中的字符序列是不可改变的,知道这个对象被销毁。
StringBuffer对象则代表一个字符序列可变的字符串,当一个StringBuffer被创建后,通过提供的append、insert、reverse、setCharAt、setlength等方法可以改变这个字符串对象的序列。
StringBuilder和StringBuffer基本相同,但是StringBuffer是线程安全的。通常情况下因为StringBuilder没有实现线程安全,所以性能略高。
String、StringBuilder、StringBuffer都实现了CharSequence接口因此CharSequence可以认为是一个字符串协议接口
Math类
Java提供了基本的加减乘除的运算符,但是对于更复杂的数学运算,例如三角函数、对数函数、指数运算则无能为力
Java提供了Math类,Math类是一个工具类,它的构造器定义成私有的了。
Math类除了提供大量的静态方法外,还提供了两个常量:PI和E
Random类专门生成一个伪随机数,有两个构造器:一个构造器使用默认的种子(当前时间)、另一个是需要显示传入一个long的种子。
ThreadLocalRandom是一个Java7新增的类,它是Random的增强版。在并发访问的环境下,使用ThreadLocalRandom来代替Random可以减少多线程资源竞争,最终保证系统具有更好的线程安全。
BIgDecimal类
float和double两种基本浮点类型任意引起精度丢失。
为了可以精确表示计算浮点数,Java提供了BigDecimal类,该类提供了大量的构造器用于创建BigDecimal对象,包括把所有的基本数值型变量转换成一个BigDecimal对象,也包括利用数字字符串、数字字符数组来创建BigDecimal对象。
当程序使用new BigDecimal(0.1)创建一个BigDecimal对象时,它的值并不是0.1,它实际上等于一个近似0.1的数的数字。因为0.1无法准确表示为double浮点数,所以传入BigDecimal构造器的值不会正好等于0.1(虽然表面上等于该值)
所以推荐使用字符串String构造BigDecimal
如果必须使用double浮点数作为BigDecimal构造器的参数,不要直接用double构造对象,而是提过BigDecimal.valueOf(double value)静态方法创建BigDecimal对象。
BigDecimal类提供了add、substract、multipy、divide、pow等方法对精确浮点数进行常规运算。
Date类
总体来说,Date是一个设计相当糟糕的类,因此Java推荐尽量减少使用Date构造器和方法,如果需要对日期时间进行加减运算,或获取时间的年月日等信息,可以使用Calendar工具类。
Calendar类
因为Date类在设计上存在一些缺陷,所以Java提供了Calendar类
add与roll的区别
roll修改的字段超过允许的范围时,上级字段不会增大。
正则表达式是一个强大的字符串处理工具,可以对字符串进行查找、提取、分割、替换等操作
String类也提供了几种特殊的方法
boolean matches(String regex)
String replaceAll(String regex,String replacement)
String replaceFirst(String regex,String replacement)
String[] split(String regex)
创建正则表达式
正则表达式就是一个用于匹配字符串的模板,可以匹配一批字符串,所以创建正则表达式就是创建一个特殊的字符串。
d是digit数字
s是space空白
w是word单词
d、s、w的大写形式恰好匹配与之相反的字符。
使用正则表达式,一旦在程序中定义了正则表达式就可以使用pattern和matcher来使用正则表达式
patten对象是正则表达式编译后在内存中的表示形式,因此正则表达式字符串必须先被编译为Pattern对象,任何再利用该Pattern对象创建对应的Matcher对象。
执行匹配所设计的状态保留再Matcher对象中,多个Matcher对象可以共享一个Pattern对象。
上面语句等效于前面的三句语句。但 采用这种语句每次都需要重新编译新的Pattern对象
国际化与格式化
全球化的Internet需要全球化的软件。全球化软件意味着同一种版本的产品能够容易地适用于不同地区的市场,软件的全球化意味着国际化和本地化。
当一个应用需要在全球范围使用时,就必须考虑在不同的地域和语言环境下使用情况,最简单的要求就是用户界面上的信息可以用本地化语言来显示。
国际化是指应用程序运行时,可以根据客户端请求来自的国家和地区、语言的不同来显示不同的界面。
Java程序的国际化思路是将程序中的标签、提示等信息放在资源文件中,程序需要支持哪些国家、语言环境,就对应提供相应的资源文件。
资源文件是key-value对,每个资源文件中的key是不变的,但value则随不同的国家、语言而改变。
java.util.Resourcebundle:用于加载国家、语言资源包
java.util.Locale:用于封装特定的国家/地区、语言环境
java.text.MessageFormat:用于格式化带占位符的字符串
为了实现程序的国际化,必须先提供程序所需要的资源文件。资源文件的内容是很多key-value对,其中key是程序使用的部分,而value则是程序界面显示字符串。
资源文件的命名可以有如下三种形式。
其中baseName可以随意定,而language和country都不可以随意变化,必须是Java所支持的语言和国家。
事实上,Java不可能支持所有的国家和语言,如果需要获取Java所支持的国家和语言,则可以调用Locale类的getAvailableLocales()方法,该方法返回一个Locale数组,该数组里包含了Java所支持的国家和语言。
虽然可以通过查阅相关资料来获取Java语言所支持的国家/语言环境,但如果这些子类不能随手可得,则可以通过上面的程序来获得Java语言所支持的国家/语言环境
第一个文件是mess.properties,该文件的内容是
第二个文件:mess_en_US.properties,该文件内容是
然后用native2ascii工具在javahome/bin下
然后输入命令
生成了一个mess_zh_CN.propertie文件,该文件才是需要的资源文件。
从上面的程序可以看出如果希望程序完成国际化,只需要将不同的国家语言的提示信息分别以不同的文件存放即可。
例如简体中文的语言资源文件就是Xxx_zh_CN.properties文件,而美国的语言资源文件就是Xxx_en_US.properties文件。
Java程序国际化的关键类是ResourceBundle,它有一个静态方法,getBundle(String baseName,Locale locale),该方法根据Locale加载资源文件,而Locale封装了一个国家语言,例如简体中文环境,可以用简体中文的Locale代表,英语环境可以用英语的Locale代表。
从上面资源文件的命名中可以看出,不同国家、语言环境的资源文件的baseName是相同的,即baseName为mess的资源文件有很多个,不同的国家、语言环境对应不同的资源文件。