1. Java语言基础
1.1. 引言
如何使用java程序,解决计算圆的面积的简单问题?
人们解决任何问题的思想,方法和步骤,都可以理解为算法,人们解决问题的方法有好有坏,因此算法性能上也就有高有低之分。
算法在计算机中是指令的集合,解决特定问题而定义的一系列操作,算法是计算机解题的过程,先要有解题思路,然后再编写程序,解题思路是算法的逻辑形式,编写代码是算法的代码体现形式,算法是设计最具有创造性的工作之一。
算法可以用自然语言,或者伪代码(自然语言和程序设计代码一起使用)
public class ComputerArea { public static void main(String[] args) { // 第一步:获取半径?并将半径保存在程序中
// 第二步:计算面积,数学固定算法
// 第三步:在控制台显示面积 } } |
1:解决计算圆面积的问题
1:需要圆的半径
2:有现成的求圆公式
1:面积=半径*半径*π
3:显示面积
double radius=8, area;
double n=3.1415;
area=radius*radius*n;
System.out.println(area);
编写程序,编写代码其实就是把算法翻译成程序,要完成这个程序需要知道,如何定义类,如何定义程序的入口main方法,如何声明变量,使用运算符,使用输出语句等基础。
2:程序实现
1:每个java应用程序都需要有一个main方法,是程序的入口需要将计算圆面积的代码放到main方法中,暂时这么办,可以更好的实现。
2:为了存储半径,需要在程序中声明一个称谓变量(变量)的符号
1:变量时指在程序中用于存储数据和计算结果的内存位置,每个变量都有自己的名字,
可以用变量访问它在内存中的位置
2:变量名应该尽量选择描述性的文字,本例中使用radius表示半径,area表示面积
3:为了让编译器能够认识radius和area需要指定是什么数据类型的
1:java的基本数据类型有整数,浮点数、字符以及布尔类型可以称之为原始类
型(primitive data type )或者基本类型(fundamental type)
2:半径和面积都有可能是小数,所以使用浮点数
1:浮点数有double和float即双精度浮点数和单精度浮点数这里我们使
用double双精度浮点数
3:计算面积
1:radius*radius*3.14结果需要保存
2: area=radius*radius*3.14
4:显示面积
使用System.out.println()语句在控制台上显示area的值
代码实现:
public class ComputeArea { public static void main(String[] args) { // 第一步:获取半径?并将半径保存在程序中 double radius = 5; // 第二步:计算面积,并将面积保存在程序中 double area = radius * radius * 3.1415; // 第三步:在控制台现实面积 System.out.println("半径为" + radius + "的圆的面积为:" + area); } } |
著名计算机科学家沃思提出一个公式:数据结构+算法=程序。
1 对数据的描述。在程序中要指定数据的类型和数据的组织形式,即数据结构(data structure)。
2 对操作的描述。即操作步骤,也就是算法(algorithm)。
Java语言基础组成
3.1 关键字
3.2 标识符
33 注释
3.4 常量和变量
3.5运算符
3.6 语句
3.7 函数
3.8 数组
1.2. 关键字(keyword)
为什么要有关键字:被java提前占用的单词。
定义:被Java语言赋予了特殊含义的单词,对于编译器而言是有特定含义的,所以不能在程序中用于其他目的,例如当编译器看到class时,就知道class后跟的是类的名字。例如第一天写的程序中还有public static void 都是关键字。
特点:关键字中所有字母都为小写
这些关键字不能当做标识符使用
不必死记硬背,如果使用关键字作为标识符,编译器能提示错误。
注意一:
The keywords const
andgoto
are reserved, even though they are not currently used.
关键字const
和goto保留,即使他们目前不使用。
注意二:
true
, false
, and null
might seem like keywords, but they are actually literals; youcannot use them as identifiers in your programs.
真、假、空似乎是关键字,但它们实际上是字面值;你不能在程序中使用它们作为标识符 ,但是也不是关键字.
答疑:问什么 goto 是保留关键字
在C/C++ 等语言中, 使用goto 可以实现程序的跳转,例如: 在多重嵌套循环中,可以直接从内层循环跳出到外层循环,然而由于使用goto 没有任何限制,可以随意执行,打破了程序的正常的执行流程,如果程序多次使用goto, 降低程序的可读性,程序也难于编写和维护.Java 为了避免出现这种情况出现,取消了goto 关键字使用, 但是为了避免程序员自行使用goto 作为标识符引起混乱(变量名方法名涉及为goto),所以Java 将goto 设计为了关键字,用来限制程序员将goto 作为标识符使用, 所以就出现了一个从不使用的关键字. 也称之为保留字.
查看官方文档:
http://docs.oracle.com/javase/tutorial/java/nutsandbolts/_keywords.html
1.3. 标识符(Identifiers)
标识符,就是用来为Java 中的类,方法,变量等起的名字,可以通过标识符类访问对应的类方法变量. 这就像人的名字一样,每一个人都有一个名字与之对应,通过人名可以找到对应的人.
Java中的包、类、方法、参数、和变量名,可以由任意顺序的大小写字母、数字、下划线_和美元$ 。注意:标识符不能以数字开头,不能是Java中的关键字。标识符不能有空格
什么是标识符?
编写程序时用到的单词,就是程序员在定义java程序时,自定义的一些名字,例如helloworld 程序里关键字class 后跟的Demo,就是我们定义的类名。类名就属于标识符的一种。
我们的ComputeArea程序中用于声明类的名字的ComputeArea,用于存储半径的radius,存储面积的area,都是出现在程序中事物的名字,这样的名字就叫做标识符。
标识符的定义规则
标识符必须遵循以下规则
标识符由26个英文字符大小写(a~zA~Z)、数字(0~9)、下划线(_)和美元符号($)
组成
不能以数字开头,不能是关键字
严格区分大小写
标识符的可以为任意长度
合法标识符
ComputeArea,radius,area $itcast _itcast gz_itcast
注意:由于Java严格区分大小写,ITCAST 和itcast是完全不同的标识符
非法标识符
class
100java
Hellojava
Java中的标识符命名规范
包名:
多个单词组成时所有字母小写
package com.itcast
类名:
多个单词组成时所有单词的首字母大写
HelloWorld
变量名和函数名:
多个单词组成时第一个单词首字母小写,其他单词首字母大写
lastAccessTime getTime
常量名
多个单词组成时,字母全部大写,多个单词之间使用_分隔
INTEGER_CACHE
注意:标识符在定义的时候最好见名知意,提高代码阅读性。
1.4. 注释
为了提高程序的阅读性,用于注释说明解释程序。
注释是标注该程序是干什么的,以及是如何创建的。注释有助于程序员之间沟通和理解程序
编译器会忽略单行和多行注释。
1、 单行注释(line comment)
用//表示,编译器看到//会忽略该行//后的所有文本
2、 多行注释(block comment)
用/**/表示,编译器看到/*时会搜索接下来的*/,忽略掉/**/之间的文本
public static void main(String[] args) { // 第一步:获取半径?并将半径保存在程序中 double radius = 5; // 第二步:计算面积,并将面积保存在程序中 /* double area = radius * radius * 3.1415; // 第三步:在控制台现实面积 System.out.println("半径为" + radius + "的圆的面积为:" + area); */
} |
3、 文档注释
对于文档注释,是java特有的注释,其中注释内容可以被JDK提供的工具 javadoc 所解析,生成一套以网页文件形式体现的该程序的说明文档。
例如:本例中使用javadoc -d test -version -author Demo1.java 命令
-d 指定说明文件的存放目录
test 说明文件存放目录
-version 代表要求javadoc程序在说明文件中加入版本信息
-author 加入作者信息。
注释是一个程序员必须要具有的良好编程习惯。初学者编写程序可以养成习惯:先写注释再写代码。将自己的思想通过注释先整理出来,在用代码去体现。因为代码仅仅是思想的一种体现形式而已。
/** @author jack @version 1.0 */
class Demo{ /* 这是主函数,是程序的入口 它的出现可以保证程序的独立运行 */ public static void main(String[] args){ //这是输出语句用于将括号内的数据打印到控制台。 System.out.println("hello java"); } } |
注意:多行注释中可以嵌套单行注释,多行注释不能嵌套多行注释。错误!!!
class Demo{ /* 这是主函数,是程序的入口 它的出现可以保证程序的独立运行 /* 注意:多行注释嵌套多行注释是不行的。 */ */ public static void main(String[] args){ //这是输出语句用于将括号内的数据打印到控制台。 System.out.println("hello java"); } |
编码习惯:
初学者编写程序的习惯:先写注释再写代码
文档注释(/** */)只能在类、方法和属性的上面。
注释的使用细节:
1. 嵌套问题
单行注释是可以嵌套单行注释的
但是多行注释不能嵌套多行注释
1.5. 计算机中的数值单位
计算机是由逻辑电路组成,逻辑电路通常只有两个状态,开关的接通与断开,这两种状态正好可以用“1”和“0”表示。为了存储和处理信息,计算机就利用电路的这两种状态:关(off)和开(on),可以看做是0和1,通过关和开的排列组合,即0和1的排列组合,来表示数字,字母,符号以及其他类型的信息。这就是二进制的由来,二进制数的一位所包含的信息就是一比特,即0和1称之为比特(bit),这就是计算机的二进制。所以计算机存储的都是二进制,无论文档,图片视频等等,都是以二进制的形式存储在计算机中的。
计算机中的位
二进制数系统中,每个0或1就是一个位(bit),位是数据存储的最小单位。其中8bit就称为一个字节(byte)。计算机中的CPU位数指的是CPU一次能处理的最大位数。例如32位计算机的CPU一次最多能处理32位数据。
二进制如何存储信息?
在计算机中通常将8个基本二进制数据(bit)表示一个字节.8个2进制代表一个字节,由n个字节表示数据,就是计算机表示数据的方式.计算机内存中存放的都是二进制数据
1Byte=8bit比特 1Byte就是1个字节
1KB=1024Byte
1MB=1024KB
1GB=1024MB
1TB=1024GB
在计算机领域,人们还经常使用210、220、230、240等数值作为度量单位,分别简称为K、M、G、T,它们对应的数值分别如下:
(1)1K = 210 = 1024,约等于103;
(2)1M = 220 = 1024×1024,约等于106,即约等于一百万(兆);
(3)1G = 230 = 1024×1024×1024,约等于109,即约等于十亿;
(4)1T = 240 = 1024×1024×1024×1024,约等于106×106,即约等于万亿(即兆兆)。
Byte:8个二进制数代表一个字节 1Byte = 8bit
KB: 1024个字节代表一个K字节 1KB = 1024Byte 2的十次方个字节
MB: 1024个KB代表一个M字节 1MB = 1024KB 2的二十次方字节
GB: 1024个MB代表一个G字节 1GB = 1024MB 2的三十次方字节
TB: 1024个GB代表一个T字节 1TB = 1024GB 2的四十次方字节
人们通常所说的硬盘大小和内存大小的基本单位就是byte(字节),譬如,1M内存就是指大约一百万个字节的数据量,而人们通常说的网络数据流量的基本单位是bit(比特),譬如,1M网速指的是大约一百万个比特的数据量。所以,从理论上讲,一个1M大小的文件在1M网速的网络上需要8秒才能传输完毕。
网络度量单位:
kbps 10的3次方位秒(bit)
Mbps 10的6次方位秒
Gbps 10的9次方位秒
Tbps 10的9次方位秒
问:个人电脑的有线网卡都是100Mbps,意味着,我在百兆的居于网络中每秒可以传输多少数据? 就是100Mbps/8= 12.5MB/S 。明白这个就知道运营商提供的宽带4Mbps带宽达不到4M/S了,实际只有500KB/S。
1.6. Java的数据类型
使用Java编写程序,要求用户输入两个整数,将这两个整数相加,然后在控制台显示他们的和.
程序=数据+指令+文档。
上述程序运行会用到数据,数据在计算机中如何表示?
如果我们想要使用java实现加法运算,例如我们要计算1+5的结果,不能直接去要求计算机去算,而要先跟计算机请求一个地方存放1,另外一个地方存放5,然后让计算机计算这两个地方存放的数字的和。 通过刚才对计算机的数值单位的了解,已经知道了知道计算机里面保存一个数字或者一个字母,都是需要分配一定的空间,内存空间的最小单位是比特(bit),8个比特为一个字节(byte)。为了保存不同的数字或者字母,我们在申请空间的时候就要告诉计算机,想要要保存什么类型的数据。而计算机会根据这个类型,分配一定尺寸的内存给用户。
通俗的讲,通常我们查看商品的价格时,可能是100块,可能是10分钱,也可能是5毛钱。这些数值后面跟的都有单位,我们知道了单位,数值才有意义.我们在写加法程序的时候,需要在程序中定义数据,定义数据的时候,显然需要告诉计算机这个数值是什么单位的.那么在Java程序中就是数据的类型,计算机根据声明的数据的类型,在内存中分配对应的空间用来存储数据。
Java对于每一种数据都定义了明确的具体数据类型,编译器会根据数据类型的不同在内存总分配不同大小的内存空间。
Java的基本数据类型在任何操作系统中都具有相同的大小。所有系统中,java变量的取值都是一样的。这也是java跨平台的一个特性。
1.6.1. 整数类型:
Java使用四种类型整数,byte、short、int、long
byte占用一个字节,数字大小为 -128~127 - 27 ~27 -1
short占用两个字节,数字大小为 - 32768~ 32767 -215 ~ 215-1
int占用四个字节,数字大小为 -2147483648~ 2147483647 -231 ~ 231-1
long占用八个字节,数字大小为 -9223372036854775808~9223372036854775807 -263 ~ 263 -1
类型 | 大小/位 | 大小/字节 | 取值范围 |
byte | 8 | 1 | -128~127 - 27 ~27 -1
|
short | 16 | 2 | - 32768~ 32767 -215 ~ 215-1
|
int | 32 | 4 | -2147483648~ 2147483647 -231 ~ 231-1
|
long | 64 | 8 | -263 ~ 263 -1
|
这些类型都是有符号的
1.6.2. 浮点数
Java使用两种类型浮点数:float和double。double是float的两倍。double叫做双精度浮点数,float叫做单精度浮点数。
类型名 | 大小/位 | 取值范围 |
float | 32 | 1.4E-45~3.4E+38,1.4E-45~-3.4E+38 |
double | 64 | 4.9E-324~1.7+308,-4.9E-324~-1.7E+308 |
注:1.5E-45表示1.5乘以10的-45次方 -1次方得10分之一,-2次方得100分之一。
注意:
1:int最常用(20亿左右)。long可以用在统计世界人口,byte,short用在特殊场合(如果知道存储在变量中的整数在一个字节范围内,就应该将变量声明为byte)
2:double和float,一般都使用double,double类型,因为double类型比float更精确。需要存储大量数据才考虑单精度一般使用(float可以节约内存)。
Java中每种整数类型所能存储的值
Max 01111111 |
byte |
Min 10000000 |
Max 01111111-11111111 |
short |
Min 10000000-00000000 |
Max 01111111-11111111-11111111-11111111 |
int |
Min 10000000-00000000-00000000-00000000 |
Max 01111111-11111111-11111111-11111111- 01111111-11111111-11111111-11111111 |
long |
Min 10000000-00000000-00000000-00000000- 10000000-00000000-00000000-00000000 |
注意:蓝色字符为最高位,是符号位1为负数,0为正
1.6.3. char 类型
Java中使用单引号表示字符,注意一个数字作为一个字符和作为一个数值的差别.数字128是一个可以用于数学运算的数值,在字符串中”128”中的1 2 8 只是字符.
用来存储诸如字母、数字、标点符号、及其他符号之类的单一字符。Java的字符占用两个字节,是Unicode 编码的。
char letter='a'; char num='1'; |
我们已经了解计算机内部使用二进制,一个字符在计算机中是以0和1构成的序列来存储的。将字符映射为它的二进制形式的过程称之为编码(encoding)。字符有多种不同的编码形式,编码表定义该如何编码每个字符。
疑问?键盘上的字符’A’在内存中是什么?,为什么我们屏幕上,看到的是A 这就涉及到了编码和解码
拓展信息:
计算机为了存储和处理信息,例如数字,字符,计算机科学家发明了码表,将这些数字字符都编码成为二进制,当我们想要在计算机中使用数据的时候,计算机进行了按照编码表编码和解码的工作,因为cpu要执行的数据和指令都以二进制数据(一组比特或者字节的)形式存在于内存中。
例如在ASCII(American Standard Code for InformationInterchange,美国信息交换标准代码)编码表中Java 的J是01001010二进制表示的,对应的十进制是74
ASCII
我们知道,在计算机内部,所有的信息最终都表示为一个二进制的字符串。每一个二进制位(bit)有0和1两种状态,因此八个二进制位就可以组合出256种 状态,这被称为一个字节(byte)。也就是说,一个字节一共可以用来表示256种不同的状态,每一个状态对应一个符号,就是256个符号,从 0000000到11111111。
上个世纪60年代,美国制定了一套字符编码,对英语字符与二进制位之间的关系,做了统一规定。这被称为ASCII码,一直沿用至今。
ASCII码一共规定了128个字符的编码,比如空格"SPACE"是32(二进制00100000),大写的字母A是65(二进制01000001)。这128个符号(包括32个不能打印出来的控制符号),只占用了一个字节的后面7位,最前面的1位统一规定为0。
大多数计算机都兼容ASCII码,基本的ASCII字符集中每个字符用7位二进制数来表示,因此可以表示128个不同的字符.
可以表示所有的
大小写字母(A~Z, a~z)
数字(0~9)
标点符号(.,:等)
特殊字符(&,|,\)
控制字符(回车,空格)
ISO-8859(Latin)
英语用128个符号编码就够了,但是用来表示其他语言,128个符号是不够的。比如,在法语中,字母上方有注音符号,它就无法用ASCII码表示。于是, 一些欧洲国家就决定,利用字节中闲置的最高位编入新的符号。比如,法语中的é的编码为130(二进制10000010)。这样一来,这些欧洲国家使用的编码体系,可以表示最多256个符号。
GB2312
计算机如果使用7位的ASCII编码,或者8位的ISO-8859-1编码,是无法处理汉字的计算机科学家设计了用于简体中文的GB2312和用于繁体中文的big5码表。
由于一个字节只能表示256个符号,无法有效的表示中文,所以中国的GB2312 自然使用了2个字节表示中文. 如果使用两个字节表示一个汉字,所以理论上最多可以表示256x256=65536个符号。
GB2312(1980年)一共收录了7445个字符,包括6763个汉字和682个其它符号。
GBK
GB2312支持的汉字太少。1995年的汉字扩展规范GBK1.0收录了21886个符号,它分为汉字区和图形符号区。汉字区包括21003个字符。
GB18030
2000年的GB18030是取代GBK1.0的正式国家标准。该标准收录了27484个汉字,同时还收录了藏文、蒙文、维吾尔文等主要的少数民族文字。
现在的PC平台必须支持GB18030,对嵌入式产品暂不作要求。所以手机、MP3一般只支持GB2312。
有的中文Windows的缺省内码还是GBK,可以通过GB18030升级包升级到GB18030。不过GB18030相对GBK增加的字符,普通人是很难用到的,通常我们还是用GBK指代中文Windows内码。
ASCII、GB2312、GBK到GB18030,这些编码方法是向下兼容的,即同一个字符在这些方案中总是有相同的编码,后面的标准支持更多的字符。在这些编码中,英文和中文可以统一地处理。
Unicode
世界上存在着多种编码方式,同一个二进制数字可以被解释成不同的符号。因此,要想打开一个文本文件,就必须知道它的编码方式,否则用错误的编码方式解读,就会出现乱码。
如果有一种编码,将世界上所有的符号都纳入其中。每一个符号都给予一个独一无二的编码,那么乱码问题就会消失。这就是Unicode 所以Unicode 也叫做:统一码、万国码、
Unicode 学名: UniversalMultiple-Octet Coded Character Set 简称 UCS
目前的用于实用的Unicode版本对应于UCS-2,使用16位的编码空间。也就是每个字符占用2个字节,基本满足各种语言的使用。Unicode使用16个二进制位表示一个字符.所以可以支持表示65535个不同字符.并且Unicode码包括ASCII码,所以可以理解为ASCII是Unicode的一个子集.
ANSI
如果使用记事本同学发现有一种ANSI 编码,其实是系统默认的编码方式。对于英文文件是ASCII编码,对于简体中文文件是GB2312编码(只针对Windows简体中文版,如果是繁体中文版会采用Big5码)。
JAVA和Unicode
Java使用了统一码(Unicode)统一码支持世界不同的语言。最初被设计为2个字节(16比特)的字符编码,能够产生65536个字符。一个Unicode码占两个字节,用\u开头的4位十六进制数表示,范围从’\u0000’到’\uffff’例如:中文:欢,迎的unicode码是分别是'\u6b22','\u8fce'
如何获得Unicode 码
Microsoft Word或者金山WPS之下,按下Alt键不放,输入 0 和某个字符的 Unicode 编码(十进制),再松开 Alt 键即可得到该字符,如Alt + 033865会得到Unicode字符“叶”(繁体)。另外按Alt + X 组合键,MS Word 也会将光标前面的字符同其十六进制的四位 Unicode 编码进行互相转换。
char ch='A'; System.out.println(ch); ch='\u0041'; System.out.println('\u0041'=='A'); //true //自增和自减运算符可以用在char变量上,会得到该字符之前之后的Unicode码 System.out.println(++ch); //B |
特殊字符的转义序列:转义字符
需求:使用输出语句,打印出带引号的信息例如输出
System.out.println("teachersaid"java is fun"");编译是无法正常通过的。语法有错误,编译器读到第二个引号就认为是字符串的结束,剩余的不知道怎么处理。
如何解决这个问题:java中使用转义字符来表示特殊的字符,。一个转义字符以反斜杠开始,(\)
转义字符
想要打印带引号的字符串怎么办,就可以使用反斜杠(\)后跟字符,这个反斜杠就是转义字符。
转义字符 名称 Unicode \b Backspace (退格键) \u0008 \t Tab (Tab键盘) \u0009 \n Linefeed (换行) \u000A \r Carriage Return(回车) \u000D \\ Backslash (反斜杠) \u005C \' Single Quote (单引号) \u0027 \" Double Quote (双引号) \u0022 |
\r 回到一行开头,回车
\n 表示换行。
\t 制表符,相当于Table键
\b 退格键,相当于Back Space
\’ 单引号
\’’ 双引号
\\ 表示一个斜跨
上述问问题解决:System.out.println("teachersaid\"java is fun\"");
注意:换行符就是另起一行,回车符就是回到一行的开头,所以我们平时编写文件的回车符应该确切来说叫做回车换行符
1.6.4. boolean 类型
boolean由数学家Geogore Boole 发明
boolean 类型用来存储布尔值,在java中布尔值只有2个,true和false。
boolean flag=true; flag=false; |
Java中这8中基本数据类型都是小写的。
1.7. 常量
编写Java程序计算给定半径的圆的周长,参考数学公式
C=2πr
该数学公式中 2和圆周率π的值是已知的,将该公式转换成Java程序时,显然2和π的值是固定不变的值,它们有明确的值,不会改变,这就是常量.
注意:在本次教学中π我们定义为 3.14即可.
1.7.1. 整形常量
十进制、十六进制、八进制
十进制:0,1,2,3,4,5,6,7,8,9 不能以0开头
十六进制:0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f 十六进制以 0x,0X开头
八进制:0,1,2,3,4,5,6,7 八进制以 0开头。
默认情况下,整形常量是一个十进制整数,要表示八进制的常量,就用0开头,十六进制就用0x或者0X开头。
整形常量默认是int类型,32位(bit)4个字节。范围在-2147483648到2147483647。
长整形:
100000000000L
为了表示一个long型的常量需要在数字后加L或者l(小写字母l)但是l(小写字母l)和数字1不易区分,所以推荐使用L。
想要输出2147483648这个整数,必须在结尾处加上L,就是2147483648L,因为2147483648超出了int的范围。
System.out.println(2147483648L);
1.7.2. 浮点数
float 32位单精度浮点数结尾为f(F)
double 64位双精度浮点数结尾为d(D)
浮点数默认是双精度,所以float类型一定要加f。
0.5f 或者0.5F 1.555d 或者3.1415D,或者3.14
1.7.3. 布尔常量
布尔用于区分一个事物的正反两面。只有两个值 true 和flase
1.7.4. 字符常量
将一个数字字母或者符号用单引号( ' ' )标识,java中字符占用2个字节,使用Unicode码表示。’a’ ‘b’
1.7.5. 字符串常量
将一个或者多个字符用双引号标识。表示一连串字符。
“helllo java”
这里的双引号,单引号都是英文下的。
1.7.6. null常量
只有一个值,表示引用为空。
1.8. 进制转换
人类习惯的数值是十进制,但是计算机中是二进制,所以在计算机内部要进行转换。
1.8.1. 十进制
由0、1、2、3、4、5、6、7、8、9组成一个十进制数是用一个或者多个这些数构成的一个排列。
例如十进制数7423的表示
1.8.2. 二进制
例如:1101
十进制转二进制
例如十进制123转二进制1111011
除以2,反向取余数,直到商为0终止。
二进制转十进制
看下图
十进制的一种表示方法:例如十进制数7423的表示
十进制数第0位的权值是10的0次方,第1位的权值是10的1次方……
二进制转十进制转换公式
二进制数第0位的权值是2的0次方,第1位的权值是2的1次方……
由于计算机中保存的二进制,对于大的整数数据而言,二进制形式过于复杂(长)
导致计算的时候会比较繁琐,所以计算机中还有另外两种进制表现形式。八进制和十六进制
1.8.3. 八进制
由数字0~7 组成,就是逢8进1,以0开头。为什么是0~ 7 其实是将二进制的每
三位当做八进制的一位,二进制的000~111 正好就是十进制的0到7。
1位(bit)就是二进制中的一个数,3位就是8进制中的一个数
十进制转八进制
除以8,反向取余数,直到商为0终止。
例如十进制120 转8进制是170
八进制转十进制
八进制数第0位的权值为8的0次方,第1位权值为8的1次方,第2位权值为8的2次方…
二进制转八进制
方案一:
将二进制转成十进制,在将十进制转成八进制.
1111000--->120--->170
2进制--->10进制--->8进制
方案二:
将二进制从低位开始的每3位转为8进制数即可。高位不足的空位补0
1111000 (二进制)
000--->0
111--->7
011--->1
1111000 (二进制) ---> 170 (八进制)
八进制转二进制
将8进制的数的每一位转为二进制,整体就是八进制对应的二进制。
170(八进制)
1--->001
7--->111
0--->000
170(八进制)---> 001111000 (二进制)
1.8.4. 十六进制
0,1,2,3,4,5,6,7,8,9, a(10) b(11) c(12) d(13)e(14) f(15) 十六进制以 0x,0X开头(a到f或者A到F)其实是二进制的每4位,当做十六进制的一位,0-9 只能表示10个数,就从字母那里借了a-f 表示16个数。二进制的0000-1111 就是十进制的0到15 逢16进1.
十进制转十六进制
10进制数转换成16进制的方法,和转换为2进制的方法类似,唯一变化:除数由2变成16。
十进制数除以16直到商为0,反向取余数。
图例是将十进制123转为16进制.
十六进制转十进制
公式
二进制与十六进制转换
十六进制转二进制
如何将十六进制转二进制?
把十六进制的每一位数转换为四位的二进制位,
例如,十六进制7B转二进制是1111011,7的二进制位是111,B的二进制位是1011
二进制转为十六进制
将二进制转为十六进制,从右往左将每四位二级制数转换为一位十六进制数。
例如:二进制1110001101 的十六进制是38D,如何得到,该二进制从右往左,每四位转换为十六进制,1101 是D,1000是8,0011是3。
1.9. 变量
1.9.1. 变量
编写Java程序计算给定半径的圆的周长,参考数学公式
C=2πr
该数学公式中 2和圆周率π的值是已知的,将该公式转换成Java程序时,已知2和π是常量,半径r 和根据半径计算出的周长是会变化的.那么就需要存储这些变化的数据,那么圆的半径和周长就需要定义变量来存储.
计算机的存储设备:
1. 硬盘 存储的数据永久保存
2. 内存 断电后数据消失(注意)
变量是用于存储程序中用到的数据。被称为变量是因为变量的值可能会改变。
变量是内存中的一个存储区域,该区域有自己的名称(变量名)和类型(数据类型),该区域的数据可以在同一类型范围内不断变化。变量是一段有名字的内存,用来存储java程序中的信息。
为什么要定义变量:用来不断的存放同一类型的常量,并可以重复使用。
变量用于表示特定类型的数据。如何使用变量可以告诉编译器变量的名字和存储的数据类型来声明该变量。
1.9.2. 变量声明
变量声明用于告诉编译器根据数据类型为变量分配合适的存储空间。(variable declaration)
格式如下:
数据类型 变量名; |
例如:
int number; //声明的number是一个int变量 double area; //声明的area是一个双精度浮点数变量 double salary; |
上述例子中使用了数据类型int和double。
如果几个变量为同一类型,可以一起声明。
例如:
int x, y, z; //声明了x,y,z,3个int类型变量。 |
变量声明细节:
按照java标示符命名规范,变量名使用小写字母表示。如果一个名字由多个词组成,多个单词组成时第一个单词首字母小写,其他单词首字母大写
lastAccessTime getTime
1.9.3. 变量初始化
int number; number = 10; |
我们可以一步完成变量的声明和初始化。上述2行等同于下面一行代码
int number= 10; |
定义变量的格式:数据类型 变量名 = 初始化值;
定义变量的格式:数据类型 变量名 = 初始化值; 例如: int max = 100; |
注:格式是固定的,记住格式,以不变应万变。变量就如同数学中的未知数。
1.9.4. 变量的有效取值范围
系统为不同数据类型的变量类型分配了不同的空间大小。
例如,double型变量在内存中占用8个字节,float占用4个字节。byte占用1个字节。
举例1:
byte b=126 //ok byte e=128 |
编译报错,128超出了byte类型的取值范围。byte范围是(-128~127)
举例2:
float f=3.5 ;
编译报错,小数常量默认类型为double。double 型常量在内存中占用8个字节,Java 为float 变量只分配了4个字节,将8个字节的内容装入4个字节的容器,存不下。float f=3.5f 编译即可通过。或者double f=3.15;
1.10. Java的运算符
有了数据,数据也能够进行存储了,想要操作数据该怎么办?需要进行加减乘除等运算,在java中使用程序如何实现?
运算符是一种特殊的符号,用来表示数据的运算、赋值和比较
算术运算符
赋值运算符
比较运算符
逻辑运算符
移位运算符
1.10.1. 算术运算符
“+”是正号、加法运算、还有一个功能,将字符串连起来,并且任何值与字符串相加都得字符串。
System.out.println("abc"+"def");//abcdef
System.out.println(123+"abc");//123abc
“*”“/”乘和除
int x = 3515; x = x / 1000 * 1000;// ? 3515 System.out.println(x); // 3000 |
注意:上述结果为什么是3000而不是3515?对于除号“/” 整数和小数是有区别的:整数之间除法,只保留整数部分而舍弃小数部分。
如果想要使用小数点后的部分。考虑使用double 或者float
double d=3515; d=d/1000*1000; System.out.println(d); //3515.0 float f=3515f; f=f/1000*1000; System.out.println(f); //3515.0 |
总结:当除法操作数都是整数时,除法的结果就是整数,结果的小数部分会被舍弃。
例如5/2结果是2.而不是2.5。所以为了实现现实生活中的除法,可以让其中一个数为浮点数,5.0/2=2.5,或者5/2.0=2.5。
“++”“--”加加和减减
int x = 1; int y=1; y = ++x; // x先自增,x自增后的结果赋值给y System.out.println(x); // 2 y = x++; // x的值先赋给y,然后x再自增。 System.out.println(x); // 3 System.out.println(y); // 2 先运算再取值。 |
++x 是在变量参与其他运算之前先将自己加1,再用新值参与运算。而x++是先用原值参
与其他运算,再将自己加1。
结论:
如果运算符在变量的前面,则该变量自增1或者自减1,然后返回的是变量的新值,如
果运算符在变量的后面,则变量也会自增或者自减1,但是返回的是变量原来的值。++在前就是先运算,再取值,++在后就是先取值,再运算。
自增自减运算符案例:
完成如下运算: 一; int i = 10; int newNum = 10 * i++; 11 System.out.println(newNum);//? 110 二: int i = 10; int newNum = 10 * ++i;//? 11 System.out.println(newNum); //110 一可以理解为 int i = 10; int newNum = 10 * i; //10 i = i + 1; //i=11 二可以理解为 int i = 10; i = i + 1; i=11 int newNum = 10 * i; //11 newNum=110
|
|
“%” 取模,取余数
运算符%是取得除法运算的余数。%左边的操作是被除数,右边的是除数
System.out.println(7%3); System.out.println(12%4); System.out.println(26%8); System.out.println(20%3); 7%3=1; 12%4=0, 26%8=2, 20%3=2; |
分析:%就是除法运算取余数
注释:Divisor:除数, Dividend:被除数,Quotient:商,Remainder:余数
如果%可以用在正整数上,如果用于负整数是什么结果?
如果是除数是负数,可以把除数的负号忽略不计。例如
int x = 7; int y = -2; System.out.println(x % y); // 1 |
但是如果被除数是负数就需要注意了:
int x = -7; int y = 2; System.out.println(x % y); // -1 |
只有当被除数是负数时,余数的结果才是负数。
System.out.println(-5 % 2); //-1 System.out.println(5 % -2); //1 System.out.println(-5 % -2); //-1 除法: System.out.println(-5 / 2); // -2 System.out.println(5 / -2); // -2 System.out.println(-5 / -2); // 2 |
运算符案例:
1使用程序判断一个整数是偶数还是奇数
2 使用程序判断假设今天是星期6,那么问10天后的今天是星期几?
3 使用程序计算500秒是几小时几分钟几秒?
4:将数值表达式使用Java程序翻译,并通过程序求出运算结果
其中int x=1;inty=2,int a=3,int b=4,int c=5;
案例1:
public static void main(String[] args) { // 判断一个整数一奇数还是偶数 int x = -100; // 奇数是,1,3,5...偶数是2,4,6...显然整数除2能整除,也就%(取模)结果为0就是偶数。 int result = x % 2; System.out.println(result); // 使用判断语句进行判断。 if (result == 0) { System.out.println(x + "是偶数"); } else { System.out.println(x + "是奇数"); } } |
方案2 使用判断该数结果是否是奇数。
(但是该算法有问题,如果被判断的整数为负数是否有效?)
public static void main(String[] args) { // 判断一个整数一奇数还是偶数 int x = 1; // 奇数是,1,3,5...偶数是2,4,6...显然奇数%的结果为1. int result = x % 2; System.out.println(result); // 使用判断语句进行判断。 if (result == 1) { System.out.println(x + "是奇数"); } else { System.out.println(x + "是偶数"); } } |
改进
public static void main(String[] args) { // 判断一个整数一奇数还是偶数 int x = -1; // 奇数是,1,3,5...偶数是2,4,6...显然奇数%的结果为1. int result = x % 2; System.out.println(result); // 使用判断语句进行判断。 if (result != 0) { System.out.println(x + "是奇数"); } else { System.out.println(x + "是偶数"); } } |
案例二:判断星期
public static void main(String[] args) { // 设定今天是星期1,用int 1表示星期一,0表示星期天 int today = 1; // 十天后是星期几?,一个星期是7天,7天之后又是星期1,可以用? int future = (today+10) % 7; if (future == 0) { System.out.println("10天后是星期天"); } else { System.out.println("10天后是星期:" + future); }
} |
案例三:求时间
求:1小时 23分 20秒共多少秒? int seconds = 5000; int hour; int minutes; int second; // 1:通过seconds除%60得到秒数 second = seconds % 60; System.out.println(second); // 2:通过seconds除以60得到总的分钟数,minutes int totalMinutes = seconds / 60; // 3:通过总的分钟数%60得到分钟数 minutes = totalMinutes % 60; // 4:通过总的分钟数/60获取总的小时数 int totalHour = totalMinutes / 60; // 5:通过总的小时数%24获取小时数 hour = totalHour % 24; System.out.println(hour + " :" + minutes + ":" + second);
|
案例4:
int x = 1; int y = 2; int a = 3; int b = 4; int c = 5; int result = (3 + 4 * x) / 5 - 10 * (y - 5) * (a + b + c) / x + 9* (4 / x + (9 + x) / y); System.out.println(result); // 442 |
1.10.2. 赋值运算符
= , +=,-=, *=, /=, %=
运算符 | 运算 | 范例 | 结果 |
= | 赋值 | a=3,b=2 | a=3,b=2 |
+= | 加等于 | a=3,b=3;a+=b; | a=5,b=2; |
-= | 减等于 | a=3,b=2,a-=b; | a=1,b=2; |
*= | 乘等于 | a=3,b=2,a*=b; | a=6,b=2 |
/= | 除等于 | a=3,b=2,a/=b; | a=1,b=2; |
%= | 模等于 | a=3,b=2,a%=b; | a=1,b=2 |
a+=b 可以想象成 a=a+b;
例如在声明和初始化变量的时候,已经用到了赋值运算符.
变量声明完了之后,可以使用赋值语句(assignmentstatement)给变量赋一个值,Java中使用等号(=)作为基本的赋值运算符(assignmentoperator),
格式如下:
variable = expression; 变量 = 表达式;
|
变量我们已经知道如何声明,表达式是什么?
表达式的:
表达式涉及到值(常量),变量和通过运算符计算出的值,以及他们组合在一起计算出的新值。
x =y+1;
例如:
public static void main(String[] args) { int x = 1; // 声明int变量x,赋值1给变量x int y = 0; // 声明int变量y,赋值0给变量y double area; // 声明double变量area double radius = 1.0; // 声明double变量radius,并赋值1.0给变量radius x = 5 * (3 / 2) + 3 * 2; // 将=右半部分表达式的计算结果赋值给变量x x = y + 1; // 将变量y和1的求和的值赋值给变量x area = radius * radius * 3.14159; // 将计算面积的值赋值给变量area } |
赋值运算符小问题
问题1: int x; System.out.println(x = 1); 如何理解? 答:等价于 x=1; System.out.println(x); 注意:不能 1=x,变量名必须在赋值运算符的左边。
|
问题二: int x; int y; int z; x = y = z = 100; 如何理解? 答:等价于 int x; int y; int z; z = 100; y = z; x = y;
|
1.10.3. 比较运算符
如何比较两个值? 如何编写Java程序判断整数3和5中较大的值?
比较运算符比较的两边操作数,结果都是boolean的,只有true和false两种结果。
运算符 | 运算 | 例子 | 结果 |
= = | 相等于 | 4= =3 | false |
!= | 不等于 | 4!= 3 | true |
< | 小于 | 4 < 3 | flase |
> | 大于 | 4>3 | true |
<= | 小于等于 | 4<=3 | false |
>= | 大于等于 | 4>=3 | true |
instanceof | 检查是否是类的对象 | "hello"instanceof String | true |
注意:比较运算符 = = 是两个= ,如果只有一个那就是赋值了。
int x = 7; int y = 3; System.out.println(x == y); // false System.out.println(x = y); //3 System.out.println(x != y); |
1.10.4.逻辑运算符
使用Java程序判断某一年是否为闰年.
很显然,该年份被4整除但不能被100整除,或者可以被400整除满足上述条件就是闰年.需要将多个条件表达式的结果进行逻辑处理(并且和或者).这就需要使用逻辑运算符.
什么是逻辑运算符?连接比较运算符的符号称之为逻辑运算符。那么为什么要连接比较运算符? 举例:当你去公司应聘,招聘要求,男性(判断为真),并且开发经验1年(判断为假)那么,我们还适合去面试吗,不能,因为只满足了一项,总体是不满足的(总体结果为假)。
逻辑运算符用于对boolean型结果的表达式进行运算,运算的结果都是boolean型。我们的比较运算符只能进行一次判断,对于对此判断无能为力,那么逻辑运算符就可以经将较运算符连接起来。
逻辑运算符用于连接布尔型表达式,在Java中不可以写成3<x<6,应该写成x>3 & x<6 。
“&”和“&&”的区别:单与时,左边无论真假,右边都进行运算;双与时,如果左边为真,右边参与运算,如果左边为假,那么右边不参与运算。
“|”和“||”的区别同理,双或时,左边为真右边不参与运算。
“ ^ ”异或与“|”或的不同之处是:当左右都为true时,结果为false。
& 与 | 或 ^ 异或 ! 非
1、&与
true & true = true ; talse & true= false; true & false = false; false & false= false;
|
总结 & 符号特点
& : 只要两边的boolean 表达式结果,有一个false.那么结果就是false
只有两边都为true ,将结果为true.
2、|或
true | true =true; ture | false =true; false | true =true; false | false =flase; |
总结 | : 两边只要有一个为真结果就为真,当两边同为假时结果才为假.
3、^ 异或
true ^ true =false; ture ^ false =true; false ^ true= true; false ^ false=flase; |
^ : 两边相同结果是false
两边不同结果是true;
4、!非
!true = false !false= true
|
5、&& 短路
研究发现,&运算只有两边全为真的时候,结果才为真,那么当左边为假的时候就没有必要在进行判断,&&就产生了。
int a =4;
a >3&& a< 6;
a >3& a< 6 ;
在这种情况下世没有区别的
如果:
a =2
a >3& a< 6 2大于 3 为假, 接着运算 2 小于6 为真,总的结果为假
a >3&& a< 6; 此时a 不大于3 结果为false 右边不运算了.即短路.所以&& 比& 效率稍微高了一点.
public static void main(String[] args) { int x = 0; int y = 1; if (x == 0 && y == 1) { System.out.println(x + y); } } |
1.10.5. 位运算符
按位操作符用来操作整数基本数据类型中的单个比特(bit),就是二进制,按位操作符会对两个参数中对应的位(bit)执行布尔运算,最终生成一个结果。按位操作符来源于C语言面向底层的操作,Java设计的初衷是嵌入式电视机机顶盒,所以面向底层的操作也保留了下来。
任何信息在计算机中都是以二进制的形式保存的,”&”、“|”、“^”除了可以作为逻辑运算符也可以作为位运算符。位运算是直接对二进制进行运算。他们对两个操作数中的每一个二进制位都进行运算。例如int是由32个二进制数组成,因此使用位运算符可以对整数值的二进制数进行运算。
位(bit)运算符:
位运算符
| 运算符含义
|
& | 与(AND) |
| | 或(OR) |
^ | 异或 |
~ | 取反 |
规则:
可以把1当做true 0当做false
只有参与运算的两位都为1,&运算的结果才为1,否则就为0。
只有参加运算的两位都是0,| 运算的结果才是0,否则都是1。
只有参加运算的两位不同,^ 运算的结果才为1,否则就为0。
1、&与运算
& 参见运算的两位数都为1,&运算符结果才为1,否则就为0。
6&3
00000000 | 00000000 | 00000000 | 00000110 | 6 |
00000000 | 00000000 | 00000000 | 00000011 | 3 |
00000000 | 00000000 | 00000000 | 00000010 | & =2 |
2、|或运算
| 参与运算的两位都为0,|运算的结果才为0,否则就为1。
00000000 | 00000000 | 00000000 | 00000110 | 6 |
00000000 | 00000000 | 00000000 | 00000011 | 3 |
00000000 | 00000000 | 00000000 | 00000111 | | =7 |
3、^异或运算
^只有参加运算的两位不同,^运算的结果才为1,否则就为0。
00000000 | 00000000 | 00000000 | 00000110 | 6 |
00000000 | 00000000 | 00000000 | 00000011 | 3 |
00000000 | 00000000 | 00000000 | 00000101 | ^ =5 |
1、~ 反码
就是取反,二进制只有1和0,取反就是如果为1,取反就是0,如果是0,取反就是1。
0000-0000 | 0000-0000 | 0000-0000 | 0000-0110 | 6 |
1111-1111 | 1111-1111 | 1111-1111 | 1111-1001 | 取反 -7 |
System.out.println(~6);//-7
4、负数表示
负数对应的正数的二进制取反(反码)再加一。
-6
0000-0000 | 0000-0000 | 0000-0000 | 0000-0110 | 6 |
1111-1111 | 1111-1111 | 1111-1111 | 1111-1001 | 取反 |
1111-1111 | 1111-1111 | 1111-1111 | 1111-1010 | 加1 |
5、异或特点
一个数异或同一个数两次,结果还是那个数. 用处一个简单的加密思想.
6^3^3
0000-0000 | 0000-0000 | 0000-0000 | 0000-0110 | 6 |
0000-0000 | 0000-0000 | 0000-0000 | 0000-0011 | ^3 |
0000-0000 | 0000-0000 | 0000-0000 | 0000-0101 |
|
0000-0000 | 0000-0000 | 0000-0000 | 0000-0011 | ^3 |
0000-0000 | 0000-0000 | 0000-0000 | 0000-0110 | 结果是6 |
除了这些位运算操作,还可以对数据按二进制位进行移位操作,Java的移位运算符有三种。
1.10.6. 移位操作符
<< 左移
>> 右移
>>>无符号右移
位运算符 | ||
运算符 | 运算 | 范例 |
<< | 左移 | 3 << 2 = 12 --> 3*2*2=12 |
>> | 右移 | 3 >> 1 = 1 --> 3/2=1 |
>>> | 无符号右移 | 3 >>> 1 = 1 --> 3/2=1 |
& | 与运算 | 6 & 3 = 2 |
| | 或运算 | 6 | 3 = 7 |
^ | 异或运算 | 6 ^ 3 = 5 |
~ | 反码 | ~6 = -7 |
位运算符的细节 | |
<< | 空位补0,被移除的高位丢弃,空缺位补0。 |
>> | 被移位的二进制最高位是0,右移后,空缺位补0; 最高位是1,空缺位补1。 |
>>> | 被移位二进制最高位无论是0或者是1,空缺位都用0补。 |
& | 二进制位进行&运算,只有1&1时结果是1,否则是0; |
| | 二进制位进行 | 运算,只有0 | 0时结果是0,否则是1; |
^ | 任何相同二进制位进行 ^ 运算,结果是0;1^1=0 , 0^0=0 不相同二进制位 ^ 运算结果是1。1^0=1 , 0^1=1 |
技巧:可以理解为二进制1就是true,0就是false。
案例:
1、左移 (算术移位)
3<<2 是如何在计算机里是实现的?
首先将3转换为2进制,
00000000 | 00000000 | 00000000 | 00000011 | 3 的二进制 | ||
00000000 | 00000000 | 00000000 | 000011 | 左移2位,砍掉高位 | ||
0000 0000 | 0000 0000 | 0000 0000 | 0000 1100 | 低位补0 |
结果是12,所以3<<2 =12;
2、右移
6>>2
00000000 | 00000000 | 00000000 | 00000110 | 6的二进制 | ||
000000 | 00000000 | 00000000 | 00000001 | 右移10被砍掉 | ||
00000000 | 00000000 | 00000000 | 00000001 | 高位补0 |
结果是1,所以6>>2 =1;
结论一个数往左移越移越大,往右边移越来越小.
6/4=1 ; 6/2=3 ;
右移两位就是除以 2的2次方,右移一位就是除以 2的一次方。
用处:最快的运算是位运算。
3、无符号右移 (逻辑移位)
通过演示发现右移时高位就空了出来,>>右移时高位补什么要按照原有 数据的最高位来决定。
1111-11111111-1111 1111-1111 1111-1010 -6>>2
1111-11111111-1111 1111-1111 1111-0010
最高位补什么要看原有最高位是什么
那么使用>> 后原来是最高位1 的那么空出来的最高位还是1 的,是0的还是0。
如果使用>>> 无论最高位是0还是1 空余最高位都拿0 补,这就是无符号右移。
1111-11111111-1111 1111-1111 1111-1010 -6>>>2
001111-11111111-1111 1111-1111 1111-10
结果是;1073741822
1.10.7. 三元运算符
格式
(条件表达式)?表达式1:表达式2;
如果条件为true,运算后的结果是表达式1;
如果条件为false,运算后的结果是表达式2;
示例:
1获取两个数中大数。
intx=3,y=4,z;
z =(x>y)?x:y;//z变量存储的就是两个数的大数。
int x = 1; int y = 2; int z; z = x > y ? x : y; System.out.println(z); //2 |
2判断一个数是奇数还是偶数。
int x=5; System.out.println((x%2==0?"偶数":"奇数")); |
1.11. 基本数据类型的转换
1.11.1. 自动类型转换
也叫隐式类型转换
可以将一个数赋值给更大数值范围的变量,例如可以将byte 变量赋值给short变量可以将short变量赋值给int变量可以将int变量赋值给long变量。
Java内部其实做了工作就是自动将数值进行了类型提升,就叫做自动类型转换(也叫隐式类型转换)
byte b = 1; //00000001 short s = b; //00000000 00000001 int i = s; long lon = i; float f=lon; double d = lon; //1.0 |
自动类型转换(也叫隐式类型转换)
要实现自动类型的转换,需要满足两个条件,第一两种类型彼此兼容,第二目标类型取
值范围必须大于源类型。所有的数字类型,包括整形和浮点型彼此都可以进行转换。
例如:
byte b=100; int x=b; System.out.println(x);//程序把b结果自动转换为int类型。 |
1.11.2. 强制类型转换
也叫显式类型转换
不可以将一个数值赋给范围更小数值范围的变量,除非进行类型转换。
byte b = 100; b = b + 2; System.out.println(b); |
上述例子发生了什么,发生了类型转换。
b+2 遇到了加法运算,2默认是int类型,byte类型b变量存储的值自动类型提升为
了int类型。执行完加法运算后的结果就是int类型,想要将int的类型值放入到byte类型变量b中,无法放入,编译报错。
System.out.println((double)1/2); //0.5 System.out.println((double)(1/2)); //0.0 int i=5; byte b=(byte)i; System.out.println(i); //5 double d=4.5; int i=(int)d; System.out.println(i); //4
|
byte b=1; b=(byte)(b+2); |
当两种类型彼此不兼容,或者目标类型取值范围小于源类型(目标是byte源是int)
无法自动转换,此时就需要进行强制类型转换。
强制类型转换需要注意:
损失精度!!!
int a=128; byte b=(byte)a; System.out.println(b);//-128 /* * 此时的强转已经造成了数值的不准确 */ |
int
00000000 | 00000000 | 00000000 | 10000000 |
10000000 |
byte
再次分析此行代码
byte b = 100; b = b + 2; System.out.println(b); |
编译:提示如下错误。
1.11.3. 类型转换的原理
可以把byte 理解为1两的碗,short 2两的碗,int 4两的碗,long 8两的碗。1两碗的满碗酒可以倒入 2两 4两 8两的碗中。但是 4两碗的酒倒入1两碗的酒就有一些问题。
注意:将int型或者long型转换为float型或者将long型转换为double型时,某些最低有效位数字可能会丢失.
什么时候要用强制类型转换
比如小数部分只想保留整数部分.
一定要清楚要转换的数据在转换后数据的范围内否则会损失精度.
public static void main(String[] args) { byte b = 100; b = (byte) (b + 2); System.out.println(b); // 102 //舍弃小数部分 double d=5.5; int num=(int)d; } |
1.11.4. 表达式的数据类型自动提升
算术表达式,逻辑表达式进行运算时,会先将两个操作数转换为同一种类型,然后在进行计算.
所有的byte型、short型和char的值将被提升到int型。
如果一个操作数是long型,计算结果就是long型;
如果一个操作数是float型,计算结果就是float型;
如果一个操作数是double型,计算结果就是double型。
分析 System.out.println(‘a’+1)结果?
自动类型提升
byte b = 3; int x = 4; x = x + b;// b会自动提升为int类型参与运算。 System.out.println(x);// 7
|
强制类型转换
byte b = 2; /* * 强制类型转换,强制将b+2强制转换为byte类型,再赋值给b */ b = (byte) (b + 2); System.out.println(b);// 4 |
思考1
byte b=126;
问:既然数据默认的有数据类型,那么126 默认是int类型的,为什么存储到byte类型时不会报错呢。
126 是常量java在编译时期会检查该常量(每个常量)是否超出byte类型的范围。如果没有可以赋值。
思考2:byte b=128;能否正常的编译和运行。
该语句会出现编译错误,128超出了byte变量的存储范围,所以出现编译错误。
思考3
byte b1=3,b2=4,b;
b=b1+b2;
b=3+4;
哪一句编译失败?为什么?
b =3+4, 3和4都是常量,所以java在编译时期会检查该常量(每个常量)是否超出byte类型的范围。如果没有可以赋值。例如b=128+1 就无法编译通过。b=127+1;也是无法通过。
b =b1+b2 不可以,因为b1 和b2 是变量,表达式求值时,变量值会自动提升为int型,表达式结果也就成了int型,这是要赋值给byte型的b,必须进行强制类型转换了。
思考4:short s1 = 1;
s1= s1+1;
s1+=1;
问:s1= s1+1; s1+=1; 与有什么不同?
对于short s1 = 1; s1 = s1 + 1; 由于s1+1运算时会自动提升表达式的类型,所以结果是int型,再赋值给short类型s1时,编译器将报告需要强制转换类型的错误。
对于short s1 = 1; s1 += 1;由于 += 是java语言规定的运算符,java编译器会对它进行特殊处理,因此可以正确编译。
6、System.out.println(‘a’+1)结果
美国人为了让计算机识别他们生活中的文字,让二进制表示生活中的文字.所以一个字母代表了一个二进制.,二进制也有十进制的表现形式.,把生活中的字母都用数字来标识,例如97 代表a ,98 代表 b。打印’a’就把a作为输出显示,没有疑问。但是 ‘a’+1 有加号涉及到了运算。根据java自动类型提升规则,同样道理 char 提升为int 。就把’a’代表的数字体现了出来。a 表示的是97 97+1就是98; 那么想要查看98 表示的char 是什么怎么实现呢 ?就要用到刚才介绍的强制类型转换了 System.out.println(char(‘a’+1));就取到了98 在ASCII码表中表示的字符。大写A 和小写a 在 ASCII有不同的表现。还有一个概念字符’1’ 在ASCII中 不是数字 1,可以运行代码查看,到此就可以明白了char 类型,char类型也是可以参与运算的,为什么可以参与运算呢。因为字符在ASCII表中都有对应的数字体现。所有的计算机兼容ASCII。
System.out.println('a'+1); //98
System.out.println((char)('a'+1)); //b
补充问题:
int i='a'+'b'; System.out.println(i);//结果? System.out.println("hello"+'j'); //结果? |
总结:
所有数值运算符都可以用在char型数据上,如果另一个操作数是一个数字或者字符,那么char会自动提升为int型,如果另一个操作数是字符串,那么字符就会和字符串相连。
1.11.5. 作业练习:
1:使用输出语句,输出如下效果
hello \nihao "?
2:类名、方法名、常量和变量的命名规范是什么?
3: 编写程序根据圆柱体的半径和高,计算圆柱的体积
公式如下:面积=半径*半径*π
体积=面积*高
半径和高使用变量定义。
4:代码的运行结果
public static void main(String[] args) { int res = 12+012+0x12; System.out.println(res); System.out.println(0xFFFF); } |
5:说出以下代码运行结果
public static void main(String[] args) { System.out.println( 12/0 ); } |
6:如果错误修改正确
public static void main(String[] args) { int a = 1234l; }
|
7:如果错误修改正确
public static void main(String[] args) { long a = 12345678910; } |
8:运行结果
public static void main(String[] args) { int a = 0; a++; System.out.println(a++); System.out.println(++a); } |
9:运行结果
public static void main(String[] args) { System.out.println( 5%-2+123/100+10 ); } |
10:运算结果
public static void main(String[] args) { int a = 1; System.out.println( a+=2+ a++ + ++a ); } |
1最有效率的方式算出2乘以8等于几?
使用2*8 可以实现但是效率不是最高的,最高的是进行位移运算 2<<3
2.对两个整数变量的值进行互换(不需要第三方变量)
1.定义第三方变量
int m = 3; int n = 8; int z; z = m; m = n; n = z; System.out.println(m); System.out.println(n); |
1(方案2):
int m = 3; int n = 8; System.out.println(m); System.out.println(n); m = m + n;// 8+3; 11 8 n = m - n;// 11-8; 3 m = m - n;// 11-3; 8 System.out.println(m); System.out.println(n);
|
若果n和m 的值非常大,容易超出int范围.
1(方案3):
int n = 8; int m = 3; n = n ^ m;// 8^3; m = n ^ m;// 8^3^3; 8 n = n ^ m;// 8^3^8; 3
|