类是构建所有Java应用程序和applet的构建块。
【applet:是一种Java程序。它一般运行在支持Java的Web浏览器内。因为它有完整的Java API支持,所以applet是一个全功能的Java应用程序。
applet的工作原理:
Java Applet 可以大大提高Web页面的交互能力和动态执行能力。包含Applet的网页被称为Java-powered页,可以称其为Java支持的网页。当 Applet用户访问这样的网页时,Applet被下载到用户的计算机上执行,但前提是用户使用的是支持Java的网络浏览器。由于Applet是在用户的计算机上执行的,所以它的执行速度不受网络带宽或者Modem存取速度的限制,用户可以更好地欣赏网页上Applet产生的多媒体效果。在Java Applet中,可以实现图形绘制,字体和颜色控制,动画和声音的插入,人机交互及网络交流等功能。 Applet还提供了名为抽象窗口工具箱(Abstract Window Toolkit, AWT)的窗口环境开发工具。 AWT利用用户计算机的GUI元素,可以建立标准的图形用户界面,如窗口、按钮、滚动条等等。目前,在网络上有非常多的Applet范例来生动地展现这些功能,读者可以去调阅相应的网页以观看它们的效果。
Applet 小应用程序的实现主要依靠 java.applet包中的Applet类。与一般的应用程序不同,Applet应用程序必须嵌入在HTML页面中,才能得到 解释执行;同时Applet可以从Web页面中获得参数,并和Web页面进行交互。
Applet是一种Java的小程序,它通过使用该Applet的HTML文件,由支持Java的 网页浏览器下载运行。也可以通过java开发工具的 appletviewer来运行。Applet 程序离不开使用它的HTML文件。这个HTML文件中关于Applet的信息至少应包含以下三点:
1) 字节码文件名(编译后的Java文件,以.class为后缀)
2)字节码文件的地址
3)在网页上显示Applet的方式。
一个HTML文件增加Applet有关的内容只是使网页更加富有生气,如添加声音、动画等这些吸引人的特征,它并不会改变HTML文件中与Applet无关的元素。【安全性限制】
为了防止这样的问题出现,在缺省的情况下,大多数浏览器在Applet安全方面受到诸多的限制,几乎不能对系统进行任何“读”或“写”的操作:
1. 不允许Applet访问本地文件系统
2. Applet不能执行任何本地计算机上的程序
3. 不允许Applet尝试打开除提供Applet的 服务器之外的任何系统的Socket
4. 不允许Applet访问用户名、电子邮件地址等与本地系统有关的信息
5. 对于Applet而言,Java环境中的某些标准系统属性是只读的
6. Applet不能创建或装载Applet的机器的网络连接
7. Applet不能充当 网络服务器,监听或接收来自远程系统的连接请求
8. 不允许Applet装载动态库或定义本地方法调用
9. Applet不能操纵不在自己 线程组中的任何线程
10. Applet不能关闭JVM。
应用程序转换成Applet:
将图形化的Java应用程序(是指,使用AWT的应用程序和使用java程序启动器启动的程序)转换成嵌入在web页面里的applet是很简单的。
下面是将应用程序转换成applet的几个步骤:
- 编写一个HTML页面,该页面带有能加载applet代码的标签。
- 编写一个JApplet类的子类,将该类设置为public。否则,applet不能被加载。
- 消除应用程序的main()方法。不要为应用程序构造框架窗口,因为你的应用程序要显示在浏览器中。
- 将应用程序中框架窗口的构造方法里的初始化代码移到applet的init()方法中,你不必显示的构造applet对象,浏览器将通过调用init()方法来实例化一个对象。
- 移除对setSize()方法的调用,对于applet来讲,大小已经通过HTML文件里的width和height参数设定好了。
- 移除对 setDefaultCloseOperation()方法的调用。Applet不能被关闭,它随着浏览器的退出而终止。
- 如果应用程序调用了setTitle()方法,消除对该方法的调用。applet不能有标题栏。(当然你可以给通过html的title标签给网页自身命名)
- 不要调用setVisible(true),applet是自动显示的。
Applet程序只能嵌入到HTNL网页中通过浏览器来运行,目的是为了增强网页的表现能力和交互方式。】
文件名、标识符
Java中定义类名的规则很宽松。名字必须以字母开头,后面可以跟字母和数字的任意组合,长度上基本上没有限制。但不能使用Java保留字(例如:public或class等关键字)作为类名。
标准的命名规范为:类名是以大写字母开头的名词。如果名字由多个单词组成,每个单词的第一个字母都应该大写(这种在一个单词中间使用大写字母的方式称为骆驼命名法(camel case),以自身为例,应该写成CamelCase)。
源代码的文件名必须与公共类的名字相同,并用.java作为拓展名。因此存储这段源代码的文件名必须为FirstSample.java。
如果已经正确的命名了这个文件,并且源代码中没有任何录入错误,在编译这段源代码之后就会得到一个包含在字节码的文件。Java编译器将字节码文件自动地命名为FirstSample.class,并存储在源文件的同一目录下。
运行已编译的程序时,Java虚拟机总是从指定类中的main方法的代码开始执行(这里的“方法”就是Java中的“函数”),因此为了代码能够执行,在类的源文件中必须包含一个main方法。当然,也可以将用户自定义的方法添加到类中,并在main方法中调用这些方法。
定义:Java语言中,对于变量,常量,函数,语句块也有名字,我们统统称之为Java标识符。
标识符是用来给类、对象、方法、变量、接口和自定义数据类型命名的。
Java标识符由数字,字母和下划线(_),美元符号($)或人民币符号(¥)组成。在Java中是区分大小写的,而且还要求首位不能是数字。最重要的是,Java关键字不能当作Java标识符。
下面的标识符是合法的:
myName,My_name,Points,$points,_sys_ta,OK,_23b,_3_
下面的标识符是非法的:
#name,25name,class,&time,if
建议:
类名规范:首字母必须大写,后面每个单词收字迷大写(大驼峰式),长度没有限制 [源代码的文件名必须与公共类的名字相同,并且.java作为拓展名。Eg:FirstSample.java]
方法名规范:首字母小写,后面每个单词的首字母大写(小驼峰式)
变量名规范:首字母小写,后面每个单词的首字母大写(小驼峰式)
.java(java文件)就是这样一个未经编译的源程序,一般是给程序员看。
.class(class文件)就是被编译器编译过的Java文件,给计算机看。
注释:(对程序中的内容进行解释说明,是给程序员看的,不参与编译和运行,不影响程序的执行效率)
//:单行注释
/* */:多行注释
/** */:文本注释
/**
* This is the first sample program in Core Java Chapter 3
* @version 1.01 1997-03-22
* @auther Gary Cornell
*/
public class FirstSample{
public static void main (String[] args){
System.out.println("We will not use 'Hello,World!'");
}
}
- 警告:在Java中,/* */注释不能嵌套。也就是说,不能简单地把代码用/*和*/括起来作为注释,因为这段代码本身也可能包含一个*/界定符
数据类型
Java是一种强类型语言。这就意味着必须为每一个变量声明一种类型。在Java中,一共有8种数据类型(primitive type),其中有4种整型、2种浮点类型、1种字符类型char(用于表示Unicode编码的代码单元)和一种用于表示真值的boolean类型。
- 注释:Java有一个能够表示任意精度的算术包,通常称为“大数”。虽然被称为大数,但它并不是一种基本Java类型,而是一个Java对象。
-
变量:
在程序的执行过程中,只可以在一定范围内发生改变的量
分类:
1.整数类型
byte类型 | 1个字节 | -128到127 |
short类型 | 2个字节 | 正负3万多 |
int类型 | 4个字节 | 正负21亿 整数默认就是int类型 |
long类型 | 8个字节 | 大概19位数字 表示long类型的数据,后面建议添加L |
在Java中,整形的范围与运行Java代码的机器无关。这就解决了软件从一个平台移植到另一个平台,或者在同一平台中的不同操作系统之间进行移植给程序员带来的诸多问题。与此相反,C与C++程序会针对不同的处理器选择最为高效的整形,这样会造成一个在32位处理器上运行的很好的C程序在16位系统上运行时却发生整数溢出。由于Java程序必须保证在所有机器上都能够得到相同的运行结果,所以各种数据类型的取值范围必须固定。
长整型中,十六进制数值有一个前缀0x或0X。八进制有一个前缀0,例如,010对应十进制中的8。从Java7开始,加上前缀0b或0B就可以写二进制数。例如:0b1001就是9。另外,同样是从Java7开始,还可以为数字字面量加下划线,如用1_000_000表示100万。这些下划线只是为了让人更易读懂。Java编译器会去除这些下划线。
- 注释:在C和C++中,int和long等类型的大小与目标平台相关。在8086这样的16位处理器上整数占2字节;不过,在32位处理器(比如Pentium或SPARC)上,整数则为4字节。类似地,在32位处理器上Long值为4字节,在64位处理器上则为8字节。由于存在这些差别,这对编写跨平台程序带来了很大的难度。在Java中,所有的数值类型所占据的字节数与平台无关。
注意,Java没有任何无符号形式的int、long、short或byte类型。
- 注释:如果要使用不可能为负的整数值而且确实需要额外的一位(bit),也可以把有符号整数值解释为无符号数,但是要非常仔细。例如:一个byte值b可以不表示范围-128到127,如果你想表示0到255的范围,也可以存储在一个byte中。基于二进制算术运算的性质,只要不溢出,加法、减法和乘法都能正常计算。但对于其他运算,需要调用Byte.toUnsignedInt(b)来得到一个0到255的int值,然后处理这个整数值,再把它转换回byte。Integer和long类都提供了处理无符号除法和求余数的方法。
2.浮点类型
float类型 | 4个字符 | 采用科学计数法,虽然占4个字节,但是取值范围远远超过long类型 | 表示float类型的数据后 面建议添加F |
double类型 | 8个字节 | 小数据默认就是double类型 |
- 注释:可以使用十六进制表示浮点数值。例如:0.125=2-3 可以表示成0*1.0p-3。在十六进制表示法中,使用p表示指数,而不是e(e是一个十六进制数位)。注意,尾数采用十六进制,指数采用十进制。指数的基数是2,而不是10。
所有的浮点数值计算都遵循IEEE754规范。具体来说,下面是用于表示溢出和出错情况的三个特殊的浮点数值:
正无穷大
负无穷大
NaN(不是一个数字)
例如,一个正整数除以0的结果为正无穷大。计算0/0或者负数的平方根结果为NaN。
- 注释:常量Double.POSITIVE_INFINITY、Double.NEGATIVE_INFINITY和Double.NaN(以及相应的Float类型的常量)分别表示这三个特殊的值,但在实际应用中很少遇到。特别要说明的是,不能如下检测一个特定值是否等于Double.NaN:
if(x == Double.NaN)
所有“非数值”的值都认为是不相同的。不过,可以如下使用Double.isNaN方法来判断:
if(Double.isNaN(x))
- 警告:浮点数值不适用于无法接受舍入误差的金融计算。例如:命令System.out.println(2.0-1.1)将打印出0.8999999999999999,而不是人们期望的0.9。这种舍入误差的主要原因是浮点数值采用二进制系统表示,而在二进制系统中无法精确地表示分数1/10.这就好像十进制无法精确的表示分数1/3一样。如果在数值计算中不允许有任何舍入误差,就应该使用BigDecimal类型
3. 其他
boolean类型 | 1个字节 |
char类型 | 2个字节 |
boolean类型有两个值:false和true,用来判断逻辑条件。整型值和布尔值之间不能进行转换。
注释:在C++中,数值甚至指针可以代替boolean值。值0相当于布尔值false,非0相当于布尔值true。在Java中则不是这样。因此,Java程序员不会遇到下述麻烦:
if(x = 0)
…
meant x == 0
在C++中这个测试可以编译运行,其结果是false。而在Java中,这个测试将不能通过编译,其原因是整数表达式x = 0不能转换为布尔值。
char类型原本用于表示单个字符。不过,现在情况已经有所改变。如今,有些Unicode字符可以用一个char值描述,另外一些Unicode字符则需要两个char值。
char类型的字面量值要用单引号括起来。例如:‘A’是编码值为65的字符常量。它与“A”不同,“A”是包含一个字符A的字符串。char类型的值可以表示为十六进制值,其范围从\u000到\uFFF。例如:\u2122表示商标符号(TM),\u03c0表示希腊字母Π。
除了转义序列\u之外,还有一些用于表示特殊字符的转义序列。所有的转义序列都可以出现在加引号的字符字面量或字符串中。例如:‘\u2122’或“Hello\n”。转义序列\u还可以出现在加引号的字符常量或字符串之外(其他所有的转义序列都不可以)。例如:
public static void main(String\u005B\u005D args)
就完全符合语法规则,\u005B和\u005D分别是[和]的编码。
转义字符的转义序列
转义序列 | 名称 | Unicode值 |
\b | 退格 | \u0008 |
\t | 制表 | \u0009 |
\n | 换行 | \u000a |
\r | 回车 | \u000d |
\" | 双引号 | \u0022 |
\' | 单引号 | \u0027 |
\\ | 反斜杠 | \u005c |
逃逸字符序列
字符 | 名称 |
\b | 回退一格 |
\t | 到下一个表格位 |
\n | 换行 |
\r | 回车 |
\" | 双引号 |
\' | 单引号 |
\\ | 反斜杠本身 |
制表位
- 每行的固定位置
- 一个\t使得输出从下一个制表位开始
- 用\t才能使得上下两行对齐
- 警告:Unicode转义序列会在解析代码之前得到处理。例如:"\u002+\u0022"并不是一个由引号(U+0022)包围加号构成的字符串。实际上,\u0022会在解析之前转换为“,这会得到""+"",也就是一个空串。更隐秘地,一定要当心注释中的\u。注释
//\u000A is a newline
会产生一个语法错误,因为读程序时\u00A0会替换为一个换行符。类似地,下面这个注释
//look inside c:\users
也会产生一个语法错误,因为\u后面并没有跟着4个十六进制数。
4.Unicode和char类型
Unicode编码机制,打破了传统字符编码机制的限制。在Unicode出现之前,已经有许多不同的标准:美国的ASCII、西欧语言的ISO-8859-1、俄罗斯的KOI-8、中国的GB 18030和BIG-5等。这样就产生了下面两大问题:
一是对于任意给定的代码值、在不同的编码方案下有可能对应不同的字母;二是采用大字符集的语言其编码长度有可能不同。例如:有些常用的字符采用单字节编码,而另一些字符则需要两个或多个字节。
设计Unicode编码的目的就是要解决这些问题。在20世纪80年代开始启动统一工作时,人们认为两个字节的代码宽度足以对世界上各种语言的所有字符进行编码,并有足够的空间留给未来拓展。在1991年发布了Unicode 1.0,当时仅占用65 536个代码值中不到一半的部分。在设计Java时决定采用16位的Unicode字符集,这比使用8位字符集的其他程序设计语言有了很大的改进。
十分遗憾的是,经过一段时间之后,Unicode字符超过了65 536个,其主要原因是增加了大量汉语、日语和韩语中的表意文字。现在,16位的char类型已经不能满足描述所有Unicode字符的需要了。
Java语言从Java5开始解决这个问题。码点(code point)是指与一个编码表中的某个字符对应的代码值。在Unicode标准中,码点采用十六进制书写,并加上U+,例如U+0041就是拉丁字母A的码点。Unicode码点可以分成17个代码平面(code plane)。第一个代码平面成为基本多语言平面(basic multilingual plane),包括码点从U+0000到U+FFFF的”经典“Unicode代码;其余的16个平面的码点为从U+10000到U+10FFFF,包括辅助字符(supplementary character)。
UTF-16编码采用不同长度的编码表示所有Unicode码点。在基本语言平面中,每个字符用16位表示,通常称为代码单元(code unit);而辅助字符编码为一对连续的代码单元。采用这种编码对表示的各个值落入基本多语言平面中未使用的2046个值范围内,通常称为替代区域(surrogate area)(U+D800~U+DBFF用于第一个代码单元,U+DC00~U+DFFF用于第二个代码单元)。这样设计非常巧妙,我们可以从中迅速知道一个代码单元是一个字符的编码,还是一个辅助字符的第一或第二部分。例如:O是八元数集的一个数学符号,码点为U+1D546,编码为两个代码单元U+D835和U+DD46。
在Java中,char类型描述了UTF-16编码中的一个代码单元。
因此不建议在程序中使用char类型,除非确实是需要处理UTF-16代码单元。最好将字符串作为抽象数据类型处理。
- 提示:如果想要知道哪些Unicode字符属于Java中的“字母”,可以使用Character类的isJavaIdentifierStart和isJavaIdentifierPart方法来检查。
尽管$是一个合法的Java字符,但是不要在你自己的代码中使用这个字符。它只用在Java编译器或其它工具生成的名字中。
在Java9中,单下划线_不能作为变量名。不过,将来的版本可能使用_作为通配符。
5.常量:
(在程序执行过程中,值不可以发生改变的量)
- 整数:300、500
- 小数:7.7、9.0
- 字符:字符常量必须使用单引号‘’引起来,而且‘ ’中只能有一个字符(不能没有字符,也不能有多个字符)
eg:‘a’ 正确
‘’ 错误,不能没有内容
‘ ’ 正确,有一个空格字符
‘ab’ 错误,不能有两个字符
‘好’ 正确
- 字符串:字符串必须使用“”引起来,“”中可以写多个字符
eg:"a" 正确
"abc" 正确
"" 正确
" " 正确,有一个空字符
"好" 正确
"真的好想你" 正确
- 空常量:null 不用加"" 并且不能直接输出空常量
eg:System.out.println(null);错误的
在Java中,利用关键字final指示常量。
例如:
public class Constants {
public static void main(String[] args) {
final double CM_PER_INCH = 2.54;
double paperWidth = 8.5;
double paperHeight = 11;
System.out.println("Paper size in centimeters:" + paperWidth * CM_PER_INCH + "by" + paperHeight * CM_PER_INCH);
}
}
关键字final表示这个变量只能被赋值一次。一旦被赋值之后,就不能够再更改了。
在Java中,经常希望某个常量可以在一个类的多个方法中使用,通常将这些常量称为“类常量(class constant)”。可以使用关键字static final设置一个类常量。‘
例如:
public class Constants {
public static final double CM_PER_INCH = 2.54;
public static void main(String[] args) {
final double CM_PER_INCH = 2.54;
double paperWidth = 8.5;
double paperHeight = 11;
System.out.println("Paper size in centimeters:" + paperWidth * CM_PER_INCH + "by" + paperHeight * CM_PER_INCH);
}
}
- 注意:类常量的定义位于main方法的外部。因此,在同一个类的其他方法中也可以使用这个常量。而且,如果一个常量被声明为public,那么其它类的方法也可以使用这个常量。而且,如果一个常量被声明为public,那么其它类的方法也可以使用这个常量。
- 注释:const是Java保留的关键字,但目前并没有使用。在Java中,必须使用final关键字定义常量。
6.枚举类型
有时候,变量的取值只在一个有限的集合内。例如:销售的披萨或服装只有小、中、大和超大这四种尺寸。当然,可以将这些尺寸分别编码为1、2、3、4或S、M、L、X。但这种设置很容易出错。很可能在变量中保存的是一个错误的值(如0或m)。
针对这种情况,可以自定义枚举类型。枚举类型包括有限个命名的值。
例如:
enum Size {SMALL、MEDIUM、LARGE、EXTRA_LARGE};
可以声明这种类型的变量:
Size s = Size.MEDIUM;
Size类型的变量只能存储这个类型声明中给定的某个枚举值,或者特殊值null,null表示这个变量没有设置任何值。
字节:
字节是我们常见的计算机最小存储单元,计算机存储任何的数据,都是以字节的形式存储,右键点击文件属性,我们可以查看文件的字节大小。
bit(位):储存一个0或者1所占的空间 简写B
8个bit(二进制位)0000-0000表示为1个字节,写成1byte或者1B。
- 8 bit=1 B
- 1024 B=1 KB
- 1024 KB=1 MB
- 1024 MB=1 GB
- 1024 GB=1 TB
一个字节有八位
进制:
逢几进一,就是几进制
分类:
- 十进制:逢十进一,每位数字0~9
- 二进制:逢二进一,每位数字0~1
- 八进制:逢八进一,每位数字0~7
- 十六进制:逢十六进一,每位数字0~9,A[10],B[11],C[12],D[13],E[14],F[15]
目的:每种类型的字节数不同,它的取值范围就不同,需要根据需求做出选择
Java程序在虚拟机中运行,虚拟机在内存中运行,也就是Java程序在内存中运行
运算符
运算符用于连接值。
算术运算符
+ | 加 |
- | 减 |
* | 乘 |
/ | 除 |
% | 模(取余) |
++ | 自增 |
-- | 自减 |
- 注释:可移植性是Java语言的设计目标之一。无论在哪个虚拟机上运行,同意运算应该得到同样的结果。对于浮点数的算术运算,实现这样的可移植性是相当困难的。double类型使用64位存储一个数值,而有些处理器则使用80位浮点寄存器。这些寄存器增加了中间过程的计算精度。
例如:
double w = x * y / z;
很多Intel处理器计算x * y,并且将结果存储在80位的寄存器中,再除以z并将结果截断为64位。这样可以得到一个更加精确的计算结果,并且还能够避免产生指数溢出。但是这个结果可能与始终使用64位计算的结果不一样。因此,Java虚拟机的最初规范规定所有的中间计算必须进行截断。这种做法遭到了数学社区的反对。截断计算不仅可能导致溢出,而且由于截断操作需要消耗时间,所以实际上的计算速度要比精确计算慢。因此,Java程序设计语言承认了最优性能与理想的可再生性之间存在的冲突,并给予了改进。在默认情况下,现在虚拟机设计者允许对中间计算结果采用拓展的精度。但是对于使用strictfp关键字标记的方法必须使用严格的浮点计算来生成可再生的结果。
例如:
可以把main方法标记为
public static strictfp void main(String[] args)
那么,main方法中的所有指令都将使用严格的浮点计算。如果将一个类标记为strictfp,那么这个类中的所有方法都要使用严格的浮点计算。
具体的计算细节取决于Intel处理器的行为。在默认情况下,中间结果允许使用扩展的指数,但不允许使用扩展的尾数(Intel芯片支持截断尾数时并不损失性能)。因此,这两种方法的区别仅仅是采用默认方法不会产生溢出,而采用严格的计算有可能产生溢出。
数值类型之间的转换
当用一个二元运算符连接两个值时(例如 n+f,n是整数,f是浮点数),先要将两个操作数转化为同一种类型,然后再进行计算。
- 如果两个操作数中有一个是double类型,另一个操作数就会转化为double类型;
- 否则,如果其中一个操作数是float类型,另一个操作数就会转化为double类型;
- 否则,如果其中一个操作数是long类型,另一个操作数将会转化为long类型;
- 否则,两个操作数都将被转换为int类型。
强制类型转换
在Java中,允许进行强制类型转换(cast),虽然,这种转换可能会丢失一些信息。强制类型转换的语法格式是在圆括号中给出想要转换的目标类型,后面紧跟待转换的变量名。
例如:
double x = 9.997;
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。
如果运算符得到一个值,其类型与左侧操作数的类型不同,就会发生强制类型转换。例如,如果x是一个int,则以下句子
x += 3.5;
是合法的,将把x设置为(int)(x + 3.5)
关系与boolean运算符
Java包含丰富的关系运算符。用==、!=、<、>、<=、>=、&&、||(&&、||运算符是按照"短路"方式来求值的)等关系运算符检测相等性。
例如:
3 == 7的值为false
3 != 7的值为true。
expression1 && expression2
第一个表达式的真值为false,那么结果就不可能为true。
expression1 || expression2
第一个表达式的真值为true,结果为true。
x != 0 && 1 / x > x + y
如果x等于0,那么第二部分就不会计算。
Java支持三元操作符?:
如果条件为true,下面的表达式
condition ? expression1 : expression2
就为第一个表达式的值,否则计算为第二个表达式的值。
例如:
x < y ? x : y
会返回x和y中较小的一个。
位运算符
& | ("and") |
| | ("or") |
^ | ("xor") |
~ | ("not") |
>> | 位模式左移 |
<< | 位模式右移 |
- 注释:应用在布尔值上时,&和|运算符也会得到一个布尔值。这些运算符与&&和||运算符很类似,不过&和|运算符不采用"短路"方式来求值,也就是说,得到计算结果之前两个操作数都需要计算。
- 警告:移位运算符的右操作数要完成模32的运算(除非左操作数是long类型,在这种情况下需要对右操作数模64)。例如:1 << 35的值等同于1 << 3 或 8。
- 注释:在C/C++中,不能保证>>是完成算术移位(扩展符号位)还是逻辑移位(填充0)。实现者可以选择其中更高效的任何一种做法。这意味着C/C++中的 >> 运算符对于负数生成的结果可能会依赖于具体的实现。Java则消除了这种不确定性。
运算符级别
运算符优先级
运算符 | 结合性 |
[]、()(方法调用) | 从左向右 |
!、~、++、--、+(一元运算)、-(一元运算) ()(强制类型转换) new | 从右向左 |
*、/、% | 从左向右 |
+、- | 从左向右 |
<<、>>、>>> | 从左向右 |
<、<=、>、>=、instanceof | 从左向右 |
==、!= | 从左向右 |
& | 从左向右 |
^ | 从左向右 |
| | 从左向右 |
&& | 从左向右 |
|| | 从左向右 |
?: | 从右向左 |
=、+=、-=、*=、/=、%=、&=、|=、^=、<<=、>>=、>>>= | 从右向左 |
字符串
从概念上讲,Java字符串就是Unicode字符序列。例如,字符串"Java\u2122"由5个Unicode字符J、a、v、a和TM组成。Java没有内置的字符串类型,而是在标准Java类库中提供了一个预定义类。很自然的叫做String。每个用双引号括起来的字符串都是String类的一个实例:
String e = "";
String greeting = "Hello";
字符串
String类的substring方法可以从一个较大的字符串提取出一个子串。例如:
String greeting = "Hello";
String s = greeting.substring(0,3);
创建一个由字符"Hel"组成的字符串。
- 注释:类似于C和C++,Java字符串中的代码单元和代码点从0开始计数。
substring方法的第二个参数是不想复制第一个位置。这里要复制位置为0、1和2(从0到2,包括0和2)的字符。在substring中从0开始计数,直到3为止,但不包含3。
substring容易计算子串的长度。字符串s.substring(a,b)的长度为b-a。例如:子串"Hel"的长度为3-0=3。
拼接
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);
如果需要把多个字符串放在一起,用一个界定符分隔,可以使用静态join方法:
String all = String.join("/","S","M","L","XL");
在Java11中,还提供了一个repeat方法:
String repeated = “Java”.repeat(3);
不可变字符串
String类没有提供修改字符串中某个字符的方法。如果希望将greeting的内容修改为"Help!",不能直接将greeting的最后两个位置的字符修改为'P'和'!'。
greeting = greeting.substring(0,3) + "p!";
由于不能修改Java字符串中的单个字符,所以在Java文档中将String类对象称为是不可变的(immutable),如同数字3永远是数字3一样,字符串"Hello"永远包含字符H、e、l、l和o的代码单元序列。你不能修改这些值,不过,可以修改字符串变量greeting,让它引用另外一个字符串,这就如同可以让原本存放3的数值变量改成存放4一样。
- 注释:在C程序员第一次接触Java字符串的时候,常常会感到困惑,因为他们总将字符串认为是字符数组:
char greeting[] = "Hello";
Java字符串其实是类似于char*指针,
char* greeting = "Hello";
当把greeting替换为另一个字符串的时候,Java代码大致进行下列操作:
char* temp = malloc(6);
strncpy(temp , greeting , 3);
strncpy(temp + 3 , "p!" , 3);
greeting = temp;
的确,现在greeting指向字符串"Help!"。即使最顽固C程序员也得承认Java语法要比一些一连串的strncpy调用舒服得多。不过,如果对greeting做另一个赋值会怎样?
greeting = "Howdy";
这样做会不会产生内存泄漏呢?毕竟原始字符串在堆中分配。而Java将自动的进行垃圾回收。如果一个内存块不再使用了,系统最终会将其回收。
如果你是C++程序员,习惯使用ANSI C++定义的String类,会感觉使用Java的String类型更舒服。C++String对象也会自动地进行内存的分配与回收。内存管理是通过构造器、赋值操作和析构器显示执行的。不过,C++字符串是可修改的,也就是说,可以修改字符串中的单个字符。
检测字符串是否相等
可以使用equals方法检测两个字符串是否相等。对于表达式:
s.equals(t);
如果字符串s与字符串t相等,则返回true;否则,返回false。需要注意的是,s与t可以是字符串变量,也可以是字符串字面量。例如:以下表达式是合法的:
"Hello".equalsIgnoreCase("hello")
一定不要使用==运算符检测两个字符串是否相等!这个运算符只能够确定两个字符串时否存放在同一个位置上。当然,如果字符串在同一个位置上,它们必然相等。但是,完全有可能将内容相同的多个字符串副本放置在不同的位置上。
String greeting = "Hello";
if(greeting == "Hello")
if(greeting.substring(0,3) == "Hel")
如果虚拟机始终将相同的字符串共享,就可以使用==运算符检测是否相等。但实际上只有字符串字面量是共享的,而+或substring等操作得到的字符串并不共享。因此,千万不要使用==运算符检测字符串的相等性,以免在程序中出现这种最糟糕的bug,看起来这种bug就像随机产生的间歇式错误。
- 注释:对于习惯使用C++的String类的人来说,在进行相等检测的时候一定要特别小心。C++的String类重载了 == 运算符以便检测字符串内容的相等性。可惜Java没有采用这种方式,它的字符串“外观”看起来就像数值一样,但进行相等性测试时,表现得又类似于指针。Java语言的设计者本来也可以像对+那样进行特殊处理,为字符串重新定义 == 运算符。当然,每一种语言都会存在一些不太一致的地方。
C程序员从不使用 == 对字符串进行比较,而是使用strcmp函数。Java的compareTo方法完全类似于strcmp,因此其,可以如下这样使用:
if(greeting.compareTo("Hello") == 0)
不过,使用equals看起来更为清晰。
空串与Null串
空串""是长度为0的字符串。可以调用以下代码检查一个字符串是否为空:
if(str.length() == 0)
或
if(str.equals(""))
空串是一个Java对象,有自己的串长度(0)和内容(空)。不过,String变量还可以存放一个特殊的值,名为null,表示目前没有任何对象与该变量关联。
要检查一个字符串是否为null,要使用以下条件:
if(str == null)
又是要检查一个字符串既不是null也不是空串,这种情况下就需要使用以下条件:
if(str != null && str.length() != 0)
码点与代码单元
Java字符串由char值序列组成。char数据类型是一个采用UTF-16编码表示Unicode码点的代码单元。最常用的Unicode字符使用一个代码单元就可以表示,而辅助字符需要一对代码单元表示。
length方法将返回采用UTF-16编码表示给定字符串所需要的代码单元数量。例如:
String greeting = "Hello";
int n = greeting.length();
想得到实际长度,即码点数量,可以调用:
int cpCount = greeting.codePointCount(0 , greeting.length());
调用s.charAt(n)将返回位置n的代码单元,n介于0~s.length() - 1之间。例如:
char first = greeting.charAt(0);
char last = greeting.char;
要想得第i个码点,应该使用下列语句
int index = greeting.offsetByCodePoints(0 , i);
int cp = greeting.codePointAt(index) ;
使用UTF编码表示字符O(U+1D546) 需要两个代码单元。调用
char ch = sentence.charAt(1);
返回的不是一个空格,而是O的第二个代码单元。为了避免这个问题,不要使用char类型。太底层了。
注释:不要以为可以忽略包含U+FFF以上代码单元的奇怪字符,喜欢emoji表情符号的用户可能会在字符串中加入类似的🍺(U+1F37A , 啤酒杯)的字符。
如果想要遍历一个字符串,并且依次查看每一个码点,可以使用下列语句:
int cp = sentence.codePointAt(i);
if (Character.isSupplementaryCodePoint(cp)) i += 2;
else i++;
可以使用下列语句实现反向遍历:
i--;
if (Character.isSurrogate(sentence.charAt(i))) i--;
int cp = sentence.codePointAt(i);
显然,这很麻烦。更容易的办法是使用codePoints方法,它会生成一个int值的“流”,每个int值对应一个码点。可以将它转化成一个数组,再完成遍历。
int[] codePoints = str.codePoints().toArray();
反之,要把一个码点数组转换为一个字符串,可以使用构造器。
String str = new String(codePoints , 0 , codePoints.length);
注释:虚拟机不一定把字符串实现为代码单元序列。在Java9中,只包含单字节代码单元的字符串使用byte数组实现,所有其他字符串使用char数组。
7.包裹类型:
对于基本数据类型,Java提供了对应的包裹(wrap)类型。这些包裹类型将一个基本数据类型的数据转换成对象的形式,从而使得它们可以像对象一样参与运算和传递。
基本类型 | 包裹类型 |
boolean | Boolean |
char | Character |
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
整数共4个字节
一个字节8位
所以整数共有32位
整数的最大值为231-1
因为“值”从0开始表示,0已经占去一个位置,所以要减一了。
2的32次方算的是用8个坑位,最多可表示多少个数字,属于“数量”的概念。但是现在说的是“值”这个概念,它是从“0”开始的。“值”是0,但是“数量”已经是1了;如果“数量”是0,那就表示不了“值”了。
都是阿拉伯数字,但是0和0含义不一样,一个0表示没有,一个0表示最小值
Java当中的所有整数为[-232 0 232-1]
MIN_VALUE MAX_VALUE
public class ParcelType{
public static void main(String[] args){
Scanner in = new Scanner(System.in);
int i = 10;
Integer k = 10;
k = i;
System.out.println(Integer.MAX_VALUE);
}
}
包裹类型的用处
- 获得该类型的最大值最小值
- Integer.MIN_VALUE
- Integer.MAX_VALUE
运算符
- 当需要让一个类或对象做事情的时候,用.运算符
- a.length
- Integer.MAX_VALUE