HIT-SC-Chapter Four
目录
HIT-SC-Chapter Four
Data Type and Type Checking 数据类型与类型检验
1 Data type in programming languages
(1)Types and Variables for general computer language
通用计算机语言的类型和变量
-
数据类型:
- 一组值
- 一组操作
-
变量
- 存储一种特定类型值的某个位置的命名
- Example: String foo
- 用特定数据类型定义,可存储满足类型约束的值
(2) Types in Java
- 基本数据类型
int
long
boolean
double
char
- 对象数据类型
- String
- BigInteger
- 基本数据类型小写,对象数据类型大写
(3) Object Types
- 层次结构:
- 根是Object(所有非基本数据类型都是对象类型)
- 除Object外的所有类都有一个父类,用extends子句指定
- 单亲继承
- 如果省略extends子句,默认为Object
- 一个类是它所有超类的一个实例--继承关系
- 从其超类继承可见字段和方法
- 可以重写方法以更改其行为 Override
- Boxed primitives
- 将基本类型包装成对象类型
- 例如:
- Boolean\Integer\Short\Long\Character\Float\Doubble
- 通常是在定义集合类型时使用
- 一般情况下,尽量避免使用
- 一般可以自动转换
(4) Operators
- 执行简单计算的符号
- = + - * /
- 遵循标准的数学规则
- 字符串连接(+)
(5) Operations
- 接受输入并产生输出的函数(有时本身也会更改值)
- 作为前缀、中缀和后缀操作符
- 作为对象的方法。
- 作为一个类函数。例如:
Math.sin()
- 在这里,
Math
不是一个对象。它是包含sin
的类。
- 在这里,
- Overloading operators/operations 重载
- 同样的操作名用不同的数据类型
- 在Java中,算术操作符+、-、*、/被大量重载于数字基本类型。
- 方法也可以重载。大多数编程语言都有一定程度的重载。
- (将在3.3节OOP中讨论)
2 Static vs. dynamic data type checking
- 类型转换
- 被赋予了不合法的数据类型
- 范围大的可以赋予范围小的
- 范围小的不能赋予范围大的
(1) Static Typing vs. Dynamic Typing
静态类型与动态类型
- Java是一种静态类型的语言。
- 所有变量的类型都是在编译时(在程序运行之前)知道的,因此编译器也可以推断出所有表达式的类型。
- 如果a和b被声明为int类型,那么编译器会得出a+b也是int类型的结论。
- 实际上,Eclipse环境会在您编写代码时执行此操作,因此您可以在输入时发现许多错误。(静态检查)
- 在编译时进行类型检查
- 在像Python这样的动态类型语言中,这种检查被延迟到运行时(当程序运行时)。
(2) Static Checking and Dynamic Checking
- three kinds
- Static checking: the bug is found automatically before the program even
runs. - Dynamic checking: the bug is found automatically when the code is
executed. - No checking: the language doesn’t help you find the error at all. You have
to watch for it yourself, or end up with wrong answers.
- Static checking: the bug is found automatically before the program even
(3) Static checking
- Mismatched Types
- ( 赋值语句的左右必须类型完 全一致!)
- 静态检查意味着在编译时检查bugs。
- 静态类型检查:可在编译阶段发现错误,避免了将错误带入到运行阶段,可提高程序正
确性/健壮性。
- 静态类型检查:可在编译阶段发现错误,避免了将错误带入到运行阶段,可提高程序正
- 检查错误:
- 将操作应用于错误类型的参数所导致的错误
- 语法错误
- 比如额外的标点符号或虚假的单词。即使像Python这样的动态类型语言也会进
行这种静态检查。
- 比如额外的标点符号或虚假的单词。即使像Python这样的动态类型语言也会进
- 类名/函数名错误
like Math.sine(2)
- 参数数目错误
- 参数类型错误
- 返回值类型错误
(4) Dynamic checking
- 非法的参数值
- 例如,只有当y实际上为零时,整数表达式x/y才会出错;否则它的工作原理。在这个表达式中,除以零不是静态误差,而是动态误差。
- 非法返回值
- 越界
- 空指针
(5) Static vs. Dynamic Checking
- 静态检查往往是关于与变量的特定值无关的类型和错误
- 静态类型保证一个变量将具有该集合中的某些值,但直到运行时我们才确切知道它具有哪个值。
- ?
- 因此,如果错误只会由某些值引起,比如除以零或超出范围,那么编译器将不会引发关于它的静态错误。
- 相反,动态检查往往是关于由特定值引起的错误。
- 即 关于“类型”的检查《--》关于值的检查
3 Mutability and Immutability
(1) 赋值
-
在计算机中,赋值是最难得问题之一,它相当于将一个计算结果放到一个存储空间中,是一个存储的过程。
-
String foo; foo = "JSX LOVE JJY"
-
-
赋值可以与变量声明结合使用
-
double badPi = 3.14; boolean isJanuary = true;
-
(2) Changing a variable or its value
改变一个变量、改变一个变量的值,有何区别
- 改变一个变量:将该变量指向另一个值的存储空间。
- 改变一个变量的值:将该变量当前指向的值的存储空间写入一个新的值。
(3) Immutability 不变性
-
不变性:重要设计原则
-
不变数据类型
- 类型的值一旦创建就永远不能更改。
-
引用类型的不变:一旦确定其指向的对象,就不能再被改变
- 要使引用不可变,请使用关键字final声明它
- 如果编译器无法确定final变量不会改变,就提示错误---静态类型检查
- 使用
final
变量尽量作为方法的输入参数和局部变量 - Note:
- final类无法派生子类
- final变量无法改变值/引用
- final方法无法被子类重写
-
对象的不变性:
- 对象是不可变的:一旦创建,它们总是指向同一个值/引用。
- 可变对象:拥有方法可以修改自己的值/引用
-
String
-
StringBuilder
-
千万不要用Date !
- 使用java包中的一个类。time: LocalDateTime, Instant等。
- 所有这些都在它们的规范中保证它们是不可变的
-
the risk
- 别名是使可变类型有风险的原因
- 安全地使用可变类型:局部变量,不涉及共享;只有一个引用
- 多个引用,就变得不安全
- 别名是使可变类型有风险的原因
-
How to Modify the code?
- 要返回对象的新副本(防御复制)–防御性拷贝
- 大量内存浪费
- 如果我们使用不可变类型,那么程序的不同部分可以安全地共享内存中的相同值,因此复制更少,所需的内存空间也更少。
- 要返回对象的新副本(防御复制)–防御性拷贝
4 Snapshot diagram as a code-level, run-time, and
moment view
(1) Snapshot diagrams
-
为了理解微妙的问题,画出运行时发生的事情的图对我们来说是很有用的。
-
用于描述程序运行时的内部状态
(2) 快照图中的基本类型和对象类型
-
Primitive values 由裸常量表示。传入的箭头是对变量或对象字段值的引用。
-
Object values是由其类型标记的圆。
- 当我们想要显示更多的细节时,我们将字段名写入其中,并用箭头指出它们的值。更详细的信息是,字段可以包含它们声明的类型。
(3) Reassignment and immutable values
- 不可变对象(设计者希望它们总是表示相同的值)在快照图中用双线椭圆表示,就像我们图中的String对象一样。
(4) Mutable values
(5) 不可变的引用
- 在快照图中,不可重新分配的引用(final)由双箭头表示。
- 引用是不可变的,但值是可变的
- 可变的引用也可指向不可变的值
5 Complex data types: Arrays and Collections
(1)Arrays
- 数组是另一种类型t的固定长度序列
- 包含所有可能的数组值,但特定的数组值一旦创建,就永远不能改变其长度。
- 操作
- indexing:
- assignment:
- length: a.length
(2)List
- 列表是另一种类型T的变长序列。
- 操作:
- list.get
- list.set(2,0)
- list.size()
- List is an interface.
- members in a List must be an object.
- Please use List rather than arrays
(3) Set
- Set是零个或多个唯一对象的无序集合。
- 一个对象不能多次出现在集合中。
- 操作:
- s1.contain()
- s1.containAll()
- s1.removeAll()
- Set是一个抽象接口
(4) Map
- A Map is similar to a dictionary (key-value) 类似字典:键-值
- Map is an abstract interface 抽象接口
- map.put()
- map.get()
- map.containsKey()
- map.remove()
- 声明List、Set和Map变量
- 使用Java集合,我们可以限制集合中包含的对象的类型。
- 添加项时,编译器可以执行静态检查,以确保只添加适当类型的项
- 然后,当我们取出一个项时,就可以保证它的类型是我们所期望的。
- 只能是引用类型:不能创建基本类型的集合
- 创建List、Set和Map变量
- 抽象接口needs Concrete Class The implementation
- 它们定义了这些各自的类型如何工作,但它们不提供实现代码。
- List: ArrayList and LinkedList
- Set: HashSet
- Map: HashMap
- 使用List, Set和Map变量
(3) 迭代器
-
-
迭代器是一个逐步遍历元素集合并逐个返回元素的对象。
-
在Java中,当你使用for(…:)循环遍历List或数组
- iterator.next()
- iterator.hasNext()
-
突变破坏迭代器
-
-
-
-
for不能删除
-
6 Useful immutable types
- 基本类型和封装对象类型都是不可变的
- 如果需要使用较大的数字进行计算,BigInteger和BigDecimal是不可变的。
- 不要使用可变的
Date
,根据所需的时间粒度使用适当的不可变类型。 - Java集合类型的通常实现是可变的
- Collections实用工具类具有获取这些可变集合的不可修改视图的方法:
- Collections.unmodifiableList
- Collections.unmodifiableSet
- Collections.unmodifiableMap
- Collections实用工具类具有获取这些可变集合的不可修改视图的方法:
(1)围绕可变数据类型的不可变包装器
-
得到的结果是不可变的,只能看;
-
缺点是在运行时获得了不可变性,而不是在编译时。无法据此进行静态检查。
-
但这总比没有好,所以使用不可修改的列表、映射和集合是减少bug风险的好方法。
-
-
不可修改的包装器通过拦截所有会修改集合的操作并抛出UnsupportedOperationException,从而剥夺了修改集合的能力。
-
不可修改的包装有以下两种主要用途:
- 使集合在构建后成为不可变的。在这种情况下,最好不要维护对后台集合的引用。这绝对保证了永恒性。
-
-
SUM
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理