软件构造第三章1

第3章:抽象数据类型(ADT)和面向对象编程(OOP)3.1数据类型和类型检查
3.1数据类型和类型检查
大纲
1.编程语言中的数据类型2.静态与动态数据类型3.类型检查4.可变性和不变性5.快照图6.复杂数据类型:数组和集合7.有用的不可变类型8.空引用9.总结
3.1数据类型和类型检查
本讲座的目的
1.了解有关数据类型的基本知识,以及编程语言中的静态和动态类型检查,尤其是Java。 2.理解可变性和可变对象3.识别别名并理解可变性的危险性4.使用不变性来提高正确性,清晰度和可变性5.使用快照图来演示程序执行期间的特定时间状态。 6.使用数组和集合来处理复杂的数据类型7.了解Null引用的危害并避免它
软件构建
1编程语言中的数据类型
3.1数据类型和类型检查
类型和变量
Atype是一组值,以及可以对这些值执行的操作。 示例: - 布尔值:真值(true或false)。 - int:Integer(0,1,-47)。 - double:实数(3.14,1.0,-2.1)。 - 字符串:文本(“hello”,“example”)。 变量:存储一种特定类型值的命名位置 - 表格:TYPENAME; - 示例:Stringfoo;
3.1数据类型和类型检查
Java中的类型
Java有几种原始类型,其中包括: - int(对于整数,如5和-200,但限于范围±2 ^ 31,或大约±20亿) - 长(对于大于±2 ^ 63的较大整数) - boolean(对于true或false) - double(对于浮点数,表示实数的子集) - char(对于单个字符,如’A’和’$’)Java也有对象类型,例如: - String表示一系列字符。 - BigInteger表示任意大小的整数。 按照Java惯例,基本类型是小写的,而对象类型以大写字母开头。
3.1数据类型和类型检查
Java中的类型
基元对象引用类型int,long,byte,short,char,float,double,boolean类,接口,数组,枚举,注释除了它们的值之外没有任何标识具有与值不同的标识不可变一些可变的,一些不是在堆栈上,仅在存在时存在在使用堆上,垃圾收集无法实现统一表达统一表达与泛型污垢便宜更昂贵
3.1数据类型和类型检查
对象类型的层次结构
根是Object(所有非基元都是对象) - 除了Object之外的所有类都有一个父类,用extends子句类指定Guitar扩展Instrument {…}如果省略extendsclause,则默认为Object类是一个实例其所有超类 - 从其超类继承可见字段和方法 - 可以覆盖方法以更改其行为
3.1数据类型和类型检查
盒装基元
原始类型的不可变容器 - 布尔,整数,短,长,字符,浮点,双除非必须,否则不要使用盒装基元! 语言执行自动装箱和自动拆箱运营商
运算符:执行简单计算的符号 - 赋值:= - 加法:+ - 减法: - 乘法:* - 除法:/操作顺序:遵循标准数学规则: - 1.括号 - 2.乘法和除法 - 3。加法和减法字符串连接(+) - 字符串文本=“你好”+“世界”; - text = text +“number”+ 5; // text =“hello world number 5”
3.1数据类型和类型检查
操作
操作是接受输入和产生输出的功能(有时会更改值本身)。 - 作为中缀,前缀或后缀运算符。例如,a + b调用操作+:int×int→int。 - 作为对象的方法。例如,bigint1.add(bigint2)调用操作add:BigInteger×BigInteger→BigInteger。 - 作为一种功能。例如,Math.sin(theta)调用操作sin:double→double。在这里,马西斯不是一个对象。它是包含sinfunction的类。
3.1数据类型和类型检查重载操作符/操作
某些操作过载,因为相同的操作名称用于不同的类型。 算术运算符+, - ,,/对Java中的数字基元类型进行了大量重载。 方法也可能超载。大多数编程语言都有一定程度的重载。
(将在第3.3节OOP中讨论)
软件构建
2静态与动态数据类型
3.1数据类型和类型检查
静态打字与动态打字
Java是一种静态类型的语言。 - 所有变量的类型在编译时(程序运行之前)都是已知的,因此编译器也可以推导出所有表达式的类型。 - 如果a和bare声明为int,则编译器断定a + bis也是int。 - 事实上,Eclipse环境在您编写代码时执行此操作,因此您在键入时会发现许多错误。 在像Python这样的动态类型语言中,这种检查会延迟到运行时(程序运行时)。
软件构建
3键入检查
3.1数据类型和类型检查静态检查和动态检查
语言可以提供的三种自动检查: - 静态检查:在程序运行之前自动发现错误。 - 动态检查:执行代码时会自动发现错误。 - 不检查:语言根本无法帮助您找到错误。你必须自己观察,或者得到错误的答案。
毋庸置疑,静态捕获错误比动态捕获它更好,动态捕获它比捕获它更好。
3.1数据类型和类型检查
不匹配的类型
Java验证类型是否始终匹配:
字符串五= 5; //错误!
test.java.2:找到不兼容的类型:int required:java.lang.String String five = 5;
3.1数据类型和类型检查
通过铸造转换
int a = 2; // a = 2 double a = 2; // a = 2.0(隐式)int a = 18.7; // ERROR int a =(int)18.7; // a = 18 double a = 2/3; // a = 0.0 double a =(double)2/3; // a = 0.6666 …
3.1数据类型和类型检查
静态检查
静态检查意味着在编译时检查错误。 错误是编程的祸根。 静态类型可防止大量错误感染您的程序:准确地说,将操作应用于错误类型的参数会导致错误。 如果你写了一行代码如下:“5”
“6”试图将两个字符串相乘,那么静态类型将在你编程时捕获这个错误,而不是等到执行期间到达该行。
3.1数据类型和类型检查
静态检查
语法错误,如额外的标点符号或虚假单词。即使像Python这样的动态类型语言也会进行这种静态检查。 错误的名称,如Math.sine(2)。 (正确的名字是罪)参数数量错误,如Math.sin(30,20)。 错误的参数类型,如Math.sin(“30”)。 错误的退货类型,如退货“30”;从声明为返回int的函数。
动态检查
非法参数值。例如,当yis实际为零时,整数表达式x / y只是错误的;否则它有效。所以在这个表达式中,除零不是静态错误,而是动态错误。 不可代表的返回值,即特定返回值无法在类型中表示的情况。 超出范围的索引,例如,对字符串使用负数或过大的索引。 在nullobject引用上调用方法。
3.1数据类型和类型检查
静态与动态检查
静态检查往往是关于类型,错误与变量具有的特定值无关。 - 静态类型保证变量将具有该集合的某些值,但我们直到运行时才知道它具有哪个值。 - 因此,如果错误仅由某些值引起,例如除零或索引超出范围,则编译器不会引发关于它的静态错误。 相反,动态检查往往是由特定值引起的错误。
3.1数据类型和类型检查原始类型不是真数
Java中的一个陷阱 - 以及许多其他编程语言 - 它的原始数字类型的边角情况不像我们习惯的整数和实数。 因此,根本不检查真正应该动态检查的一些错误。 - 整数除法:5/2不返回分数,它返回一个截断的整数。 - 整数溢出。如果计算结果太积极或太负而无法适应该有限范围,则它会安静地溢出并返回错误的答案。 (没有静态/动态检查!)例如,int big = 200000 * 200000; - 浮点类型中的特殊值。 NaN(“非数字”),POSITIVE_INFINITY和NEGATIVE_INFINITY。例如,double a = 7/0;
软件构建
4可变性和不变性
3.1数据类型和类型检查
分配
使用“=”为变量赋值示例: - String foo; - foo =“IAP 6.092”;
赋值可以与变量声明组合例如: - double badPi = 3.14; - boolean isJanuary = true;
3.1数据类型和类型检查
更改变量或其值
更改变量和更改值之间的区别是什么? - 分配给变量时,您将更改变量箭头指向的位置。您可以将其指向不同的值。 - 当您分配可变值的内容时 - 例如数组或列表 - 您正在更改该值内的引用。 改变是必要的罪恶。 优秀的程序员避免改变的事情,因为他们可能会意外地改变。
3.1数据类型和类型检查
不变性
不变性是一项主要的设计原则。 不可变类型是一种类型,其值一旦创建就永远不会改变。 - Java还为我们提供了不可变引用:分配一次但从未重新分配的变量。 要使引用不可变,请使用关键字final:final int n = 5声明它; 如果Java编译器不确定您的最终变量将仅在运行时分配一次,那么它将产生编译器错误。所以最后给你静态检查不可变引用。
3.1数据类型和类型检查
不变性
最好使用final来声明方法的参数和尽可能多的局部变量。 与变量的类型一样,这些声明是重要的文档,对代码的读者很有用,并且由编译器进行静态检查。
注意: - finalclass声明意味着它不能被继承。 - 最终变量表示它始终包含相同的值/参考但不能更改; - final方法意味着它不能被子类覆盖;
3.1数据类型和类型检查
可变性和不变性
对象可以更改:一旦创建,它们总是表示相同的值。 对象是可变的:它们具有改变对象值的方法。
3.1数据类型和类型检查
字符串作为不可变类型
Btring是不可变类型的示例。 Stringobject始终表示相同的字符串。 由于Stringis不可变,因此一旦创建,Stringobject总是具有相同的值。 要在String的末尾添加内容,您必须创建一个新的Stringobject:
注意:这是一张快照图
StringBuilder是一个可变类型
StringBuilder是一个可变类型的例子。 它有删除字符串部分,插入或替换字符等的方法.该类具有更改对象值的方法,而不仅仅是返回新值:
3.1数据类型和类型检查
可变性和不变性
那又怎样?在这两种情况下,你最终都会将沙子破坏为字符串“ab”。 - 当只有一个对象的引用时,可变性和不变性之间的区别并不重要。 但是当存在对象的其他引用时,它们的行为方式存在很大差异。 - 例如,当另一个变量指向与s相同的Stringobject,而另一个变量指向同一个StringBuilderas sb时,则不可变对象和可变对象之间的差异变得更加明显。
3.1数据类型和类型检查
可变类型的优点
使用不可变字符串,这会产生大量临时副本 - 字符串的第一个数字(“0”)实际上是在构建最终字符串的过程中复制n次,第二个数字被复制n-1次,所以上。 StringBuilder旨在最大限度地减少此复制。 - 它使用一个简单但聪明的内部数据结构,以避免进行任何复制,直到最后,当你通过toString()调用请求finalString时:
3.1数据类型和类型检查
可变类型的优点
获得良好的性能是我们使用可变对象的一个​​原因。 另一个是方便共享:程序的两个部分可以通过共享一个共同的可变数据结构更方便地进行通信。 “全局变量”
但你必须知道全局变量的缺点…
3.1数据类型和类型检查
突变的风险
由于可变类型似乎比不可变类型更强大,为什么你会选择不可变类型呢? - StringBuilders应该能够完成Stringcan所做的一切,加上set()和append()以及其他一切。 答案是不可变类型更容易出错,更容易理解,更容易做出改变。 - 可变性使您更难理解您的计划正在做什么,并且更难以执行合同。
性能与安全之间的权衡?
3.1数据类型和类型检查危险的例子#1:传递可变值
直接改变列表以获得更好的性能
但是,这会发生什么?
3.1数据类型和类型检查
风险
安全的bug? - 在这个例子中,很容易将sumAbsolute()的实现者归咎于超出其规范所允许的范围。 - 但实际上,传递可变对象是一个潜在的错误。它只是在等待一些程序员无意中改变该列表,通常具有非常好的意图,如重用或性能,但导致可能很难追踪的错误。 易于理解? - 当读取main()时,你会对sum()和sumAbsolute()有什么看法? - 读者是否清楚地看到myDatagets被其中一个改变了?
3.1数据类型和类型检查危险的例子#2:返回可变值
作为内置Java类的Dateas是一种可变类型。
这会发生什么?
3.1数据类型和类型检查
风险
在这两个示例中 - List 和Date - 如果list和datehad是不可变类型,则可以完全避免问题。 设计中的错误是不可能的。 你永远不应该使用日期! - 使用java.time包中的一个类:LocalDateTime,Instant等。 - 在规范中都保证它们是不可变的。如何修改代码?
在示例1中: - 返回对象的新副本(防御性复制),即返回新日期(groundhogAnswer.getTime()); - 但是,使用额外空间的forevery客户端 - 即使99%的客户从不改变它返回的日期。在整个记忆中,我们最终可能会有春天第一天的大量副本。 如果我们使用不可变类型,那么程序的不同部分可以安全地在内存中共享相同的值,因此需要更少的复制和更少的内存空间。 不变性可以比可变性更有效,因为不可变类型永远不需要被防御性地复制。
3.1数据类型和类型检查别名是使可变类型有风险的原因
如果你在一个方法中完全在本地使用它们,并且只使用一个对象的引用,那么使用可变对象就可以了。 导致我们刚刚看到的两个示例中的问题的原因是对同一个可变对象有多个引用,也称为候选。 - 在Listexample中,列表(在sumand sumAbsolute中)和myData(在main中)指向相同的列表。一个程序员(sumAbsolute’s)认为可以修改列表;另一个程序员(主要的)希望列表保持不变。由于别名,main的程序员输了。 - 在Dateexample中,有两个变量名称指向Date对象,groundhogAnswerand partyDate。这些别名在代码的完全不同的部分,在不同的程序员的控制下,他们可能不知道对方在做什么。
3.1数据类型和类型检查更多防御性复制示例
3.1数据类型和类型检查更多防御性复制示例
软件构建
5快照图作为代码级,运行时和时刻视图
3.1数据类型和类型检查软件构造:转换btw视图
建造时间
运行
片刻期
时刻


零件
代码流失
CI和版本
代码快照
物理架构
调用图
线程和进程
程序设计
设计
构建安装部署
重构
版本控制
演化
部署
审查,静态分析
调试测试
剖析,倾销
记录
3.1数据类型和类型检查
快照图
为了理解微妙的问题,我们可以在运行时绘制正在发生的事情的图片。 快照图表示运行时程序的内部状态 - 堆栈(正在进行的方法及其局部变量)及其堆(当前存在的对象)。 为什么我们使用快照图? - 通过图片互相交谈。 - 说明原始类型与对象类型,不可变值与不可变引用,指针别名,堆栈与堆,抽象与具体表示等概念。 - 帮助解释您的团队项目的设计(彼此之间以及与您的TA一起)。 - 为后续课程中更丰富的设计符号铺平道路。
3.1数据类型和类型检查变异值与重新分配变量
快照图为我们提供了一种可视化更改变量和更改值之间区别的方法: - 当您指定给变量或字段时,您将更改变量箭头指向的位置。您可以将其指向不同的值。 - 当您分配可变值的内容时 - 例如数组或列表 - 您正在更改该值内的引用。
3.1数据类型和类型检查快照图中的原始值和对象值
原始值 - 原始值由裸常量表示。传入箭头是对变量或对象字段中的值的引用。
对象值 - 对象值是由其类型标记的圆圈。当我们想要显示更多细节时,我们在其中写入字段名称,箭头指向它们的值。有关更多详细信息,字段可以包括其声明的类型。有些人喜欢写x:int而不是int x,但两者都很好。
3.1数据类型和类型检查重新分配和不可变值
例如,如果我们有一个String变量s,我们可以将它从值“a”重新分配给“ab”。 String s =“a”; s = s +“b”; Btring是一个不可变类型的示例,一种类型,其值一旦创建就永远不会改变。 不可变对象(设计者希望它们始终表示相同的值)在快照图中用双边框表示,如图中的Stringobjects。可变值
相比之下,StringBuilder(一个内置的Java类)是一个可变对象,它表示一个字符串,它有一些方法可以改变对象的值:StringBuilder sb = new StringBuilder(“a”); sb.append( “B”); 这两个快照图看起来非常不同,这很好:可变性和不变性之间的区别将在使代码免受错误攻击方面发挥重要作用。
3.1数据类型和类型检查
不可改变的参考
Java还为我们提供了不可变引用:分配一次且永不重新分配的变量。要使引用不可变,请使用关键字final:final int n = 5声明它; 如果Java编译器不确定您的最终变量将仅在运行时分配一次,那么它将产生编译器错误。所以final给出了对不可变引用的静态检查。 在快照图中,不可变引用(final)由双箭头表示。
3.1数据类型和类型检查
不可改变的参考
这是一个idnever随时更改的对象(不能重新分配给不同的数字),但其年龄可能会发生变化。
我们可以对可变值进行不可变引用(例如:final StringBuilder sb),即使我们指向同一个对象,其值也可以更改。 我们也可以对不可变值(如字符串)进行可变引用,其中变量的值可以更改,因为它可以重新指向不同的对象。
软件构建
6复杂数据类型:数组和集合
3.1数据类型和类型检查
排列
数组是另一种类型T的固定长度序列。例如,这里是如何声明一个数组变量并构造一个数组值来赋值给它:int [] a = new int [100]; int[]数组类型包括所有可能的数组值,但特定的数组值一旦创建,就永远不会改变其长度。 对数组类型的操作包括: - 索引:a [2] - 赋值:a [2] = 0 - length:a.length int [] a = new int [100]; int i = 0; int n = 3; while(n!= 1){a [i] = n;我++; if(n%2 == 0){n = n / 2; } else {n = 3 * n + 1; a [i] = n;我++;
3.1数据类型和类型检查
名单
使用Listtype,而不是固定长度的数组。 列表是另一种类型T的可变长度序列。列表 list = new ArrayList (); 它的一些操作: - 索引:list.get(2) - 赋值:list.set(2,0) - length:list.size()注1:Listis是一个接口注2:List中的成员必须是一个东西。 List list = new ArrayList (); int n = 3; while(n!= 1){list.add(n); if(n%2 == 0){n = n / 2; } else {n = 3 * n + 1; list.add(n);
3.1数据类型和类型检查
迭代
迭代数组int max = 0; for(int i = 0; i <array.length; i ++){max = Math.max(array [i],max); }
迭代列表int max = 0; for(int x:list){max = Math.max(x,max); }
3.1数据类型和类型检查

Setis是零个或多个唯一对象的无序集合。 对象不能多次出现在集合中。无论是在它还是在它外面。 - s1.contains(e)测试集合是否包含一个元素 - s1.containsAll(s2)测试是否s1⊇s2 - s1.removeAll(s2)从s1中删除s2Setis是一个抽象接口
3.1数据类型和类型检查
地图
一个类似于字典的Mapis(键值) - map.put(key,val)添加映射键→val - map.get(key)获取一个键的值 - map.containsKey(key)测试是否map有一个键 - map.remove(key)删除一个映射Mapis一个抽象的接口
3.1数据类型和类型检查
从Array构建列表
Arrays.asList(new String [] {“a”,“b”,“c”})声明List,Set和Mapvariables
使用Java集合,我们可以限制集合中包含的对象类型。 当我们添加项目时,编译器可以执行静态检查以确保我们只添加相应类型的项目。 然后,当我们拿出一件商品时,我们保证其类型将符合我们的预期。
3.1数据类型和类型检查声明List,Set和Mapvariables
声明:列出城市; //一个字符串列表设置<整数>数字; //一组整数Map <String,Turtle> turtles; //带有字符串键和Turtle值的Map我们无法创建基本类型的集合。 - 例如,Set 不起作用。 - 但是,我们可以使用整数包装器(例如Set 数字)。 - 使用时:sequence.add(5); //在序列中添加5 int second = sequence.get(1); //得到第二个元素
3.1数据类型和类型检查创建列表,集和映射变量
Java有助于区分 - 类型的规范 - 它做什么?抽象接口 - 实现 - 代码是什么?具体类列出,设置和映射所有接口: - 它们定义这些相应类型的工作方式,但它们不提供实现代码。 - 优势:用户有权在不同情况下选择不同的实施方案。 列表,集合和映射的实现: - List:ArrayList和LinkedList - Set:HashSet - Map:HashMap List firstNames = new ArrayList (); List lastNames = new LinkedList (); List firstNames = new ArrayList <>(); List lastNames = new LinkedList <>();设置 numbers = new HashSet <>(); Map <String,Turtle> turtles = new HashMap <>();
3.1数据类型和类型检查
迭代
List cities = new ArrayList <>();设置 numbers = new HashSet <>(); Map <String,Turtle> turtles = new HashMap <>();
for(String city:cities){System.out.println(city); }
for(int num:numbers){System.out.println(num); }
for(int ii = 0; ii <cities.size(); ii ++){System.out.println(cities.get(ii)); }
for(String key:turtles.keySet()){System.out.println(key +“:”+ turtles.get(key)); }
3.1数据类型和类型检查
迭代器作为可变类型
Iterator是一个逐步遍历元素集合并逐个返回元素的对象。 当你使用for(…:…)循环来逐步通过Listor数组时,迭代器在Java的封面下使用。
迭代器有两种方法: - next()返回集合中的下一个元素—这是一个mutator方法! - hasNext()测试迭代器是否已到达集合的末尾。
3.1数据类型和类型检查ArrayList 的示例迭代器
类定义
实例变量
不变
规格
构造函数
实例方法
3.1数据类型和类型检查
MyIterator的快照图
3.1数据类型和类型检查
变异破坏了迭代器
假设我们有一个表示为字符串的主题列表。我们想要一个方法dropCourse6,它将从列表中删除Course 6主题,留下其他主题。 首先编写规范(将在下一讲中介绍)
接下来,编写测试用例(将在第7章中研究)
3.1数据类型和类型检查
变异破坏了迭代器
实施:
运行它
如何修复?
为什么?
软件构建
7有用的不可变类型
3.1数据类型和类型检查
有用的不可变类型
原始类型和原始包装器都是不可变的。如果你需要用大数字计算,BigIntegerand BigDecimalare是不可变的。 不要使用可变日期,根据您需要的计时粒度,使用java.time中相应的不可变类型。 Java的集合类型-List,Set,Map的常规实现都是可变的:ArrayList,HashMap等.Collections实用程序类具有获取这些可变集合的不可修改视图的方法: - Collections.unmodifiableList - Collections.unmodifiableSet - 集合.unmodifiableMap底层列表/ set / map的包装器不可修改的包装
不可修改的包装器通过拦截将修改集合并抛出UnsupportedOperationException的所有操作来消除修改集合的能力。 不可修改的包装器有两个主要用途,如下所示: - 在构建集合后使集合不可变。在这种情况下,最好不要维护对支持集合的引用。这绝对保证了不变性。 - 允许某些客户端以只读方式访问您的数据结构。您保留对支持集合的引用,但分发对包装器的引用。通过这种方式,客户可以查看但不能修改,同时保持完全访问权限。
3.1数据类型和类型检查
不可修改的包装
publicstatic Collection unmodifiableCollection(Collection <?extends T> c); publicstatic Set unmodifiableSet(Set <?extends T> s); publicstatic List unmodifiableList(List <?extends T> list); 公共静态<K,V> Map <K,V> unmodifiableMap(Map <?extends K,?extends V> m); publicstatic SortedSet unmodifiableSortedSet(SortedSet <?extends T> s); publicstatic <K,V> SortedMap <K,V> unmodifiableSortedMap(SortedMap <K,?extends V> m);
软件构建
8个无效参考
3.1数据类型和类型检查
Nullreferences
在Java中,对对象和数组的引用也可以采用特殊的valueNull,这意味着引用不指向对象。 Nullvalues是Java类型系统中不幸的漏洞。 原语不能为空,编译器将拒绝这些静态错误的尝试:int size = null; //非法可以为任何非原始变量赋值null,编译器在编译时愉快地接受此代码。但是你会在运行时遇到错误,因为你不能调用任何方法或使用带有这些引用之一的任何字段(throwsNullPointerExceptions):String name = null; name.length(); int [] points = null; points.length; nullis与空字符串“”或空数组不同。
3.1数据类型和类型检查
Nullreferences
像Listmight这样的非基元和集合的数组是非空的但是包含nullas值一旦有人试图使用集合的内容,这些空值很可能会导致错误。
空值很麻烦且不安全,因此建议您将它们从设计词汇表中删除。 参数和返回值中隐式禁止空值。
3.1数据类型和类型检查
来自Guava(谷歌)
“不小心使用null会导致各种各样的错误。通过研究Google代码库,我们发现类似95%的集合不应该在其中包含任何空值,并且快速失败而不是静默接受null会对开发人员有所帮助。“
“另外,null是令人不快的模棱两可。很明显,null返回值应该是什么意思 - 例如,Map.get(key)可以返回null,因为map中的值为null,或者值不在map中。 Null可能意味着失败,可能意味着成功,可能意味着几乎任何事情。使用null以外的东西可以使你的意思清晰。“
软件构建
摘要
3.1数据类型和类型检查
本讲座摘要
静态类型检查: - 来自bugs的安全。静态检查通过在运行时捕获类型错误和其他错误来帮助安全。 - 易于理解。它有助于理解,因为类型在代码中明确说明。 - 准备好进行更改。通过识别需要同时更改的其他位置,静态检查可以更轻松地更改代码。例如,当您更改变量的名称或类型时,编译器会立即在使用该变量的所有位置显示错误,并提醒您也要更新它们。摘要
可变性对于性能和便利性很有用,但它也会通过要求使用对象的代码在全局级别上表现良好而产生错误风险,这使我们必须做的推理和测试变得非常复杂,以确保其正确性。 确保您了解不可变对象(如String)和不可变引用(如最终变量)之间的区别。 快照图可以帮助您理解这一点。 - 对象是值,由快照图中的圆圈表示,而不可变对象具有双边框,表示它永远不会更改其值。 - 引用是指向对象的指针,由快照图中的箭头表示,不可变引用是带有双线的箭头,表示不能将箭头移动到指向其他对象。
3.1数据类型和类型检查
摘要
关键设计原则是可修改性:尽可能使用不可变对象和不可变引用。 - 安全免受错误。不可变对象不容易受到混叠引起的错误的影响。不可变引用总是指向同一个对象。 - 容易明白。因为不可变对象或引用总是意味着相同的东西,所以对于代码的读者来说更简单 - 他们不必遍历所有代码来查找可能更改对象或引用的所有位置,因为它无法改变。 - 准备好改变。如果在运行时无法更改对象或引用,则在程序更改时不必修改依赖于该对象或引用的代码。
软件构建
结束

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值