Java语言的类型系统.ppt_第1页
Java语言的类型系统.ppt_第2页
Java语言的类型系统.ppt_第3页
Java语言的类型系统.ppt_第4页
Java语言的类型系统.ppt_第5页
已阅读5页,还剩59页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

Lecture Notes on Object-Oriented Programming & Design /lwj/object-oriented/ Dr. LI Wenjun /lwj/ Department of Computer Science SUN YAT-SEN UNIVERSITY, GZ 510275,第三讲 Java语言的类型系统,数据类型概述 Java语言的基本数据类型 符号常量 运算符与表达式 类型转换 简单的输入输出,3.1 数据类型概述,字母C ASCII字符 二进制串:01000011 无符号整数 正整数67,类型的作用,所有数据均属于某一特定类型 类型决定了数据的内部表示方式 有符号整数占用4个字节且最高位表示正负符号,双精度浮点数占用8个字节且这8个字节又分为阶码和尾数两部分(IEEE 754),. 类型决定了数据的取值范围 表示方式决定取值范围与精度,例如2个字节表示的有符号短整数取值范围仅为-32 768至+32 767,. 类型决定了数据上的可用操作 例如两个整数可进行加、减、乘、除、整除、取模等运算;两个字符串可进行比较、连接、判断子串等操作,但不可作四则算术运算。 同一类型的不同数据具有相同的表示方式、取值范围和可用操作,强类型 vs 弱类型,强类型(strong-typing) 程序中的每一数据都明确地属于某一类型(“先声明、后使用”原则);数据所属的类型声明后不可动态改变。 强类型语言:Java、C+、Ada、Pascal、. 弱类型(weak typing) 不强制数据一定属于某种类型;数据的类型通常由运行环境通过类型推导规则来确定。 弱类型语言:Smalltalk、Foxpro、许多脚本语言、.,强类型带来的好处,对编译程序而言: 可生成更高效率的目标代码。 可帮助程序员发现并定位与类型有关的错误。 对程序员而言: 提高了程序的可读性。,数据:在程序中表达实体的属性。 常量变量数据。 常量:在程序执行过程中取值不能改变的数据。 变量:在程序执行过程中取值可改变的数据。,程序中的数据,如何确定数据的类型,常量:类型由数据的书写形式确定(以值代名)。 800、1500 是整数类型的常量; 800.0、3.14159 是双精度浮点数类型常量; a、$ 是字符类型常量; “Data Structure”、“确认退出?” 是字符串类型常量。 通常使用后缀修饰那些不是默认的类型,如800L、3.14F。 变量:显式地声明变量的类型。 程序员自由选择标识符为变量命名。 遵循“先声明、后使用”原则。 double balance; int total, average; 早期也有一些高级语言通过书写形式确定变量的类型,例如:如IAGE是整数类型、XAVERAGE是浮点类型。,变量的4个要素,名字 类型 地址 值,E.Dijkstra:一旦你理解了在程序设计中变量的使用方法,你就理解了程序设计的精华。,变量的左值(Lvalue)与右值(Rvalue)!,Java语言提供了8种基本数据类型 又称原始(primitive)数据类型。 Integral char、byte、short、int、long Numeric Floating float、double Logical boolean Java语言的类型系统(Type System) 基本类型 数组(array)类型 引用类型 class 用户自定义类型(UDT) interface,3.2 Java语言的基本数据类型,特殊值:null,有人也将char另分类为Textual,Primitive,Java不把void作为一种类型 故不能用(void)作类型转换,布尔类型,常量 true、false 变量 boolean isMarried; / 职工是否已婚 boolean hasNext = true; / 是否有下一数据需处理,表示方法 只需占用1位。 Java语言并未规定编译器的实现方式。 取值范围 true, false 可用操作 可用:赋值运算、关系运算(仅=和!=)、逻辑运算、位运算(位非除外)、条件运算、. 不可用:算术运算、位非运算。,字符类型,常量 普通字符: A、9、$、_、 、. 转义(escape)字符: n 、t、“、. 7、07、007、. xdd、udddd、. 变量 char choice; / 用户输入的选择结果 char choice = Y; / 用户输入的选择结果 Java语言采用Unicode编码(双字节) C和C+语言采用ASCII码(单字节),表示方法 采用Unicode编码:/。 取值范围 类型 长度 取值范围 char 2字节(16位) u0000 uFFFF 0 65,535 可用操作 可用:赋值运算、算术运算、关系运算、位运算、条件运算、. 不可用:逻辑运算。,整数类型,常量 8 进制数: 0开头,其后只允许出现0至7;例如,0123。 16进制数: 0x开头,其后允许出现0至9和A至F;例如,0x53。 10进制数: 其余开头。例如,83。 整数常量只有int和long类型。 默认类型是int;指定long类型必须加后缀L或l:83L、0x53L。 变量 byte age; / 职工的年龄 short length; / 数组的长度 int size = 0; / 用户输入数据的大小 long max = 0; / 所求的最大数目,表示方法与取值范围 类型 长度 取值范围 byte 1字节(8位) -27 27-1 (有符号二进制补码,下同) -128 +127 short 2字节(16位) -215 215 -1 -32,768 +32,767 int 4字节(32位) -231 231 -1 -2,147,483,648 +2,147,483,647 long 8字节(64位) -263 263 -1 9,223,372,036,854,775,808 9,223,372,036,854,775,807 可用操作 可用:赋值运算、算术运算、关系运算、位运算、条件运算、. 不可用:逻辑运算。,C+的short、int和long的 取值范围依赖于机器字长,浮点类型,常量 小数表示法: 3.14、3.14F 科学记数法: 3.14E-5 默认类型是double,指定float类型须加后缀F或f:3.14F。 整数后缀D或d成为double类型:15D、3d。 变量 float balance; / 信用卡帐户的余额 double weight = 0; / 工件的重量 编程原则:如果double与float之间的空间效率差别不会对整个程序的效率产生明显影响时,应选用double类型。,表示方法 1985年通过的IEEE 754标准:阶码采用增码、尾数采用原码;数符位于最左位;尾数规格化,从而可多用1位精度。 32位(单精度)浮点数:阶码8位、尾数24位。 64位(双精度)浮点数:阶码11位、尾数53位。 取值范围 类型 长度 取值范围 float 4字节(32位) 约-3.41038 +3.41038 double 8字节(64位) 约-1.810308 +1.810308 可用操作 可用:赋值运算、算术运算、关系运算、位运算、条件运算、. 不可用:逻辑运算。,Java允许浮点数取模,与数学意义下实数的区别 (1) 程序中的浮点数是数学意义下实数的一个子集; (2) 程序中的浮点数是离散的而数学意义下的实数是连续的。 精度与溢出 JRE不执行运行期间的溢出检查。 没有C+语言的long double类型(10字节80位表示格式)。 JDK预定义的类:java.math.BigDecimal。,字符串类型,常量 “Programming in Java“ “His name is “John“.n“ “注意:7n李明正在上课!n“ 变量 String authorName = “; / 作者姓名 String message = “数据已保存!“; / 提示信息 String不是保留字,而是JDK预定义的可重用类。 注意“A“与A的区别!,注意在Unicode编码中, 1个汉字的长度仅占1位,变量的初始化,使用未设置初始值的变量会产生一个编译错误 例如: int x; int y = x + 1; Java语言的设计比C+语言更注重编程的安全性!,基本数据类型的包装类(wrapper),每一基本数据类型都有一个对应的包装类 Java比C+语言更接近纯(pure)面向对象程序设计语言! boolean Boolean char Character byte Byte short Short int Integer long Long float Float double Double,所谓常量只是指在程序运行过程其值保持不变, 但并不意味着在应用环境中或整个软件生存期会一成不变!,3.3 符号常量,编译器可保证符号常量只能初始化,而不能对其赋值。 适当使用符号常量可提高程序的可扩充性。,使用符号常量的好处,常量只能进行一次赋值 不同于C+语言:既可使用初始化表达式,也可使用赋值。 通常在声明的同时进行初始化: final double PI = 3.14; / 圆周率 final int MAX = 100; / 学生人数的上限 禁止对已有初始值的符号常量再次进行赋值!,符号常量的用法,3.4 运算符与表达式,表达式是对程序中数据的最基本操作 表达式运算符操作数 运算符 算术运算、关系运算、逻辑运算、位运算、. 一元、二元、三元 操作数类型值 注意Java语言不将void当作一种类型。,表达式的作用,求值结果类型值 由运算符以及参与运算的操作数(类型值)决定。 当表达式中有多个运算符时,还取决于运算符之间的优先级与结合性质。 副作用(side effect):在表达式求值过程中改变操作数的值 赋值运算是一种表达式: x = y、x += y、x+、. 方法调用是一个表达式: obj.f(x) 指派变量:可作为左值使用 C+语言允许条件运算“?:”的结果作为左值;Java语言不允许。,赋值运算,赋值运算符 x = expr 赋值表达式 求值结果:x的值、x的类型。 副作用:操作数x的值被改变。,复合与简化写法 除方便程序员外,还可生成效率更高的代码! x += expr、x -= expr、x *= expr、x /= expr、x %= expr x = expr、x = expr x &= expr、x |= expr、x = expr x+、+x、x-、-x x+与+x 副作用相同,但求值结果不同。,算术运算,算术运算符 x + y -x、x y x * y x / y 15 / 3、16 / 3、17 / 3 求值结果均为5 1 / 3、2 / 3 求值结果均为0 x % y 17 % 3 求值结果为2 28 % 5 求值结果为3 类型推导 op: X Y Z: X或Y为byte、short或char时,会隐式地放宽(提升)为int。 Z取决于X和Y的大者。 X和Y均不允许是boolean。,Signature,重载(overloading)运算符 运行符“/”的含义由其参数的类型确定。 Java语言不允许程序员重载现有的运算符 C+语言则允许程序员重载现有的运算符。,关系运算,关系运算符 x = y x y x != y 注意不是 x y。 类型推导 op: X Y boolean,其中: 对于=和!=,X和Y允许任意基本类型; 对于其他,X和Y不允许boolean。 注意引用类型的关系运算的特殊性!,字符串的比较 比较性质:属于对象的比较,比较特殊! 比较依据:Unicode字符集。 s1.euqals(s2) 区别(s1 = s2)! s1.euqalsIgnoreCase(s2) 忽略大小写的差别。 pareTo(s2) 返回:0(=)、0()。 pareToIgnoreCase(s2) 其他对象的比较 根类Object定义了equals()方法。 该方法缺省语义是浅比较而不是深比较,故需重定义equals()方法。 JDK预定义的类绝大部分重定义了equals()方法。,逻辑运算,逻辑运算符 x & y x | y !x 类型推导 &, |: boolean boolean boolean !: boolean boolean 与C+语言不同,不能将整型(short、int等)当作boolean使用。,短路(short-circuit)求值 只有两个逻辑运算会短路求值:“&”和“|”。 无论单纯逻辑表达式求值还是控制分支或循环,均以短路形式求值。 为什么要短路求值? 优化了时间效率仅仅是一方面原因。 对语言使用者(程序员编程)或实现者(设计编译器)的影响! if (count != 0) & (total / count 10) . if (obj != null) & obj.found() .,位运算,位运算符 x & y 0xff00 & 0xf0f0 求值结果为0xf000 x | y 0xff00 | 0xf0f0 求值结果为0xfff0 x y 0xff00 0xf0f0 求值结果为0x0ff0 (Exclusive OR,简称XOR) x 0xff00 求值结果为0x00ff 组合赋值 x &= y、x |= y、x = y,位运算的应用 较少应用场合才需要。 通常是面向设备级的底层应用,如机顶盒或其他嵌入式应用。 位运算的用法 每一个bit对应一种二值的开关状态。 使用易记忆的枚举符号常量帮助程序员记忆每一位的含义。,移位运算,移位运算符 x y 有符号右移(左补符号位) 256 4 求值结果为 256/24 = 16 -256 4 求值结果为 -256/24 = -16 x y 无符号右移(左补0) 类型推导 op: Integral Integral Integral 其中: 类型为byte、short或char的操作数会放宽(提升)为int。 返回结果为左操作数提升后的类型。,右操作数决定移位距离 如果左操作数提升后为int,则右操作数仅最低的5位作为移位距离; 如果左操作数提升后为long,则右操作数仅最低的6位作为移位距离。 思考:Why ?,条件运算,唯一的三元运算符 (x y)? x : y 类型推导 op: boolean X Y Z,其中: X和Y同属于数值类型,或 X和Y同属于boolean类型,或 X和Y同属于引用类型或null 否则会导致一个编译错误。,不允许像C+那样指派变量!,字符串运算,连接运算“” 运算符重载:注意此处的“+”不是算术运算。 只要有一个操作数是String类型,则运算符“+”解释为字符串连接。 生成一个新的字符串对象! 数据的字符串化(又称外表化,Externalization) 当String+X或X+String时,X无论是基本数据类型据或引用类型,都会自动转换为字符串类型文本描述形式。 String str1 = 3.14; / 错误的做法 String str2 = “ + 3.14; / 正确的做法 String str3 = 3.14 + “; / 正确的做法 引用类型X转换为字符串类型时,会调用对象的toString()方法。 根类Object定义了toString()方法,其他类可以重定义该方法。,优先级与结合性质,不明显的优先关系最好通过括号显式表达。 . () R to L + - + - ! instanceof new (T) * / % + - = = != & | & | R to L ?: R to L = *= /= %= += -= = = &= = |=,3.5 类型转换,隐式(implicit)类型转换 由编译器或运行环境自动完成。 更安全的设计:在不丢失信息的前提下才执行隐式转换。 显式(explicit)类型转换 由程序员手工写在源程序代码中。 如有丢失信息的可能,则必须由程序员显式地转换类型。,类型转换的工作原理,原数据的类型保持不变! 下次在同样情况下使用该数据时,仍需执行类型转换。 新类型的数据是原数据的一个副本 副本的类型与原数据不同。 副本的值尽可能保持与原数据一致(不丢失量或精度)。 从编译原理更容易看出:生成的中间代码(三元式)。 一个例子 salary = age * 1.5; 类型转换并不改变age本身的类型,而是创建age的一个副本!,类型转换的情形,赋值转换(Assignment Conversion) 表达式类型转换为某一变量的类型。 例子:float f = i; / 设i的类型为int 方法调用转换(Method Invocation Conversion) 实际参数的类型转换为形式参数的类型。 例子:double d = Math.sin(f); / 设f为float,sin()只支持double 显式类型转换(Casting Conversion) 通过类型转换运算符显式地转换表达式的类型。 例子:int i = (int) 12.5f; 字符串转换(String Conversion) 允许任何类型转换为String类型。 例子:System.out.println(“i = “ + i); 数值提升(Numeric Promotion) 提升数值运算符的操作数类型,从而可执行某一操作。 例子:f = f * i; / 设i的类型为int,f的类型为float,Java语言有5种类型转换的上下文(Context),类型转换的种类,恒等转换(Identity Conversions) 是平凡转换:自身到自身,所有类型都支持。 用途:提高可读性或借助编译器确保万一(例如,IDL编译器生成的代码)。 例子:(只存在显式转换) int i = 0; int j = (int) (i * 2);,Java语言支持7种类型转换,放宽基本类型转换(Widening Primitive Conversion) 共19条规则,均不会丢失“量”的信息,故允许隐式转换! byte short、int、long、float或double short int、long、float或double char int、long、float或double int long、float或double long float或double float double 例子: int i = 0; long j = i + 1; / 隐式转换 double x = (double) (j * 2); / 显式转换,仍可能会丢失精度!,收窄基本类型转换(Narrowing Primitive Conversion) 共23条规则,均可能丢失量与精度的信息,故不支持隐式转换! byte char short byte或char char byte或short int byte、short或char long byte、short、char或int float byte、short、char、int或long double byte、short、char、int、long或float 例子: long i = 0; int j = i + 1; / 会产生一个编译错误 float x = (float) 3.14; / 无显式转换将导致编译错误,放宽引用类型转换(Widening Reference Conversion) 共9规则,不需要运行时检测,允许隐式转换。 S T, S是T的子类(注意Object是所有类的父类!)。 S T, 类S实现了接口T。 null S, S是任意类、接口或数组类型。 J K, J是K的子接口。 J Object, J是任意接口。 A Object, A是任意数组。 A Cloneable, A是任意数组。 A Serializable, A是任意数组。 SA TA, SA和TA均为引用且可从SA放宽转换为TA。 例子:,收窄引用类型转换(Narrowing Reference Conversion) 共8规则,需要运行时检测(RTTI),仅支持显式转换。 S T, S是T的父类(注意Object是所有类的父类!)。 S T, S是非最终类且未实现接口T。 Object A, A是任意数组。 Object J, J是任意接口。 J T, J是任意接口而T是非最终类。 J T, J是任意接口而T是实现了J的最终类。 J K, J不是K的子接口且两者不含基调相同而返回类型不同的方法。 SA TA, SA和TA均为引用且可从SA收窄转换为TA。 例子:,字符串类型转换(String Conversion) 任何类型(包括null)均可转换为String类型。 所有基本类型的数据首先转换为对应的包装类; 执行每一个类都具有的toString()方法。 注意字符串类型转换是一种单向关系(不具备对称性)。 例子: System.out.println(“x = “ + x + “, y = “ + y); String result = 3.14;,Java语言禁止的类型转换 禁止任何引用类型转换为任何基本类型。 除字符串转换外,禁止任何基本类型转换为任何引用类型。 null仅支持恒等转换;禁止null转换为任何基本类型。 boolean仅支持恒等转换和字符串转换。 如果S不是T的子类且T也不是S的子类,则S到T除字符串转换外禁止任何转换。 如果S是最终类且未实现接口K,则禁止S转换为K。 如果S不是Object,则禁止S转换为任何数组类型。 如果T是最终类且未实现接口J,则J到T除字符串转换外禁止任何转换。 如果接口J和K含有同基调但不同返回类型的方法,则禁止J转换为K。 任何数组类型除转换为Object或String外,禁止转换为其他类类型。 任何数组类型除转换为Serializable或Cloneable外,禁止转换为其他接口类型。 如果SC到TC除字符串转换外禁止其他转换,则禁止SC转换为TC。,隐式类型转换规则,最小要求 byte、short或char参与算术运算、位非运算或作为数组下标时,会自动放宽为int(但复合赋值+=、-=等运算则无需提升)。 以大为主 适用于算术运算、关系运算和逻辑运算等运算; byte short int long float double 以左为主 适用于赋值; 禁止丢失信息。 Java语言比其前辈C+语言更严格! C+允许将double赋值给int或float,丢失信息是程序员自己的事。,显式类型转换规则,假设area和length为int类型: area / length 显式类型转换: (double) area / length area / (double) length 不正确的做法:无法提高精度! (double) (area / length),涉及boolean的类型转换,boolean与其他基本数据类型之间不允许类型转换 这也意味着在所有控制语句中不允许以整型代替boolean作为判断条件。 例如: int i = (int) true; / 编译程序报错 boolean b = (boolean) A; / 编译程序报错 非类型转换的转换方法: 将整数x转换为逻辑值: (x != 0) 将引用r转换为逻辑值: (r != null) 将布尔值b转换为字符串: (“ + b),一个例子程序,/ 计算某一学生数理化三科总分与平均分 public class Score public static void main(String args) int math = 92; / 数学成绩 int phys = 88; / 物理成绩 int chem = 95; / 化学成绩 int total; / 三科总分 int average; / 三科平均分 / 计算三科总分 total = math + phys + chem; / 计算三科平均分 average = total / 3; / 在屏幕上输出计算结果 System.out.println(“数理化三科总分为“ + total); System.out.println(“数理化三科平均分为“ + average); ,average = total / 3; 四舍五入: 做法一: float temp = (float) total / 3; average = (int) (temp + 0.5); 其他做法: float temp = total / 3.0F; float temp = total / (float) 3; float temp = (float) (total / 3.0); double temp = total / 3.0; 复合表达式: average = (int) (float) total / 3 + 0.5); 错误的做法: 做法一: float temp = (float) total / 3; average = (int) temp + 0.5; 做法二: float temp = total / 3.0; average = (int) (temp + 0.5);,3.6 简单的输入输出,将华氏温度F转换为相应摄氏温度C的公式: C = (F - 32) * 5 / 9,观察运算结果:最简单的输出方式,System.out.println(.) System.out.println(“长方形宽为“ + length); System.out.print(.) System.out.print(“长方形高为“); System.out.println(width); System.out.println(“长方形面积为“ + (length * width); 只在两个地方使用汉字:注释、字符串常量,最简单的程序,/ 将华氏温度转换为摄氏温度 public class Temperature public static void main(String args) System.out.print(“今天的气温是摄氏“); System.out.print(81.25 - 32) * 5 / 9); System.out.println(“度。“); ,为程序引入变量,/ 将华氏温度转换为摄氏温度 public class Temperature public static void main(String args) float fah; / 华氏温度 float cel; / 根据fah转换得到的摄氏温度 / 确定华氏温度fah fah = (float) 81.25; / 根据华氏温度fah计算摄氏温度cel cel = (fah - 32) * 5 / 9; / 输出转换得到的摄氏温度cel System.out.println(“今天气温为摄氏“ +

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论