《java核心技术卷一》读书笔记 day3

在程序运行时,经常需要将一种数值类型转换成为另一种数值类型。下图给出了数值类型之间的合法转换。

在图中有六个实心箭头,表示无信息丢失的转换;有三个虚箭头,表示可能有精度损失的转换。例如,123 456 789 是一个大整数,它所包含的位数比float所能够表达的位数多。当将这个数值转换为float类型时,将会得到同样大小的结果,但却会失去一定精度。

int n = 123456789;
float f = n;//f is 1.23456792E8

当使用商量两个数值进行二元操作时(例如n+f,n是整数,f是浮点数),先将两个操作数转换为同一种类型,然后再进行计算。

  • 如果两个操作数中有一个是double类型,另一个操作数就会转换成double类型。

  • 否则,如果其中一个操作数是float类型,另一个操作数将会转换为float类型。

  • 否则,如果其中一个操作数是long类型,另一个操作数将会转换为long类型。

  • 否则,两个操作数都将被转换为int类型。


强制类型转换

在有必要的时候int类型的值会自动转换为double类型。但另一方面,有时也需要将double转换成int。在Java中,允许这种数值之间的类型转换。在这种情况下,需要通过强制类型转换(cast)实现这个操作。强制类型转换的过程中,可能会丢失一些信息。

强制类型转换的语法格式是:圆括号中给出想要转换的目标类型,后面紧跟待转换的变量名。例如:

double x = 9.993;
int nx = (int) x;

这样,nx的值为9。强制类型转换通过阶段小数部分将浮点值转换为整型。

如果先要对浮点数进行舍入运算,以便得到最接近的整数,那就使用Math.round方法:

double x = 9.997;
int nx = (int)Math.round(x);

现在变量nx的值为10.当调用round的时候,仍然需要使用强制类型转换(int) 。其原因是round方法返回的结果为long类型,由于存在信息丢失的可能性,所以只有显示的装置类型转换才能够将long类型转换成int类型。

注意:

  • 如果试图将一个数值从一种类型强制转换成另一种类型,而又超出了目标类型的表示范围,结果就会阶段成一个完全不同的值。例如,(byte)300的实际值为44 。

  • 不要在boolean类型与任何数值类型之间进行强制类型转换,这样可以防止发生错误。只有极少数的情况才需要将布尔值转换为数值类型,这时候可以使用条件表达式 b?1:0 。


括号与运算符级别

运算符结合性
[] . () (方法调用)从左往右
! ~ ++ -- (一元运算)-(一元运算) ()(强制类型转换) new从右往左
* / %从左往右
+ -从左往右
<< >> >>>从左往右
< <= > >= instanceof从左往右
== !=从左往右
&从左往右
^从左往右
|从左往右
&&从左往右
||从左往右
?:从右往左
= += -= *= /= %= |= ^= <<= >>= >>>=从右往左

如果不使用圆括号,就会按照给出的运算符优先次序进行计算。同一个级别的运算符按照从左往右的次序进行计算(除了表中的右结合运算符外。)例如,&&的优先级比||的优先级高,所以表达式

a&&b||c

等价于:

(a&&b)||c

又因为+=是右结合运算符,所以表达式

a+=b+=c

等价于

a+=(b+=c)

也就是将b+=c的结果(加上c之后的b)加到a上。


枚举类型

有时候,变量的取值之子啊一个有限的集合内。例如:销售的复转或比萨饼只有小、中、大和超大这四种尺寸。当然,可以将这些尺寸分别编码为1、2、3、4或S、M、L、X。但这样存在着一些隐患。在变量中很可能保存的是一个错误的值(如0或m)。

针对这种情况,可以自定义美剧类型。枚举类型包括有限个命名的值。例如,

enum Size{SMALL,MEDIUM,LARGE,EXTRA_LARGE};

现在,可以声明这种类型的变量:

Size s = Size.MEDIUM;

Size类型的变量只能存储这个类型声明给定的某个枚举值,或者null值,null表示这个变量没有设置任何值。


字符串

从概念上讲,Java字符串就是Unicode字符序列。例如,串“Jav\u0061”由四个Unicode字符J、a、v和a。Java没有内置的字符串类型,而是在标准java类库中提供了一个预定义类,很自然地叫做String。每个用双引号括起来的字符串都是String类的一个实例:

String e = "";//an empty string
String greeting = "Hello";
1.子串

String类的substring方法可以从一个较大的字符串提取出一个字串。例如:

String greeting = "Hello";
String s = greeting.substring(0,3);

创建了一盒右字符“Hel”组成的字符串。

substring方法的第二个参数是不想复制的第一个位置。这里要复制位置为0、1和2(从0到2,包括0和2)。在substring中从0开始计数,直到3但不包括3 。

substring的工作方式有一个优点:容易计算字串的航都。字符串长度 s.substring(a,b)的长度为b-a。例如,子串“Hel”的长度为3-0=3 。

2.拼接

Java语言允许使用+号连接两个字符串。

String expletive = "Expletive";
String PG13 = "deleted";
String message = expletive + PG13;

上述代码将‘Expletivedeleted“赋给了message(注意,单词之间没有空格。+号按照给定的次序将两个字符串拼接起来)。

当将一个字符串与一个非字符串的值进行拼接时,后者被转换成字符串。例如:

int age = 13;
String rating = "PG" + age;

rating设置为”PG13“。

这种特性通常用在输出语句中。例如:

System.out.println("The answer is " + answer);

这是一条合法的语句,并且会打印出所希望的结果(因为单词is后面加了一个空格,输出时候也会加上这个空格)。

3.不可变字符串

String类没有提供用于修改字符串的方法。如果希望将greeting的内容修改为”Hlep!“,不能直接地将greeting的最后两个位置的字符修改为’p'和‘!’。修改这个字符串,首先提取需要的字符,然后再拼接上替换掉字符串:

greeting = greeting.substring(0,3) + "p!";//greeting之前的值为"Hello"

上面这条语句将greeting当前值修改为”Help!“。

由于不能修改Java字符串中的字符,所以在Java文档中将String类对象称为不可变字符串,如同数字3永远是数字3一样,字符串"Hello"永远包含字符H、e、l、l和o的代码单元序列,而不能修改其中的任何一个字符。当然,可以修改字符串greeting,让它引用另外一个字符串,这就如同可以将存放3的数值变量改成存放4一样。

4.检测字符串是否相等

可以使用equals方法检测两个字符串是否相等。表达式:s.equals(t)

如果字符串s与字符串t相等,则返回true;否则,返回false。需要注意的是s与t可以是字符串变量也可以是字符串常量。例如,下列表达式是合法的:

"Hello".equals(greeting);//greeting 的值为”Hello“(之前定义和初始化过)

想要检测两个字符串是否相等,而不区分大小写,可以使用equalsIgnoreCase方法。

"Hello".equalsIgnoreCase("hello");

一定不能使用==运算符检测两个字符串是否相等!这个运算符只能够确定两个字符串是否放置在同一位置上。当然,如果字符串放置在同一个位置上,它们必然相等。但是完全又肯将内容相同的字符串的拷贝位置放在不同的位置上。

String greeting = "Hello";//initialize greeting to a string
if(greeting == "Hello")...
    //probably true
if(greeting.substring(0,3) == "Hel")...
    //probavly false

如果虚拟机始终将相同的字符串共享,就可以使用==运算符检测是否相等。但实际上只有字符串常量是共享的,而+或substring等操作产生的结果并不是共享的。因此,千万不要使用==运算符测试字符串的相等性,一面在程序中出现糟糕的bug。从表面上看,这种bug很像随机产生的间歇性错误。

5.空串与Null串

空串""是长度为0的字符串。可以调用以下代码检查字符串是否为空:

if(str.length()==0)
 //   或
if(str.equals("")

空串是一个Java对象,有自己的串长度(0)和内容(空)。不过,String变量还可以存放一个特殊的值,名为Null,这表明目前没有对象与该变量关联。要检查一个字符串是否为null,要使用以下条件:

if(str == null)

有时要检查一个字符串既不是null也不为空串,这种情况就需要使用以下条件:

if(str != null && str.length() != 0)

首先要检查str不为null。若在一个null值上调用方法,会出现错误。

6.代码点与代码单元

Java字符串由char序列组成。char数据类型是一个采用UTF-16编码表示Unicode代码点的代码单元。大多数的常用Unicode字符使用一个代码单元就可以表示,而辅助字符需要一对代码单元表示。

length方法将返回采用UTF-16编码表示的给定字符串所需要的代码单元数量。例如:

String greeting = "Hello";
int n = greeting.length();//is 5

想要得到实际长度,及代码点数量,可以调用:

int cpCount = greeting.codePointCount(0,greeting.length());

调用s.charAt(n)将返回位置n的代码单元,n介于0 ~ s.length() - 1之间。例如:

char first = greeting.charAt(0);//first is 'H'
char last = greeting.cahrAt(4);//last is 'o'

想要得到第i个代码点,应使用下列语句:

int index = greeting.offsetByCodePoints(0,i);
int cp = greeting.codePointAt(index);//得到位置i+1 的Unicode编码

7.字符串 API

  • char charAt(int index)

    返回给定位置的代码单元。

  • int codePointAt(int index)

    返回从给定我i在开始或结束的代码点

  • int offsetByCodePoints(int startIndex,int cpCount)

    返回从startIndex代码点开始,位移cpCount后的代码点索引。

  • int compareTo(String other)

    按照字典顺序,如果字符串位于other之前,返回一个负数;如果字符串位于other之后,返回一个正数;如果两个字符串相等,返回0

  • boolean endsWith(String suffix)

    如果字符串以suffix结尾返回true

  • boolean equals(Object other)

    如果字符串与other相等,返回true。

  • boolean equalsIgnoreCase(String other)

    如果字符串与other相等(忽略大小写),返回true。

  • int indexOf(String str)

  • int indexOf(String str,int fromIndex)

  • int indexOf(int cp)

  • int indexOf(int cp,int fromIndex)

    返回与字符串str或代码点cp匹配的第一个子串的开始位置。这个位置从索引0或fromIndex开始计算。如果在原始串中不存在str,返回-1

  • int lastIndexOf(String str)

  • int lastIndexOf(String str,int fromIndex)

  • int lastIndexOf(int cp)

  • int lastIndexOf(int cp,int fromIndex)

    返回与字符串str或代码点cp匹配的最后一个字串的开始位置。这个位置从原始串尾端或fromIndex开始计算。

  • int length()

    返回字符串的长度。

  • int codePointCount(int startIndex,int endIndex)

    返回startIndex和endIndex -1之间的代码点数量。没有配成对的代用字符将计入代码点。

  • String replace(CharSequence oldString,CharSequence newString)

    返回一个新字符串。这个字符串用newString代替原始字符串中所有oldString。可以用String或StringBuilder作为CharSequnence作为参数。

  • boolean startsWith(String prefix)

    如果字符串以prefix字符串开始,返回true。

  • String substring(int beginIndex)

  • String substring(int beginIndex,int endIndex)

    返回一个新字符串。这个字符串包含原始字符串中从beginIndex到串尾endIndex-1的所有代码单元

  • String toLowerCase()

    返回一个新字符串。这个字符串将原始字符串的所有大写字母改成了小写字母。

  • String toUpperCase()

    返回一个新字符串。这个字符串将原始字符串的所有小写字母改成了大写字母。

  • String trim()

    返回一个新字符串。这个字符串删除了原始字符串头部和尾部的空格。

8.构建字符串

有些时候,需要由较短的字符串构建字符串,例如,按键或来自文件中的单词。采用字符串连接的方式达到此目的的效率比较低。每次连接字符串,都会构建一个新的String对象,既耗时,又浪费空间。使用StringBuilder类就可以避免这个问题的发生。

如果需要用许多小段的字符串构建一个字符串,那么应该按照下列步骤进行。首先,构建一个空的字符串构建器:

StringBuilder builder = new StringBuilder();

当每次需要添加一部分内容时,就调用append方法。

builder.append(ch);//appends a single character
builder.append(str);//appends a string

在需要构建字符串时就调用toString方法,将可以得到String对象,其中包含了构建起中的字符序列。

String completedstring = builder.toString();

注:在JDk5.0中引入StringBuilder类。这个类的前身是StringBuffer,其效率稍微有些低,但允许采用多线程的方式执行添加或删除字符的操作。如果所有字符串在一个单线程中编程(通常如此),则应该用StringBuilder替代它。这两个API是相同的。下面的API注释博爱含量StringBuilder类中的重要方法。

java.lang.StringBuilder:

  • StringBuilder()

    构造一个空的字符串构造器。

  • int length()

    返回构建器或缓冲器的代码单元数量。

  • StringBuilder append(String str)

    追加一个字符串并返回this。

  • StringBuilder append(char c)

    追加一个代码单元并返回this。

  • StringBuilder appendCodePoint(int cp)

    追加一个代码点,并将其转换为一个或两个代码单元并返回this。

  • void setcharAt(int i,char c)

    将第i个代码单元设置为c。

  • StringBuilder insert(int offset,String str)

    在offset位置插入一个字符串并返回this(offset从0开始计数)。

  • StringBuilder insert(int offset,char c)

    在offset位置插入一个代码单元并返回。

  • StringBuilder delete(int startIndex,int endIndex)

    删除偏移量从startIndex到endIndex-1的代码单元并返回this。

  • String toString()

    返回一个与构建器或缓冲器内容相同的字符串。

  • 40
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值