PDF 课件和源代码下载地址:
https://gitee.com/geektime-geekbang/LetsJava
作者回复: 接口的定义是对问题的抽象,并非是迁就于实现的。 就好像最常见的USB接口,提供了数据传输的功能,同时也提供了供电的功能。但是它并没有要求每个USB设备都必须同时用到所有的它提供的功能。 一个USB小风扇,使用供电的功能就够了。不能强求它说这个接口是USB的,不传输点数据就是白用USB了。接上USB,能供电,风扇可以转,这就已经实现了这个USB设备的应有的功能了。没有什么白不白的。因为这个接口,不是为了一个设备设计的。改天插上U盘,就用得上数据传输的功能了。 如果专门在电脑上设计一个仅供充电的USB口,一个仅供数据传输的USB口,一个既能充电又能传输数据的USB口。不是不可以,但是没必要。 最后一个题外话。问问题,一个问号和两个问号,没有什么不一样。我发现你问的问题,都是俩问号。那第二个问号,才是真的白输入了哦亲。
作者回复: 编程行有个名词叫做“保护性编程”。意思就是,要假设别人会犯错,当然,自己也会犯错。 比如上面的代码。只有在customer instanceof AbsCustomer的情况下,maxTypeToBuy才会被赋值。 或者纵观例程里现有的所有代码,给maxTypeToBuy 赋值 MAX_BUY_DEFAULT都是白费。因为都会在别的地方给覆盖掉。 但是保护性编程的理念是,无论现在代码是什么样子,我要在当时当下,当行代码,尽力做到万无一失。 来跟我重复一遍:尽力做到万无一失 maxTypeToBuy对于程序来说是相当重要的一个变量。它直接控制了后面程序会不会运行。如果maxTypeToBuy在某些情况下(可能是未来,可能是bug),没有被赋值,那么maxTypeToBuy的值将会是0。后面所有购买的情况也就不会发生了。 同学其实你很多问题都是站在“面对当下编程”的角度看代码。接口里有个参数用不到,某个赋值是“白赋值了”,都是这种想法造成的。 多写代码,多看代码,找到感觉之后你就会知道为什么需要“保护性编程”,“面向接口编程”,因为人都会犯错误,因为人的想法总会变化。如果“面对当下编程”,程序的灵活性和健壮性会很不足。代码里一个疏忽,程序可能就不能正常运转了;小小的一个需求变化,可能会需要代码从头到尾改一遍。
作者回复: 就这个例子来说,没区别。 但是构造方法的好处是,实例一开始goShoppingLeftCount就会有一个合法的值,而不会是缺省值0。这是唯一的区别,类似你买家具,构造方法是装好给你运到家(构造方法初始化),在别的方法里初始化,就是宜家这种风格,你自己动手组装家具(自己初始化)。 不好的地方就是,在你自己组装之好之前,这个家具(对象)是不能用的。
作者回复: 字面值是literal value。只有基本数据类型和string才有。 final只是不可变值。用它是这个变量的值确实不需要变化。 写独立完整的程序确实需要心中有对整个系统的把控和理解。调api和写完整的程序,就像装修和盖楼的区别,都有各自的场景,面对的问题不同,解决方式也就不一样了。
作者回复: 枚举的实例只有五个,但是我可以创建一个随意大小的枚举引用类型的数组,然后里面可以有引用指向同一个枚举的实例。
作者回复: 假设Merchandise是接口。 这里是定义了一个接口的引用的数组。将来这些接口的引用,可以指向任何一个实现了这个接口的类的实例。 就好像: Merchandise m1 = null; Merchandise m2 = null; .... m1 = new Phone(); m2 = new 任意实现了Merchandise接口的类。
作者回复: 如果是当前类的或父类的静态方法,可以不用写类名。 后面还会讲到import static,也可以省略类名。
作者回复: 哈哈,可
作者回复: 嗯呐,类,抽象类,接口,都是类型。一个文件里可以定义多个类型,IDE可以将类型都显示出来
作者回复: 和语法无关的代码有没有用的问题,你觉得它没有用,那就是没有用。这个没有什么标准或者准则。 比如说这里,如果调试代码的时候把它的值输出出来,那就有用了。 比如如果要检查是不是买得起,可能就有用了。