Java 类库就是 Java API( 应用程序接口 ),是系统提供的已实现的标准类集合,使用 Java 类库可以完成涉及字符串处理、图形、网络等多方面的操作。
API( Application Programming Interface )就是应用程序编程接口,它是软件系统不同组成部分衔接的约定。API 可以理解为是一些预先定义的函数。其设计目的在于,可以提供应用程序得以访问某些特定软件或硬件的能力,而又无需获知这些软硬件的源码,也无需理解它们的内部工作机制细节。这既方便了应用开发人员,同时也能在一定程度上,保护了软硬件的知识产权。
假设现在要编写一个机器人程序,去控制一个机器人的行为,程序需要向机器人发出各种行动命令,如果有编程经验的人会知道,机器人厂商一定会提供一些控制这些机器人的 Java 类,该类中就有操纵杆机器人各种动作的方法,只需要为每个机器人安排一个该类的实例对象,再调用这个对象的各种方法,机器人就会去执行各种动作。这个 Java 类就是机器人厂家提供的应用程序编程的接口,厂家就可以对这些 Java 类美名其曰:Xxx Robot API( 也就是 Xxx 厂家的机器人 API )。好的机器人厂家不仅会提供 Java 程序用的 Robot API,也会提供 Windows 编程语言( 如 VC++ )用的 Robot API,以满足各类编程人员的需要。
Java 对数据既提供基本数据的简单类型,也提供了相应的包装类。使用基本数据类型,可以改善系统的性能,也能够满足大多数的应用需求。但基本数据类型不具有对象的特性,不能满足某些特殊的需求。从 JDK 中可以知道, Java 中的很多类的很多方法的参数类型都是 Object,即这些方法接收的参数都是对象,同时,又需要用这些方法来处理基本数据类型的数据,这时就要用到包装类。比如,用 Integer 类来包装整数。
Java 中的基本数据类型共有 8 种,name与之相对应的基本数据类型包装类也同样有 8 种,下表列出其对应关系:
基本数据类型 | 基本数据类型包装类 |
int | Integer |
char | Character |
float | Float |
double | Double |
byte | Byte |
long | Long |
short | Short |
boolean | Boolean |
举例:
//使用包装类
class IntegerDemo
{
public static void main(String[] args)
{
String a = "123"; //定义一个字符串
int i = Integer.parseInt(a); //将字符串转换成整型
i++; //将i在原有数值上加1
System.out.println(i); //输出i的值
}
}
此例使用 Integer 类中的 parseInt() 方法,将一个字符串转换成基本数据类型。
1.装箱与拆箱
所谓装箱,就是把基本数据类型用它们相对应的引用类型包起来,使它们可以具有对象的特质,例如我们可以把 int 型包装成 Integer 类的对象,或者把 double 包装成 Double 等。
所谓拆箱,就是跟装箱的方向相反,将 Integer 及 Double 这样的引用类型的对象重新简化为值类型的数据。
JDK 1.5 之前使用手动方式进行装箱和拆箱的操作,JDK 1.5 之后可自动进行装箱和拆箱的操作。
举例:
//包装类的使用
public class Int_Integer
{
public static void main(String[] args)
{
Integer x = new Integer(10); //基本类型变为包装类,装箱
int temp = x.intValue(); //包装类变为基本类型,拆箱
System.out.println(temp * temp); //输出 temp与 temp的乘积
}
}
装箱操作:将基本数据类型变为包装类,利用各个包装类的构造方法完成。
拆箱操作:将包装类变为基本数据类型,利用 Number 类的 xxxValue() 方法完成。
2.基本数据类型与字符串的转换
使用包装类有一个最大的操作特点:可以将字符串变为指定的基本类型,使用的方法如下( 部分 ):
Integer为例:public static int ParseInt(String s);
Double为例:public static double ParseDouble(String s);
Boolean为例:public static Boolean ParseBoolean(String s);
但是以上的操作方法形式对于 Character 是不存在的,因为 String 类有一个 charAt() 方法可以取得指定索引的字符。
举例:
//将字符串变为double型数据
public class DoubleDemo
{
public static void main(String[] args)
{
String str = "123.4"; //定义一个字符串
double x = Double.parseDouble(str); //将字符串变为 double 型
System.out.println(x);
}
}
在将字符串变为数值型数据时需要注意,字符串的组成必须全部由数字组成。
举例:
//将字符串变为boolean型数据
public class BooleanDemo
{
public static void main(String[] args)
{
String str = "true"; //定义一个字符串
boolean flag = Boolean.parseBoolean(str); //将字符串转化为boolean型数据
if (flag) { //如果条件为真输出相应提示
System.out.println("条件满足");
}else { //如果条件为假输出相应提示
System.out.println("条件不满足");
}
}
}
如果此时的字符串内容不是 true 或 false,那么程序也不会出错,会按照 false 的情况进行处理。
通过以上的操作可以将字符串变为基本数据类型,那么反过来,对于将一个基本类型变为字符串的操作,Java 提供了两种做法。如下:
(1)任何的基本数据类型遇见 String 之后自动变为字符串。
(2)利用 String 类之中提供的一系列 valueOf() 方法完成。
举例( 方式一 ):
//将基本类型变为字符串
public class ToString
{
public static void main(String[] args)
{
int x = 100;
String str = x + ""; //任何类型与字符串相加之后就是字符串
System.out.println(str);
}
}
这种方式必须使用一个字符串,所以一定会产生垃圾,不建议使用。
举例( 方式二 ):
//将基本类型变为字符串
public class ToString
{
public static void main(String[] args)
{
int x = 100;
String str = String.valueOf(x); //int变为String
System.out.println(str);
}
}
这种做法更方便使用,所以在日后开发中如果遇见基本类型变为 String 的操作建议使用方式二完成。
1. System 类
Java 不支持全局方法和变量,Java 设计者将一些系统相关的重要方法和变量收集到了一个统一的类中,这就是 System 类。System 类中的所有成员都是静态的,而要引用这些变量和方法,可直接使用 System 类名作为前缀。之前已使用到了标准输入和输出的 in 和 out 变量,以下介绍 System 类中的几个方法,其他的方法可以参阅 JDK 文档资料。
exit(int status) 方法:提前终止虚拟机的运行。对于发生了异常情况而想终止虚拟机的运行,传递一个非零值作为参数。若在用户正常操作下终止虚拟机的运行,则传递零值作为参数。
CurrentTimeMillis 方法:返回自 1970 年 1 月 1 日 0 点 0 分 0 秒起至今的以毫秒为单位的时间,这是一个 long 类型的大数值。在计算机内部只有数值,没有真正的日期类型及其他各种类型,也就是说,平常用到的日期实质上就是一个数值,但通过这个数值,能够推算出其对应的具体日期时间。
getProperties 方法 :获得当前虚拟机的环境属性。每一个属性都是变量与值以成对的形式出现的。
同理,Java 作为一个虚拟的操作系统,它也有自己的环境属性。Properties 是 Hashtable 的子类,正好可以用于存储环境属性中的多个 “ 变量/值 ” 对格式的数据,getProperties 方法返回值是包含了当前虚拟机的所有环境属性的 Properties 类型的对象。
下面演示打印出当前虚拟机的所有环境属性的变量和值:
//打印当前虚拟机的所有环境属性和变量的值
import java.util.*;
public class Systeminfo
{
public static void main(String[] args)
{
Properties sp = System.getProperties(); //获取当前虚拟机的环境属性
Enumeration e = sp.propertyNames(); //获取环境属性中所有的变量
//循环打印出当前虚拟机的所有环境属性的变量和值
while (e.hasMoreElements()) {
String key = (String) e.nextElement();
System.out.println(key + " = " + sp.getProperty(key));
}
}
}
2.Runtime 类
在 Java 程序运行时,每一个 JVM 进程之中都会存在唯一的一个 Runtime 类的实例化对象。这个类是一个明显的单例设计模式,此类将构造方法私有化了,既然是单例设计模式,那么一定会在类的内部提供一个 static 定义的方法,用于取得本类的实例化对象。
取得 Runtime 类对象:public static Runtime getRuntime();
取得了 Runtime 类的实例化对象之后,可以利用以下的方法取得一些内存的相关信息。
最大可用内存数:public long maxMemory();
总共的可用内存数:public long totalMemory();
空闲内存数:public long freeMemory();
那么如果在程序之中出现了过多的垃圾,则一定会影响性能,此时可以利用 Runtime 类的如下方法清除垃圾:public void gc()。
举例:
//取得内存值
public class GetMemorySize
{
public static void main(String[] args)
{
//获取正在运行的Runtime对象的引用
Runtime run = Runtime.getRuntime(); //单例设计
String str = ""; //定义一个字符串
//通过循环产生垃圾
for (int x = 0; x < 5000; x++) {
str += x; //垃圾产生
}
System.out.println("1.最大可用内存:" + run.maxMemory());
System.out.println("1.总共可用内存:" + run.totalMemory());
System.out.println("1.空闲内存:" + run.freeMemory());
run.gc(); //清除垃圾
System.out.println("———————————————————————————————");
System.out.println("2.最大可用内存:" + run.maxMemory());
System.out.println("2.总共可用内存:" + run.totalMemory());
System.out.println("2.空闲内存:" + run.freeMemory());
}
}
由于历史上设计的原因,Java 中有关时间的 API 比较混乱,在最早的 java.util.Date 之后,Java 提供了 jdbc 中使用的 java.sql.Date,以及随后增加用于本地化时间的 Calendar 类。解决原先的时间 API 令人迷惑,不够易用的问题,Java 8 中引入了 java.time 包来彻底改变这个让人讨厌的时间 API。需要注意的是新的时间类都是不可改变并且线程安全的。那么现在来看一下如何表示日期、时间。
1.日期类
日期类及其说明如下表所示:
类名 | 说明 |
LocalDateTime | 存储了日期和时间,如 2014-08-27T14:43:14.539 |
LocalDate | 存储了日期,如 2014-08-25 |
LocalTime | 存储了时间,如 14:43:14.539 |
上面的类可以由下面的类组合。Year 表示年份,Month 表示月份,YearMonth 表示年月,MonthDay 表示月日,DayOfWeek 存储星期的一天。
举例:
//取得当前的日期时间
import java.time.*;
public class GetDatetime
{
public static void main(String[] args)
{
//新建一个LocalDateTime对象获取当前时间
LocalDateTime localDateTime = LocalDateTime.now();
System.out.println(localDateTime); //直接输出对象
}
}
此处的输出结果相较于 Java 7 中的 java.util.Date 更加的清晰易懂。符合国人习惯。
Java 8 在 java.util.time 中提供了许多实用方法。如判断是否闰年、同月日关联到另一年份等。
举例:
//判断是否闰年
import java.time.*;
public class LeapYear
{
public static void main(String[] args)
{
//用指定的年获取一个Year
Year year1 = Year.of(2019);
//从Year获取YearMonth
YearMonth yearMonth = year1.atMonth(2);
//YearMonth指定日期得到LocalDate
LocalDate localDate2 = yearMonth.atDay(5);
System.out.println("时间:" + localDate2);
//判断是否是闰年
System.out.println("是否为闰年:" + localDate2.isLeapYear());
//自动处理闰年的2月日期
//创建一个MonthDay
MonthDay monthDay = MonthDay.of(2, 5);
LocalDate leapYear = monthDay.atYear(2019);
System.out.println("闰年:" + leapYear);
//同一个MonthDay关联到另一个年份上
LocalDate nonLeapYear = monthDay.atYear(2020);
System.out.println("非闰年:" + nonLeapYear);
}
}
Java.time 的 API 提供了大量相关的方法。如下表:
方法 | 说明 |
of | 静态工厂方法,如:Year.of(2019) |
parse | 静态工厂方法,关注于解析 |
get | 获取某些东西的值 |
is | 检查某些东西的是否是 true |
with | 不可变的 setter 等价物 |
plus | 加一些量到某个对象 |
minus | 从某个对象减去一些量 |
to | 转换到另一个类型 |
at | 把这个对象与另一个对象组合起来 |
2.日期格式化类
在某些情况下,开发者可能要对日期对象进行转换。例如,程序中用的另外一个类的方法要求一个 LocalDate 类型的参数。有时,要将用到 LocalDate 对象表示的日期以指定的格式输出,或将用特定格式显示的日期字符串转换成一个 LocalDate对象,java.time.format 包是专门用来格式化输出时间/日期的。
举例:
//将时间对象格式化为字符串
import java.time.*;
import java.time.format.*;
public class DateFormatDemo
{
public static void main(String[] args)
{
//获取当前时间
LocalDate localDate = LocalDate.now();
//指定格式化规则
DateTimeFormatter f = DateTimeFormatter.ofPattern("dd/MM/uuuu");
//将当前时间格式化
String str = localDate.format(f);
System.out.println("时间:" + str);
}
}
String 是一种功能强大的数据类型,但在进行 String 类的操作之中,除了 String 类本身所具备的若干方法之外,String 也可以利用正则表达式完成一些更为复杂的操作以及验证。
1.正则的引出
举例:
//判断字符串是否由数字组成
public class JudgeString
{
public static void main(String[] args) throws Exception
{
if (isNumber("123")) { //判断字符串是否有数字组成
System.out.println("由数字组成");
}else {
System.err.println("不是由数字组成");
}
}
public static boolean isNumber(String str)
{
char data[] = str.toCharArray(); //将字符串转化成char数组
for (int x = 0; x < data.length; x++) { //循环遍历该数组
if (data[x]<'0' || data[x]>'9') { //判断数组中的每个元素是否是数字
return false;
}
}
return true;
}
}
如果是一些更为复杂的验证,那么按照如上方式所编写的代码肯定更多,所以此时,代码可以简化为如下形式:
//应用正则表达式
public class RegExp
{
public static void main(String[] args) throws Exception
{
if ("123".matches("\\d+")) { //利用正则表达式
System.out.println("由数字组成");
}else {
System.err.println("不是由数字组成");
}
}
}
在程序之中出现的 “ \\d+ ” 实际上就属于正则表达式的概念,我们发现使用正则表达式可以简化我们的程序。在 JDK 1.4 之前,Java 本身是不具备正则的操作支持的,如果需要使用正则,则需要通过 apache 下载一个正则的开发包。而到了 JDK 1.4 之后,Java 开始支持了正则,同时给出了 java.util.regex 开发包,此包提供了正则的操作类,在这个包之中只提供了两个操作类:Pattern、Matcher,可是在一般的开发之中很少去直接使用这两个类。在 JDK 1.4 之后对于 String 类进行了大量的修改,里面增加了与正则有关的操作方法,有如下几个方法是可以支持正则操作的:
方法名称 | 描述 |
public Boolean matches(String regex) | 将字符串与给出的正则进行匹配验证 |
public String repalceAll(String regex,String replacement) | 按照指定的正则全部替换 |
public String replaceFirst(String regex,String replacement) | 按照指定的正则替换首个 |
public String[] split(String regex) | 按照指定的正则拆分 |
public String[] split(String regex,int limit) | 拆分为指定长度的字符串数组 |
如果想要操作这些方法,那么就必须首先清楚正则标记。
2.正则标记
在正则操作之中,使用一系列的标记符号是一件非常重要的任务,不光是 Java,只要是支持正则操作的程序,例如,JavaScript 标记都是统一的。所有的标记都在 java.util.regex.Pattern 类提供,下面给出一些核心的正则标记:
(1)字符,表示单个字符,只能出现 1 位。
x:表示是一个指定的一位字符,例如:编写一个 a,表示是字母 a;
\\:表示一位字符 “ \ ”,但是由于 “ \ ” 有个数含义,所以使用 “ \\ ” 表示一位 “ \ ”;
\n:匹配换行;
(2)字符范围,在指定的字符范围之中选 1 位,只能出现 1位。
[abc]:表示可以是 a、b、c 中的任意一位;
[^abc]:表示不是 a、b、c 中的任意一位;
[a-zA-Z]:表示是任意一位字母( 大写或小写 );
[0-9]:表示是任意一位数字。
(3)简洁表达式,表示 1 位。
.:表示任意的一位字符;
\d:表示一位数字,等价于 “ [0-9] ”;
\D:表示一位非数字,等价于 “ [^0-9] ”;
\s:表示一位空格,等价于 “ [\t\n\x0B\f\r] ”;
\S:表示一位非空格,等价于 “ [^\t\n\x0B\f\r] ”;
\w:表示一位字母、数字、_,等价于 “ [a-zA-Z0-9_] ”;
\W:表示一位非字母、数字、_,等价于 “ [^a-zA-Z0-9_] ”;
(4)边界匹配,Java 用不上。
^:表示正则的开头;
$:表示正则的结尾。
(5)数量表示,之前的正则每个符号只表示一位,如果要表示多位,则必须使用以下的数量关系。
正则 ?:表示此正则可以出现 0 次或 1次;
正则 + :表示此正则可以出现 1 次或多次;
正则 * :表示此正则可以出现 0 次、1 次或多次;
正则 {n} :表示此正则出现正好 n 次;
正则 {n,} :表示此正则出现 n 次以上;
正则 {n,m} :表示此正则出现 n ~ m 次。
(6)逻辑操作。
正则 1 正则 2 :正则 1 之后紧跟正则 2 操作;
正则 1 | 正则 2 :表示或的关系,有一套正则标记匹配即可;
( 正则 ):表示按照一组来使用。
3.利用 String 进行正则操作
在 String 类中提供了与正则直接有关的操作方法,下面将使用这些方法进行正则标记的验证。
举例:
//字符串替换
public class SubString
{
public static void main(String[] args) throws Exception
{
String str = "a1b22c333d4444e55555f666666g";
String regex = "[0-9]+"; //数字出现1次或多次
//String regex = "\\d+"; //数字出现1次或多次
System.out.println(str.replaceAll(regex, ""));
}
}
对于 “ [0-9] ” 的这个标记,实际上也可以使用 “ \\d ” 表示,代码中已注释。
举例:
//验证邮箱格式
public class EmailValidation
{
public static void main(String[] args) throws Exception
{
String str = "[email protected]";
String regex = "\\w+@\\w+\\.\\w+";
System.out.println(str.matches(regex));
}
}
在 Math 类中提供了大量的数学计算方法。Math 类包含了所有用于几何和三角的浮点运算方法,这些方法都是静态的,每个方法的使用都非常简单。
如:四舍五入:public static long round(double a);
round() 是将小数点之后的所有小数位四舍五入,最后只剩下整数部分。
(1)如果参数为正数,且小数点后第一位 >= 5,运算结果为参数的整数部分 +1.
(2)如果参数为负数,且小数点后第一位 >= 5( 小数第一位等于 5,小数位数多于1 ),运算结果为参数的整数部分 -1.
(3)如果参数为正数,且小数点后第一位 <5;或者参数为负数,且小数点后第一位 <=5( 小数只有一位 ),运算结果为参数的整数部分。
double num = 12.345;
System.out.println(Math.round(num)); //输出结果为12
Math.round(15.5) = 16;
Math.round(-15.5) = 15;
Math.round(-15.51) = -16;
Random 类是一个随机数产生器,随机数是按照某种算法产生的,一旦用一个初值创建 Random 对象,就可以得到一系列的随机数。但如果用相同的初值创建 Random 对象,得到的随机数序列是相同的,也就是说,在程序中看到的 “ 随机数 ” 是固定的那些数,起不到 “ 随机 ” 的作用。针对这个问题,Java 设计者在 Random 类的 Random() 构造方法中使用当前的时间来初始化 Random 对象,因为没有任何时刻的时间是相同的,所以就可以减少随机数序列相同的可能性。
下面利用 Random 类来产生 5 个 0~100 之间的随机整数:
//利用Random类来产生5个0~100之间的随机整数
import java.util.Random;
public class RandomDemo
{
public static void main(String[] args) throws Exception
{
Random r = new Random(); //新建一个Random对象用于生成随机数
for (int i = 0; i < 5; i++) { //循环5次
System.out.println(r.nextInt(100) + "\t");//输出随机数,并在每个随机数之间加空格
}
}
}
利用 Random 随机产生一组数列,这种方式得到的结果事先是未知的。因此在以后编写验证码的时候可以利用此类完成。
现在要对一个非常大的数字进行操作,并且这个数字已经超过了 double 的范畴,我们唯一的做法是将数字变为字符串,之后按位进行手工的计算。但在 Java 里面为了简化此类操作专门提供了两大数字操作类:java.math.BigInteger、java.math.BigDecimal。
1.大型整数操作类 BigInteger
如果数字超过该类型的最大范围,结果会提示 “ Infinity ”。在 BigInteger 类的构造方法( public BigInteger(String val) )里面已经清楚的描述出了,如果数据过大,则只能利用字符串保存,而后在 BigInteger 类之中提供了若干个基本的数学操作。下面看一下 BigInteger 的四则运算:
//BigInteger的四则运算
import java.math.BigInteger;
public class BigNumDemo
{
public static void main(String[] args) throws Exception
{
//定义两个大的整数
BigInteger bigA = new BigInteger("123456789123456789");
BigInteger bigB = new BigInteger("1234567");
//对两个数进行加法操作
System.out.println("加法操作:" + bigA.add(bigB));
//对两个数进行减法操作
System.out.println("减法操作:" + bigA.subtract(bigB));
//对两个数进行乘法操作
System.out.println("乘法操作:" + bigA.multiply(bigB));
//对两个数进行除法操作
System.out.println("除法操作:" + bigA.divide(bigB));
//对两个数进行除法操作,并同时保存商与余数
BigInteger result[] = bigA.divideAndRemainder(bigB);
System.out.println("商:" + result[0] + ",余数:" + result[1]);
}
}
bigA 除以 BigB 的商与余数保存在 result 数组中,所以可以输出。
2.大型浮点数操作类 BigDecimal
BigDecimal 的实现用到了 BigInteger,不同的是 BigDecimal 加入了小数的概念。一般的 float 型和 Double 型数据只可以用来做科学计算或者是工程计算,由于在商业计算中,要求的数字精度比较高,所以要用到 java.math.BigDecimal 类,它支持任何精度的定点数,可以用它来精确计算货币值。下面给出 BigDecimal 的一些主要方法:
方法名称 | 描述 |
add(BigDecimal) | BigDecimal 对象中的值相加,然后返回这个对象 |
subtract(BigDecimal) | BigDecimal 对象中的值相减,然后返回这个对象 |
multiply(BigDecimal) | BigDecimal 对象中的值相乘,然后返回这个对象 |
divide(BigDecimal) | BigDecimal 对象中的值相除,然后返回这个对象 |
toString() | 将 BigDecimal 对象的数值转换成字符串 |
doubleValue() | 将 BigDecimal 对象中的值以双精度数返回 |
floatValue() | 将 BigDecimal 对象中的值以单精度数返回 |
longValue() | 将 BigDecimal 对象中的值以长整数返回 |
intValue() | 将 BigDecimal 对象中的值以整数返回 |
举例:
//BigDecimalDemo的四则运算
import java.math.BigDecimal;
public class CalculateBigDecimal
{
public static void main(String[] args)
{
//定义两个大的整数
BigDecimal bigA = new BigDecimal("123456789123456789.8");
BigDecimal bigB = new BigDecimal("1234567.6");
//对两个数进行加法操作
System.out.println("加法操作:" + bigA.add(bigB));
//对两个数进行减法操作
System.out.println("减法操作:" + bigA.subtract(bigB));
//对两个数进行乘法操作
System.out.println("乘法操作:" + bigA.multiply(bigB));
//对两个数进行除法操作
System.out.println("除法操作:" + bigA.divide(bigB,BigDecimal.ROUND_DOWN));
System.out.println("保留一位小数:" + bigA.multiply(bigB).setScale(1,BigDecimal.ROUND_UP));
}
}
ROUND_DOWM 表示舍弃一位,ROUND_UP 表示进一位,ROUND_HALF_UP 表示四舍五入,对于 Math 而言无法实现准确的位数操作,所以处理位数较大的数必须实现精确位的操作用户只有通过 BigDecimal 实现。
在 Java 中数据类型分为基本数据类型和复杂数据类型,int 属于基本数据类型,而 Integer 属于后者。
Integer 类在对象中包装了一个基本类型 int 的值。Integer 类型的对象包含一个 int 类型的字段。
此外,该类提供了多个方法,能在 int 类型和 String 类型之间互相转换,还提供了处理 int 类型时非常有用的其他一些常量和方法。
当需要往 ArrayList,HashMap 中放东西时,像 int 这种内建类型是放不进去的,因为容器都是装 object 的,但是 JDK 1.5 引入了自动装箱和自动拆箱,会自动的转化为内建类型的外覆类。
举例:
//Integer类的三种创建方法
public class UseInteger
{
public static void main(String[] args)
{
//使用new关键字新建一个Integer对象并实例化
Integer num1 = new Integer(100);
//使用Integer中的方法valueOf创建Integer对象
Integer num2 = Integer.valueOf(200);
//利用自动装箱,直接将一个int类型的整数赋给Integer,利用Java的自动装箱进行类型的转化
Integer num3 = 300;
System.out.println("三种不同的创建方式:" + num1 + " " + num2 + " " + num3);
}
}
java.lang.Boolean 类与 Integer 一样是在对象中封装了一个基本布尔型的值。Boolean 类型的对象包含在一个单一的字段中,其类型为布尔值。与 Integer 一样 Boolean 类也有三种生成的方式。此外,Boolean 类中还内置了一些实用的方法。
举例:
//Boolean类的具体使用
public class CompareBoolean
{
public static void main(String[] args)
{
Boolean b1,b2; //创建两个Boolean型变量b1,b2
b1 = new Boolean(true); //给b1赋值
b2 = new Boolean(false); //给b2赋值
int res; //创建一个整型数res
res = b1.compareTo(b2); //比较b1与b2的值
String str1 = "Both values are equal";
String str2 = "Object value is true";
String str3 = "Argument value is true";
if (res == 0) {
System.out.println(str1);
}else if (res > 0) {
System.out.println(str2);
}else if (res < 0) {
System.out.println(str3);
}
}
}
Byte 类将基本类型 byte 的值包装在一个对象中。一个 Byte 类型的对象只包含一个类型为 byte 的字段。此外该类还为 byte 和 String 的相互转换提供了几种方法,并提供了处理 byte 时非常有用的其他一些常量和方法。
如下表:
方法名称 | 返回类型 | 功能说明 |
byteValue() | byte | 返回 Byte 类的一个 byte 类型值 |
compareTo(Byte anotherByte) | int | 在数值上比较两个类对象,相等返回 0,如果调用对象小于 anotherByte 对象则返回负值,否则返回正值 |
doubleValue() | double | 返回 Byte 类的一个 double 类型值 |
intValue() | int | 返回 Byte 类的一个 int 类型值 |
parseByte(String str) | byte | 将 String 类型转换为 byte 类型 |
toString() | String | 返回 Byte 类的一个 String 类型值 |
equals(Byte anotherByte) | 若调用对象值等于 anotherByte 对象的值返回 true,否则返回 false | |
valueOf(String str | byte x) | Byte 对象 | 返回值为 str 或者 x 的 Byte 对象 |
举例:
//Byte类的基本使用方法
public class ByteFun
{
public static void main(String[] args)
{
//声明一个byte变量
byte b = 20;
//返回表示b的一个Byte实例
Byte b1 = new Byte(b);
//返回"21"的Byte对象
Byte b2 = Byte.valueOf("21");
//返回"22"的Byte对象
Byte b3 = 22;
//作为一个int型b1值
int x1 = b1.intValue();
//作为一个int型b2值
int x2 = b2.intValue();
//作为一个int型b3值
int x3 = b3.intValue();
System.out.println("b1:" + x1 + "b2:" + x2 + "b3:" + x3);
//返回b的String对象
String str1 = Byte.toString(b);
//返回b2的String对象
String str2 = Byte.toString(b2);
//返回b3的String对象
String str3 = b3.toString();
System.out.println("str:" + str1 + "str2:" + str2 + "str3:" + str3);
//将String参数解析为有符号的十进制byte
byte bb = Byte.parseByte("23");
System.out.println("Byte.parseByte(\"23\"):" + bb);
//将b1与b2比较
boolean bool1 = b1.equals(b2);
//将b1与b3比较
boolean bool2 = b1.equals(b3);
System.out.println("b1.equals(b2):" + bool1 + "b1.equals(b3)" + bool2);
}
}
1.包装类型不能够随便使用关系运算符比较大小
下面以 Integer 为例针对三种创建对象的方法进行说明。
首先,对于 new 关键字创建的包装类对象,两次 new 得到的对象引用地址是不同的,不能使用 “ == ” 关键字做大小比较。而使用 “ < ” 和 “ > ” 等运算符时,包装类型会调用 valueOf 方法,将运算符两边的对象都转换为基本类型后再做比较。这就是为何 “ == ” 不能使用而 “ < ”、“ > ”、“ <= ”、“ >= ” 这几个符号可以使用的原因。
其次,使用 valueOf 方法创建的 Integer 对象,使用 “ == ” 符号时,运行结果有时候正确,有时候不正确。查看 valueOf 方法的源码,如下:
public static Integer valueOf(int i)
{
if(i >= -128 && i <= IntegerCache.high)
return IntegerCache.cache[i + 128];
else
return new Integer(i);
}
通过看源代码能够知道,整数类型在 -128 ~ 127 之间时,会使用缓存,如果已经创建了一个相同的整数,使用 valueOf 创建第二次时,不会使用 new 关键字,而用已经缓存的对象。所以使用 valueOf 方法创建两次对象,若对应的数值相同,且数值在 -128 ~ 127 之间时,两个对象都指向同一个地址。
最后,使用 Integer i = 400 这样的方式来创建 Integer 对象,与 valueOf 方法的效果是一样的。
总之,包装类对象不可使用 “ == ” 符做比较运算,如果要进行比较运算时,最好使用 java 类库中的 compareTo 方法。