接上一节...
3.包装类boxing class(Boolean,Byte,Character,Double,Float,Long,Short)
1)
在看这些类的时候我们还是了解一下它们的父类Number吧
它是一个抽象类,只有六个函数public abstract int intValue(),byteValue(),doubleValue(),floatValue(),longValue(),
shortValue(),其中只有byteValue()和shortValue()没有用abstract来修饰,因为它的函数体如下:
public short shortValue() {
return (short)intValue();
}
byteValue()只要把return后面的short换成byte就行了。
所有的方法都没有函数体(除了[byte,short]Value,实际上他们也没有,因为intValue()没有函数体)
2)
这里我们可以先写一个测试类来分析他们的构造函数有哪些异同:这里要用到上一节的工具GetProperties
结果如下:
---------- 运行java ----------
java.lang.Byte:
----------------------Constructors----------------------
java.lang.Byte(String)
java.lang.Byte(byte)
java.lang.Double:
----------------------Constructors----------------------
java.lang.Double(String)
java.lang.Double(double)
java.lang.Float:
----------------------Constructors----------------------
java.lang.Float(String)
java.lang.Float(float)
java.lang.Float(double)
java.lang.Integer:
----------------------Constructors----------------------
java.lang.Integer(String)
java.lang.Integer(int)
java.lang.Character:
----------------------Constructors----------------------
java.lang.Character(char)
java.lang.Long:
----------------------Constructors----------------------
java.lang.Long(long)
java.lang.Long(String)
java.lang.Short:
----------------------Constructors----------------------
java.lang.Short(String)
java.lang.Short(short)
输出完成 (耗时 0 秒) - 正常终止
由结果看出:
他们基本上只有两个构造函数,一个是带相应的基本类型的参数,另外一个是带String参数的构造函数
(Float类有三个构造函数多了一个Float(double value),而Character类只有一个带char的构造函数Character(char))。
首先看看Integer:
定义了MIN_VALUE,MAX_VALUE,它们的值为(-2147483648,2147483647)int占4个字节32位
除了继承了Number中的方法外,还提供了比较的函数(compareTo,equals),还有decode(String)将 String 解码为 Integer,支持16
机制和8进制的字符串,如:"0x23","#123"都为16进制的数,还提供把10进制数变为二,八,十六进制的数的一系列类函数
String toBinaryString(int),String toOctalString(int),toHexString(int)
还有public static int parseInt(String,int)按照后面指定的基数转换为整数,缺省为10进制。
其它的象Byte,Short,Long基本类似
Character:其提供很多的类方法以便修改字符的大小写,判断是否是大,小写、判断是否是数字还是字母等
Float,Double:
注意定义了一个public static final double NaN = 0.0d / 0.0;该值表示的是一个0/0的情况。浮点(Float)和双精度(Double)
提供了isInfinite( )和isNaN( )方法,这些方法会有助于操作两个特殊的双精度(double)和浮点(float)值,这些方法检验两个由
IEEE浮点规范定义的独特的值:无穷和NaN(非具体数字)。当被检验的值为无穷大或无穷小值时,isInfinite( )方法返回true。当被
检验值为非数字时,isNaN( )方法返回true。在下面的例子中构造了两个Double对象;一个是无穷,另一个是非数字
程序运行产生如下的输出:
Infinity: true, false
NaN: false, true
其它情况与Integer相似。
Boolean:
Boolean是一个围绕布尔(boolean)值的非常细小的包装器,主要用在通过引用传递布尔(boolean)变量的场合。它包含了常数TRUE
和FALSE,这些常数定义了布尔(Boolean)对象的真与假。Boolean也定义了TYPE域,它是boolean的Class对象。
4.String ,StringBuffer, StringBuilder
可以说String类是java编程中最常用的类了,它包装了字符创几乎所有的操作,然而我们忽略了很重要的一点,那就是String使用的误
区。从表面看来String类只用一个加号(+)便完成了字符串的拼接,而StringBuffer类却要调用一个append()方法,是否实现起来更
简洁,更单纯呢?其实不然,让我们了解一下程序运行内部发生了哪些事情:
经编译后程序的Bytecode(字节码)展示出了实质: 在用String类对象直接拼接,JVM会创建一个临时的StringBuffer类对
象,并调用其append()方法完成字符串的拼接,这是因为String类是不可变的,拼接操作不得不使用StringBuffer类(并且
--JVM会将"You are nice."和"I love you so much."创建为两个新的String对象)。之后,再将这个临时StringBuffer对象
转型为一个String,代价不菲!可见,在这一个简单的一次拼接过程中,我们让程序创建了四个对象:两个待拼接的String,
一个临时StringBuffer,和最后将StringBuffer转型成为的String--它当然不是最初的str了,这个引用的名称没变,但它
指向了新的String对象。
而如果直接使用StringBuffer类,程序将只产生两个对象:
最初的StringBuffer和拼接时的String("I love you so much."),也不再需要创建临时的StringBuffer类对象而后还得将其
转换回String对象。
可以想象,当我们的字符串要被循环拼接若干段时,用String类直接操作会带来多少额外的系统开销,生成多少无用的临时
StringBuffer对象,并处理多少次无谓的强制类型转换。这种代价太大了!
String类的一些重要函数例如split(String regex, int limit)着重注意后面的参数规定的阈值。见下面的例子:
当limit的取值在能分隔字符个数之内时,s的长度为指定的长度,当limit不在这个范围的时候,s都为最大分割长度,
例如上面limit的取值范围为1-4,在这个范围内,s.length为limit的值,一旦limit不在1-4范围之内,那么s.length都为4。
另外还要注意一点就是当以split("j",0)分割的时候,理论是分割成"f", "", ":", "", "iw:qeo:fas",但是将0改成3的时候生成的
数组为"f","",":jjiw:qeo:fas", 当要生成的数组比最大值要销的时候,合并后的项。
StringBuilder类为1.5版本(包括1.5)后才加上,它是StringBuffer的替代类,但是不保证同步,当在单线程中使用的时候,一般
比StringBuffer还要块,建议单线程的情况优先使用StringBuilder.
5.Thread,Runnable(interface)
这两个类型都是为创建多线程程序而生的。JDK上给出了两个创建的例子。
1)
然后,下列代码会创建并启动一个线程:
PrimeThread p = new PrimeThread(143);
p.start();
2)
然后,下列代码会创建并启动一个线程:
PrimeRun p = new PrimeRun(143);
new Thread(p).start();
在此着重讲一下join函数,think in java上说如果某个线程在另一个线程t上调用t.join(),则此线程被挂起,直到目标线程t结束才
恢复。感觉比较难懂,到底是那个线程被挂起了,还是讲个例子好了:
此函数的意思是在主线程(main函数运行的线程)上调用了t的join函数,所以主线程只有等t线程结束才会执行打印Hello World那行,
如果把t.join()注释掉,则会先打印Helloworld,再打印the thread is running了
6.System
System中包括了一些很有用的类属性和方法,有标准输入、标准输出和错误输出流
字段摘要 :static PrintStream err “标准”错误输出流。
static InputStream in “标准”输入流。
static PrintStream out “标准”输出流。
还有一奇怪的是JDK1.4中不支持static String getenv(String name)函数了,而在JDK1.5及以后的版本中又支持了此函数,另外还
增加了一个不带参数的多态函数,可见这个函数还是比较重要的了, 函数作用在于获取指定的环境变量值。比如我们装JDK的时候
设定的"JAVA_HOME"的值可以用此函数获得,str = getenv("JAVA_HOME")就行了。
此外
static long currentTimeMillis() 返回以毫秒为单位的当前时间与协调世界时 1970 年 1 月 1 日午夜之间的时间差
static void exit(int status) 终止当前正在运行的 Java 虚拟机。 参数用作状态码;根据惯例,非 0 的状态码表示异常终止。
该方法调用 Runtime 类中的 exit 方法。该方法永远不会正常返回。调用 System.exit(n) 实际上等效于调用:
Runtime.getRuntime().exit(n)
static void gc() 运行垃圾回收器。 使虚拟机尽可能的回收从所有丢弃的对象中回收了空间。
还有对外部定义的属性的访问;加载文件和库的方法;还有快速复制数组的一部分的实用方法也比较有用。
7.Runtime, Process类
每个 Java 应用程序都有一个 Runtime 类实例,使应用程序能够与其运行的环境相连接。可以通过getRuntime 方法获取当前Runtime
可以使用其类函数 getRuntime()返回与当前 Java 应用程序相关的运行时对象。
Runtime.exec 方法创建一个本机进程,并返回 Process 子类的一个实例,该实例可用来控制进程并获得相关信息。Process
类提供了执行从进程输入、执行输出到进程、等待进程完成、检查进程的退出状态以及销毁(杀掉)进程的方法。
创建的子进程没有自己的终端或控制台。它的所有标准 io(即 stdin、stdout 和 stderr)操作都将通过三个流
(getOutputStream()、getInputStream() 和 getErrorStream()) 重定向到父进程。父进程使用这些流来提供到子进程的输入和获得
从子进程的输出。
那么这两个类有什么用呢?
在Java中使用Runtime和Process类运行外部程序(对Windows只要是能在cmd中运行的命令都行,对Linux就是shell命令)
以下就是获得机子的MAC地址的程序
输出:
00-50-56-C0-00-08
00-50-56-C0-00-01
00-15-58-67-CD-40
最后一行就是本机的MAC地址。
3.包装类boxing class(Boolean,Byte,Character,Double,Float,Long,Short)
1)
在看这些类的时候我们还是了解一下它们的父类Number吧
它是一个抽象类,只有六个函数public abstract int intValue(),byteValue(),doubleValue(),floatValue(),longValue(),
shortValue(),其中只有byteValue()和shortValue()没有用abstract来修饰,因为它的函数体如下:
public short shortValue() {
return (short)intValue();
}
byteValue()只要把return后面的short换成byte就行了。
所有的方法都没有函数体(除了[byte,short]Value,实际上他们也没有,因为intValue()没有函数体)
2)
这里我们可以先写一个测试类来分析他们的构造函数有哪些异同:这里要用到上一节的工具GetProperties
import
mycom.GetProperties;
//
我的工具类库
class Test
{
public static void main(String[] args) throws Exception
{
String[] name = new String[]{"Byte","Double","Float","Integer","Character","Long","Short"};
StringBuffer str = new StringBuffer("java.lang.");
for(int i=0; i<name.length; i++){
str.append(name[i]);
Class object = Class.forName(str.toString());
System.out.println(" " + object.getName()+ ":");
//GetProperties.printFields(object);
//GetProperties.printMethods(object);
GetProperties.printConstructs(object);
str.delete(10,str.length());
}
}
}
class Test
{
public static void main(String[] args) throws Exception
{
String[] name = new String[]{"Byte","Double","Float","Integer","Character","Long","Short"};
StringBuffer str = new StringBuffer("java.lang.");
for(int i=0; i<name.length; i++){
str.append(name[i]);
Class object = Class.forName(str.toString());
System.out.println(" " + object.getName()+ ":");
//GetProperties.printFields(object);
//GetProperties.printMethods(object);
GetProperties.printConstructs(object);
str.delete(10,str.length());
}
}
}
结果如下:
---------- 运行java ----------
java.lang.Byte:
----------------------Constructors----------------------
java.lang.Byte(String)
java.lang.Byte(byte)
java.lang.Double:
----------------------Constructors----------------------
java.lang.Double(String)
java.lang.Double(double)
java.lang.Float:
----------------------Constructors----------------------
java.lang.Float(String)
java.lang.Float(float)
java.lang.Float(double)
java.lang.Integer:
----------------------Constructors----------------------
java.lang.Integer(String)
java.lang.Integer(int)
java.lang.Character:
----------------------Constructors----------------------
java.lang.Character(char)
java.lang.Long:
----------------------Constructors----------------------
java.lang.Long(long)
java.lang.Long(String)
java.lang.Short:
----------------------Constructors----------------------
java.lang.Short(String)
java.lang.Short(short)
输出完成 (耗时 0 秒) - 正常终止
由结果看出:
他们基本上只有两个构造函数,一个是带相应的基本类型的参数,另外一个是带String参数的构造函数
(Float类有三个构造函数多了一个Float(double value),而Character类只有一个带char的构造函数Character(char))。
首先看看Integer:
定义了MIN_VALUE,MAX_VALUE,它们的值为(-2147483648,2147483647)int占4个字节32位
除了继承了Number中的方法外,还提供了比较的函数(compareTo,equals),还有decode(String)将 String 解码为 Integer,支持16
机制和8进制的字符串,如:"0x23","#123"都为16进制的数,还提供把10进制数变为二,八,十六进制的数的一系列类函数
String toBinaryString(int),String toOctalString(int),toHexString(int)
还有public static int parseInt(String,int)按照后面指定的基数转换为整数,缺省为10进制。
其它的象Byte,Short,Long基本类似
Character:其提供很多的类方法以便修改字符的大小写,判断是否是大,小写、判断是否是数字还是字母等
Float,Double:
注意定义了一个public static final double NaN = 0.0d / 0.0;该值表示的是一个0/0的情况。浮点(Float)和双精度(Double)
提供了isInfinite( )和isNaN( )方法,这些方法会有助于操作两个特殊的双精度(double)和浮点(float)值,这些方法检验两个由
IEEE浮点规范定义的独特的值:无穷和NaN(非具体数字)。当被检验的值为无穷大或无穷小值时,isInfinite( )方法返回true。当被
检验值为非数字时,isNaN( )方法返回true。在下面的例子中构造了两个Double对象;一个是无穷,另一个是非数字
class
InfNaN
{
public static void main(String args[]) {
Double d1 = new Double(1/0.);
Double d2 = new Double(0/0.);
System.out.println(d1 + ": " + d1.isInfinite() + ", " + d1.isNaN());
System.out.println(d2 + ": " + d2.isInfinite() + ", " + d2.isNaN());
}
}
public static void main(String args[]) {
Double d1 = new Double(1/0.);
Double d2 = new Double(0/0.);
System.out.println(d1 + ": " + d1.isInfinite() + ", " + d1.isNaN());
System.out.println(d2 + ": " + d2.isInfinite() + ", " + d2.isNaN());
}
}
程序运行产生如下的输出:
Infinity: true, false
NaN: false, true
其它情况与Integer相似。
Boolean:
Boolean是一个围绕布尔(boolean)值的非常细小的包装器,主要用在通过引用传递布尔(boolean)变量的场合。它包含了常数TRUE
和FALSE,这些常数定义了布尔(Boolean)对象的真与假。Boolean也定义了TYPE域,它是boolean的Class对象。
4.String ,StringBuffer, StringBuilder
可以说String类是java编程中最常用的类了,它包装了字符创几乎所有的操作,然而我们忽略了很重要的一点,那就是String使用的误
区。从表面看来String类只用一个加号(+)便完成了字符串的拼接,而StringBuffer类却要调用一个append()方法,是否实现起来更
简洁,更单纯呢?其实不然,让我们了解一下程序运行内部发生了哪些事情:
经编译后程序的Bytecode(字节码)展示出了实质: 在用String类对象直接拼接,JVM会创建一个临时的StringBuffer类对
象,并调用其append()方法完成字符串的拼接,这是因为String类是不可变的,拼接操作不得不使用StringBuffer类(并且
--JVM会将"You are nice."和"I love you so much."创建为两个新的String对象)。之后,再将这个临时StringBuffer对象
转型为一个String,代价不菲!可见,在这一个简单的一次拼接过程中,我们让程序创建了四个对象:两个待拼接的String,
一个临时StringBuffer,和最后将StringBuffer转型成为的String--它当然不是最初的str了,这个引用的名称没变,但它
指向了新的String对象。
而如果直接使用StringBuffer类,程序将只产生两个对象:
最初的StringBuffer和拼接时的String("I love you so much."),也不再需要创建临时的StringBuffer类对象而后还得将其
转换回String对象。
可以想象,当我们的字符串要被循环拼接若干段时,用String类直接操作会带来多少额外的系统开销,生成多少无用的临时
StringBuffer对象,并处理多少次无谓的强制类型转换。这种代价太大了!
String类的一些重要函数例如split(String regex, int limit)着重注意后面的参数规定的阈值。见下面的例子:
class
StringTest
{
public static void main(String[]args){
String str = "fjj:jjiw:qwo:fas";
String [] s = str.split(":",4);//
for(int i=0; i<s.length; i++)
System.out.println(s[i]);
}
public static void main(String[]args){
String str = "fjj:jjiw:qwo:fas";
String [] s = str.split(":",4);//
for(int i=0; i<s.length; i++)
System.out.println(s[i]);
}
当limit的取值在能分隔字符个数之内时,s的长度为指定的长度,当limit不在这个范围的时候,s都为最大分割长度,
例如上面limit的取值范围为1-4,在这个范围内,s.length为limit的值,一旦limit不在1-4范围之内,那么s.length都为4。
另外还要注意一点就是当以split("j",0)分割的时候,理论是分割成"f", "", ":", "", "iw:qeo:fas",但是将0改成3的时候生成的
数组为"f","",":jjiw:qeo:fas", 当要生成的数组比最大值要销的时候,合并后的项。
StringBuilder类为1.5版本(包括1.5)后才加上,它是StringBuffer的替代类,但是不保证同步,当在单线程中使用的时候,一般
比StringBuffer还要块,建议单线程的情况优先使用StringBuilder.
5.Thread,Runnable(interface)
这两个类型都是为创建多线程程序而生的。JDK上给出了两个创建的例子。
1)
class
PrimeThread
extends
Thread
{
long minPrime;
PrimeThread(long minPrime) {
this.minPrime = minPrime;
}
public void run() {
// compute primes larger than minPrime
. . .
}
}
long minPrime;
PrimeThread(long minPrime) {
this.minPrime = minPrime;
}
public void run() {
// compute primes larger than minPrime
. . .
}
}
然后,下列代码会创建并启动一个线程:
PrimeThread p = new PrimeThread(143);
p.start();
2)
class
PrimeRun
implements
Runnable
{
long minPrime;
PrimeRun(long minPrime) {
this.minPrime = minPrime;
}
public void run() {
// compute primes larger than minPrime
. . .
}
}
long minPrime;
PrimeRun(long minPrime) {
this.minPrime = minPrime;
}
public void run() {
// compute primes larger than minPrime
. . .
}
}
然后,下列代码会创建并启动一个线程:
PrimeRun p = new PrimeRun(143);
new Thread(p).start();
在此着重讲一下join函数,think in java上说如果某个线程在另一个线程t上调用t.join(),则此线程被挂起,直到目标线程t结束才
恢复。感觉比较难懂,到底是那个线程被挂起了,还是讲个例子好了:
class
JoinTest
extends
Thread
{
public JoinTest(){
super();
}
public void run() {
try{
sleep(3000);
}catch(Exception e){
e.printStackTrace();
}
System.out.println("the thread is running...");
}
public static void main(String[] args) throws Exception
{
JoinTest t = new JoinTest("th1");
//
t.start();
t.join();
System.out.println("Hello World!");
}
}
public JoinTest(){
super();
}
public void run() {
try{
sleep(3000);
}catch(Exception e){
e.printStackTrace();
}
System.out.println("the thread is running...");
}
public static void main(String[] args) throws Exception
{
JoinTest t = new JoinTest("th1");
//
t.start();
t.join();
System.out.println("Hello World!");
}
}
此函数的意思是在主线程(main函数运行的线程)上调用了t的join函数,所以主线程只有等t线程结束才会执行打印Hello World那行,
如果把t.join()注释掉,则会先打印Helloworld,再打印the thread is running了
6.System
System中包括了一些很有用的类属性和方法,有标准输入、标准输出和错误输出流
字段摘要 :static PrintStream err “标准”错误输出流。
static InputStream in “标准”输入流。
static PrintStream out “标准”输出流。
还有一奇怪的是JDK1.4中不支持static String getenv(String name)函数了,而在JDK1.5及以后的版本中又支持了此函数,另外还
增加了一个不带参数的多态函数,可见这个函数还是比较重要的了, 函数作用在于获取指定的环境变量值。比如我们装JDK的时候
设定的"JAVA_HOME"的值可以用此函数获得,str = getenv("JAVA_HOME")就行了。
此外
static long currentTimeMillis() 返回以毫秒为单位的当前时间与协调世界时 1970 年 1 月 1 日午夜之间的时间差
static void exit(int status) 终止当前正在运行的 Java 虚拟机。 参数用作状态码;根据惯例,非 0 的状态码表示异常终止。
该方法调用 Runtime 类中的 exit 方法。该方法永远不会正常返回。调用 System.exit(n) 实际上等效于调用:
Runtime.getRuntime().exit(n)
static void gc() 运行垃圾回收器。 使虚拟机尽可能的回收从所有丢弃的对象中回收了空间。
还有对外部定义的属性的访问;加载文件和库的方法;还有快速复制数组的一部分的实用方法也比较有用。
7.Runtime, Process类
每个 Java 应用程序都有一个 Runtime 类实例,使应用程序能够与其运行的环境相连接。可以通过getRuntime 方法获取当前Runtime
可以使用其类函数 getRuntime()返回与当前 Java 应用程序相关的运行时对象。
Runtime.exec 方法创建一个本机进程,并返回 Process 子类的一个实例,该实例可用来控制进程并获得相关信息。Process
类提供了执行从进程输入、执行输出到进程、等待进程完成、检查进程的退出状态以及销毁(杀掉)进程的方法。
创建的子进程没有自己的终端或控制台。它的所有标准 io(即 stdin、stdout 和 stderr)操作都将通过三个流
(getOutputStream()、getInputStream() 和 getErrorStream()) 重定向到父进程。父进程使用这些流来提供到子进程的输入和获得
从子进程的输出。
那么这两个类有什么用呢?
在Java中使用Runtime和Process类运行外部程序(对Windows只要是能在cmd中运行的命令都行,对Linux就是shell命令)
以下就是获得机子的MAC地址的程序
import
java.io.
*
;
class PRuntime
{
public static void main(String[] args) throws Exception
{
String line, physicalAddress="";
Process p = Runtime.getRuntime().exec("cmd.exe /c ipconfig/all");
BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()));
while((line = in.readLine()) != null){
if(line.indexOf("Physical Address. . . . . . . . . :") != -1){
physicalAddress = line.substring(line.indexOf(":")+2);
System.out.println(physicalAddress);
}
}
in.close();
}
}
class PRuntime
{
public static void main(String[] args) throws Exception
{
String line, physicalAddress="";
Process p = Runtime.getRuntime().exec("cmd.exe /c ipconfig/all");
BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()));
while((line = in.readLine()) != null){
if(line.indexOf("Physical Address. . . . . . . . . :") != -1){
physicalAddress = line.substring(line.indexOf(":")+2);
System.out.println(physicalAddress);
}
}
in.close();
}
}
输出:
00-50-56-C0-00-08
00-50-56-C0-00-01
00-15-58-67-CD-40
最后一行就是本机的MAC地址。